-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implicitNotFound
should allow type computation inside its pretty printer
#22392
Comments
And also please note that moving the import language.experimental.namedTuples
import NamedTuple.{NamedTuple, AnyNamedTuple}
type OnlyInts[T <: Tuple] = T match
case EmptyTuple => true
case Int *: ts => OnlyInts[ts]
case _ => false
@annotation.implicitNotFound("Types ${T} contain non-ints")
type IsOnlyInts[T <: Tuple] = OnlyInts[T] =:= true
def f[A <: AnyNamedTuple](using IsOnlyInts[NamedTuple.DropNames[A]]): Unit = ()
@main def main(): Unit = f[(a: Int, b: String, c: Int)] This produces: [error] -- [E172] Type Error: Main.scala:13:55
[error] 13 |@main def main(): Unit = f[(a: Int, b: String, c: Int)]
[error] | ^
[error] |Types NamedTupleDecomposition.DropNames[(a : Int, b : String, c : Int)] contain non-ints |
Checkout my implementation of |
@soronpo You could achieve arbitrary error messages with macros, but I believe this proposition
|
Famous last words. I don't think this is easy to implement at all. In fact, I don't think it's possible to reliably implement. You can't take a string representation of a type, put it in a different context, and somehow hope to be able to parse and typecheck it somewhere else. |
Previous use case at previous ticket #22367 (comment) There is an ancient Scala 2 ticket to improve implicitNotFound along these lines. Surely Scala 3 compiletime and inline facilities make it feasible. Maybe it must wait for the Great Collection Literal Syntax Debate of 2025 to subside. There are other issues with the annotation, when it appears on parent classes, so maybe it's an opportunity to re-design the feature. |
Compiler version
3.6.2
Minimized example
This is not a minimized example because the problem is simple and this better illustrates the benefits.
Say you are using implicits to perform some non-trivial compile-time verification of the input types. In that case, you probably are checking subcomponents of the input types, not only doing simple matches against the top-level types. In this toy example you check the shape of the values part of a named tuple.
You want to offer some helpful hints to the end-user of your library, and since the validation failed on some part inside of the top-level type, you want the error message to talk about this incorrect part only.
Output Error/Warning message
Why this Error/Warning was not helpful
What happened here is that the pretty printer inside
implicitNotFound
has interpreted the wholeNamedTuple.DropNames[A]
as a type variable name and, since it could not find it, it printed?
.Suggested improvement
To increase utility of annotations like
implicitNotFound
for explaining users what they should improve, the compiler should interpret expressions inside${}
as not only variables and normalize/simplify them before printing. What I would like to see here:The text was updated successfully, but these errors were encountered: