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
"amb prefix" printed to stdout as the implicit scope excludes implicits in a companion available via two different prefixes #5340
Comments
Imported From: https://issues.scala-lang.org/browse/SI-5340?orig=1 |
@retronym said (edited on May 8, 2012 9:30:14 PM UTC): class Poly {
class E
object E {
implicit def conv(value: Any): E = sys.error("")
}
}
object MyApp {
val r: Poly = sys.error("")
val s: Poly = sys.error("")
val b: r.E = sys.error("")
// okay
s.E.conv(b): s.E
// compilation fails with error below
println(b: s.E)
// amb prefix: MyApp.s.type#class E MyApp.r.type#class E
// amb prefix: MyApp.s.type#class E MyApp.r.type#class E
// ../test/pending/run/t5310.scala:17: error: type mismatch;
// found : MyApp.r.E
// required: MyApp.s.E
// println(b: s.E)
// ^
}
|
@retronym said: |
This was referenced Jul 24, 2017
PR: scala/scala#6010 |
retronym
pushed a commit
to retronym/scala
that referenced
this issue
Jan 13, 2018
When the implicit scope is constructed an initial pruning phase attempts to discard implicit members which it is believed would later be rejected as ambiguous. Members of a companion are discarded if they can be reached via more than one prefix, on the assumption that being visible via two or more paths means that the multiple values must conflict with one another. However, this does not take into account the possibility that the implicit members might depend on the prefix in a way which renders them non-ambiguous. This scenario is illustrated in scala/bug#4947 and scala/bug#5340. This PR address that by only pruning implicits which are independent of the prefix. Whilst this PR tries to stay as close as possible to the current behaviour, I believe that it would be desirable to drop the early pruning of even the prefix-independent implicits. If we do that then we get improved error messages reporting ambiguity rather the ambiguous members being silently ignored which leads to otherwise unexplained failures of implicit resolution. For instance in the case of `test/files/neg/t5340.scala` which currently reports, ``` t5340.scala:15: error: type mismatch; found : Quux[MyApp.r.E,MyApp.s.E] required: Int (new Quux[r.E, s.E]): Int // fails due to pre-stripping implicits which ^ one error found ``` we would get the following report, ``` t5340.scala:15: error: type mismatch; found : Quux[MyApp.r.E,MyApp.s.E] required: Int Note that implicit conversions are not applicable because they are ambiguous: both method conv in object E of type [T, U](b: Quux[T,U])Int and method conv in object E of type [T, U](b: Quux[T,U])Int are possible conversion functions from Quux[MyApp.r.E,MyApp.s.E] to Int (new Quux[r.E, s.E]): Int // fails due to pre-stripping implicits which ^ one error found ``` Which is clearly more informative (even if also a little baffling). I think that ambiguity via multiple paths is sufficiently rare that the performance benefits of this early pruning are likely to minimal and not enough to outweigh improved error messages. Because this change can result in a symbol _legitimately_ being revisited, via a different prefix, we need to change the way that the a pruned path is represented. Instead of using empty lists, as introduced in scala#5951 (which fixes scala/bug#10081) we use explicit sentinels to mark that a symbol has been visited at a given prefix yielding no additional implicits. Testing this yielded scala/bug#10425 which appears to be a regression relative to 2.12.x. That's also fixed in this PR.
milessabin
added a commit
to milessabin/scala
that referenced
this issue
Jan 13, 2018
When the implicit scope is constructed an initial pruning phase attempts to discard implicit members which it is believed would later be rejected as ambiguous. Members of a companion are discarded if they can be reached via more than one prefix, on the assumption that being visible via two or more paths means that the multiple values must conflict with one another. However, this does not take into account the possibility that the implicit members might depend on the prefix in a way which renders them non-ambiguous. This scenario is illustrated in scala/bug#4947 and scala/bug#5340. This PR address that by only pruning implicits which are independent of the prefix. Whilst this PR tries to stay as close as possible to the current behaviour, I believe that it would be desirable to drop the early pruning of even the prefix-independent implicits. If we do that then we get improved error messages reporting ambiguity rather the ambiguous members being silently ignored which leads to otherwise unexplained failures of implicit resolution. For instance in the case of `test/files/neg/t5340.scala` which currently reports, ``` t5340.scala:15: error: type mismatch; found : Quux[MyApp.r.E,MyApp.s.E] required: Int (new Quux[r.E, s.E]): Int // fails due to pre-stripping implicits which ^ one error found ``` we would get the following report, ``` t5340.scala:15: error: type mismatch; found : Quux[MyApp.r.E,MyApp.s.E] required: Int Note that implicit conversions are not applicable because they are ambiguous: both method conv in object E of type [T, U](b: Quux[T,U])Int and method conv in object E of type [T, U](b: Quux[T,U])Int are possible conversion functions from Quux[MyApp.r.E,MyApp.s.E] to Int (new Quux[r.E, s.E]): Int // fails due to pre-stripping implicits which ^ one error found ``` Which is clearly more informative (even if also a little baffling). I think that ambiguity via multiple paths is sufficiently rare that the performance benefits of this early pruning are likely to minimal and not enough to outweigh improved error messages. Because this change can result in a symbol _legitimately_ being revisited, via a different prefix, we need to change the way that the a pruned path is represented. Instead of using empty lists, as introduced in scala#5951 (which fixes scala/bug#10081) we use explicit sentinels to mark that a symbol has been visited at a given prefix yielding no additional implicits. Testing this yielded scala/bug#10425 which appears to be a regression relative to 2.12.x. That's also fixed in this PR.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In the context of a computer algebra project, implicits are used to implement automatic conversion (coercion) of polynomial coefficients to polynomials, as in x+1, with x = polynomial over the integers. The code below produces a strange error message in the standard output when compiled with scalac.
The error message:
The involved code is in scala/tools/nsc/typechecker/Implicits.scala
The text was updated successfully, but these errors were encountered: