-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Support implicitNotFound on parameters #6340
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
Conversation
|
See also scala/collection-strawman#432 |
|
What happens in the following case? @implicitNotFound("BarError")
trait Bar
@implicitNotFound("FooError")
trait Foo
object Foo {
implicit def ev(implicit @implicitNotFound("BarParamError") bar : Bar) : Foo = ???
}
implicitly[Foo] |
|
It tells you With So it's picked up here as well. |
test/files/neg/t2462b.check
Outdated
| trait Meh2[-From, +To] | ||
| ^ | ||
| t2462b.scala:13: warning: Invalid implicitNotFound message for value theC: | ||
| The type parameter Uuh referenced in the message of the @implicitNotFound annotation is not defined by value theC. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this message confusing. The type parameter is supposed to be defined by m, not by theC.
| private lazy val typeParamNames: List[String] = sym.typeParams.map(_.decodedName) | ||
| private def typeArgsAtSym(paramTp: Type) = paramTp.baseType(sym).typeArgs | ||
| private lazy val typeParamNames: List[String] = { | ||
| val s = if (sym.isParameter) sym.enclMethod else sym |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can (and should) we get the full scope here instead of only the method's type parameters? This doesn't work:
scala> trait I[X, Y]
defined trait I
scala> trait T[A] { def f[B](implicit @scala.annotation.implicitNotFound("Missing I[${A}, ${B}]") i: I[A, B]): Unit = () }
^
warning: Invalid implicitNotFound message for value i:
The type parameter A referenced in the message of the @implicitNotFound annotation is not defined by value i.
defined trait TThis allows a more specific message for individual implicit parameters
that are not found.
This allows improving error message, for example in overloading
resolution:
```
scala> trait Iterable[A] { def map[B](f: A => B): Iterable[B] }
scala> trait SortedSet[A] { def map[B: Ordering](f: A => B): SortedSet[B] }
scala> def t(s: SortedSet[Int]) = s.map(x => x) // OK
t: (s: SortedSet[Int])SortedSet[Int]
scala> def t[T](s: SortedSet[T]) = s.map(x => x) // Confusing error
^
error: No implicit Ordering defined for T.
```
better:
```
scala> trait SortedSet[A] { def map[B](f: A => B)(implicit @annotation.implicitNotFound("No implicit Ordering[${B}] found to build a SortedSet[${B}]. You can build an unordered Set[${B}] by calling `unsorted` before `map`.") ord: Ordering[B]): SortedSet[B] }
defined trait SortedSet
scala> def t[T](s: SortedSet[T]) = s.map(x => x)
^
error: No implicit Ordering[T] found to build a SortedSet[T]. You can build an unordered Set[T] by calling `unsorted` before `map`.
```
77c974a to
3d2b107
Compare
|
Updated. When putting an |
test/files/neg/t2462c.check
Outdated
| t2462c.scala:36: error: I see no C[Foo[Int]] | ||
| h[Foo[Int]] | ||
| ^ | ||
| t2462c.scala:40: error: String List[?] List[C[_]] Int Option[Long] -- . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The List[?] is not great here. The formatParameterMessage method could be improved for the case of type constructors. cc @adriaanm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider me sniped :-) I pushed a commit that adds some ad-hoc pretty printing for these. Feel free to g push -f HEAD^
|
Maybe we can say this is good enough to merge? It's only about error messages. We can always accept contributions that improve it :) I'd like to not spend much more time on this. |
|
What will happen when an implicit parameter is missing from an implicit conversion? : @implicitNotFound("BarError")
trait Bar
@implicitNotFound("FooError")
trait Foo
object Foo {
implicit def fromBar(bar : Bar)(implicit @implicitNotFound("FooParamError") foo : Foo) : Foo = foo
}
val foo : Foo = new Bar{}Currently (and sadly) scalac does not even report |
Same as before. No (user-defined) error. Having some form of interactive implicit search debugger would be great, but for error messages I don't think we should try to guess secondary issues. |
In many cases I don't think it's guessing and I would have loved a custom error instead of just a |
8badb82 to
e907e31
Compare
| val paramSyms = paramNames.map(lookupTypeParam).filterNot(_ == NoSymbol) | ||
| val paramTypeRefs = paramSyms.map(sym => typeRef(NoPrefix, sym, sym.typeParams.map(_ => WildcardType))) | ||
| val prefix = fun match { | ||
| case TypeApply(Select(qual, _), _) => qual.tpe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could collapse these two cases (and also deal with repeated Apply) using: case treeInfo.Applied(Select(qual, _), _, _) => qual.tpe
test/files/neg/t2462c.check
Outdated
| t2462c.scala:36: error: I see no C[Foo[Int]] | ||
| h[Foo[Int]] | ||
| ^ | ||
| t2462c.scala:40: error: String List[?] List[C[_]] Int Option[Long] -- . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider me sniped :-) I pushed a commit that adds some ad-hoc pretty printing for these. Feel free to g push -f HEAD^
|
We could discuss that in a ticket and a different PR, but it's definitely out of scope for this one. |
|
@lrytz, others: the first commit LGTM, but I'll let you decide on my follow-up :-) |
@adriaanm I created a separate ticket for that With some help I can create a PR, if you'd consider accepting it. |
| h[Foo[Int]] | ||
| ^ | ||
| t2462c.scala:40: error: String List[?] List[C[_]] Int Option[Long] -- . | ||
| t2462c.scala:40: error: String List [?T0, ZZ] -> List[C[_]] Int Option[Long] -- . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
People will complain why this syntax doesn't work in their code 😏
|
Neither do wildcards :-p
…On Fri, Jun 15, 2018 at 14:19 Lukas Rytz ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In test/files/neg/t2462c.check
<#6340 (comment)>:
> @@ -10,7 +10,7 @@ t2462c.scala:33: error: No C of Foo[Int]
t2462c.scala:36: error: I see no C[Foo[Int]]
h[Foo[Int]]
^
-t2462c.scala:40: error: String List[?] List[C[_]] Int Option[Long] -- .
+t2462c.scala:40: error: String List [?T0, ZZ] -> List[C[_]] Int Option[Long] -- .
People will complain why this syntax doesn't work in their code 😏
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#6340 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAFjy1Wkw8M7zeEoEIYyMedNqqaLfdtmks5t86ZagaJpZM4SLMvC>
.
|
let's first discuss on the ticket -- I'm not against on principle or anything, but it's probably worth talking through before embarking on the implementation |
This allows a more specific message for individual implicit parameters
that are not found.
This allows improving error message, for example in overloading
resolution:
better: