Support implicitNotFound on parameters#6340
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. |
| 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.
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.
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 |
| 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.
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.
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.
could collapse these two cases (and also deal with repeated Apply) using: case treeInfo.Applied(Select(qual, _), _, _) => qual.tpe
| 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.
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.
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: