- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Propagating ambiguous implicit values and unhelpful scalac error messages
Fri, 2011-12-30, 11:02
I had an issue recently where scalac was unable to provide a helpful error message in the case of ambiguous implicits. It's in the event that the ambiguity is 1-step-removed.
Here is a standard ambiguous implicit
So far so good. But what happens when we declare a second type, for which an implicit value only exists if there is an implicit value for the Foo?
Now, if we have some reliance on finding an implicit Baz instance...
There is no warning as to why the implicit baz method is not applicable. In practice this can be really hard to track down (especially with a library like scalaz). Is there any way in which you can generate an error which looks like
Chris
Here is a standard ambiguous implicit
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Server VM, Java 1.6.0_18).Type in expressions to have them evaluated.Type :help for more information.
scala> trait Foo[T] { def foo: T }defined trait Foo
scala> def bar[T : Foo]: T = implicitly[Foo[T]].foobar: [T](implicit evidence$1: Foo[T])T
scala> implicit val f1 = new Foo[Int] { def foo = 1 }f1: java.lang.Object with Foo[Int] = $anon$1@6f6068
scala> implicit val f2 = new Foo[Int] { def foo = 2 }f2: java.lang.Object with Foo[Int] = $anon$1@ec9441
scala> bar[Int]<console>:12: error: ambiguous implicit values: both value f1 in object $iw of type => java.lang.Object with Foo[Int] and value f2 in object $iw of type => java.lang.Object with Foo[Int] match expected type Foo[Int] bar[Int] ^
So far so good. But what happens when we declare a second type, for which an implicit value only exists if there is an implicit value for the Foo?
scala> trait Baz { def baz[T : Foo] = implicitly[Foo[T]].foo }defined trait Baz
scala> implicit def z[T : Foo] = new Baz {}z: [T](implicit evidence$1: Foo[T])java.lang.Object with Baz
Now, if we have some reliance on finding an implicit Baz instance...
scala> def bat(implicit baz: Baz) = bazbat: (implicit baz: Baz)Baz
scala> bat.baz[Int]<console>:16: error: could not find implicit value for parameter baz: Baz bat.baz[Int] ^
There is no warning as to why the implicit baz method is not applicable. In practice this can be really hard to track down (especially with a library like scalaz). Is there any way in which you can generate an error which looks like
could not find implicit value for parameter baz: Baz. "implicit def z" not applicable here due to ambiguous implicit values for Foo[Int]:Would such an error message be feasible?
both value f1 in object $iw of type => java.lang.Object with Foo[Int] and value f2 in object $iw of type => java.lang.Object with Foo[Int] match expected type Foo[Int]
Chris
Wed, 2012-01-11, 00:21
#2
RE: Propagating ambiguous implicit values and unhelpful scalac
I'm not familiar enough with the internals of implicit resolution to know whether this is possible. But if the compiler finds a type with a method with a matching name with an in-scope implicit conversion to that type, it could carry around a single slot saying why the implicit conversion was not applicable. If there are more than one such conversions; tough. You only get one error message. But one is better than none.
Chris
Date: Tue, 3 Jan 2012 11:45:00 +0000
Subject: Re: [scala-user] Propagating ambiguous implicit values and unhelpful scalac error messages
From: turingatemyhamster@gmail.com
To: oxbow_lakes@hotmail.com
CC: scala-user@googlegroups.com
Hi,
I'd love an error message like this. However, I'm not sure what the workable heuristic would be - when would it know that the first-level implicit that failed due to a 2nd level one was the intended implicit? There will be a whole load of level-1 implicits that it tries and fails with. So, on failure, would it go back to the most specific implicit that failed, and then if that was itself a level-1 lookup that failed due to a level-2 lookup, give the error? If that level-2 implicit failed due to a level-3, do you recurse the messages?
I've been having an entertaining time trying to write some DSL stuff that uses implicits, and debugging them is a PITA. The intellij plugin can sometimes pop-up an implicit that is used, but doesn't always get them, and doesn't give you any feedback when no implicit can be found. Consider:
def foo()(implicitly b: Bar)...foo // no implicit found for b: Bar
Once the compiler has complained here, what I need is a UI where I can get a drop-down of in-scope implicits, and click the one that I think should have been used, and then get out an explanation for why it was not applicable. If the implicit arg relies on something else, then this process needs to be continued recursively. A truly interactive implicit debugging environment would be a godsend.
Matthew
On 30 December 2011 10:02, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
--
Dr Matthew PocockIntegrative Bioinformatics Group, School of Computing Science, Newcastle Universitymailto: turingatemyhamster@gmail.com gchat: turingatemyhamster@gmail.commsn: matthew_pocock@yahoo.co.uk irc.freenode.net: drdozerskype: matthew.pococktel: (0191) 2566550mob: +447535664143
Chris
Date: Tue, 3 Jan 2012 11:45:00 +0000
Subject: Re: [scala-user] Propagating ambiguous implicit values and unhelpful scalac error messages
From: turingatemyhamster@gmail.com
To: oxbow_lakes@hotmail.com
CC: scala-user@googlegroups.com
Hi,
I'd love an error message like this. However, I'm not sure what the workable heuristic would be - when would it know that the first-level implicit that failed due to a 2nd level one was the intended implicit? There will be a whole load of level-1 implicits that it tries and fails with. So, on failure, would it go back to the most specific implicit that failed, and then if that was itself a level-1 lookup that failed due to a level-2 lookup, give the error? If that level-2 implicit failed due to a level-3, do you recurse the messages?
I've been having an entertaining time trying to write some DSL stuff that uses implicits, and debugging them is a PITA. The intellij plugin can sometimes pop-up an implicit that is used, but doesn't always get them, and doesn't give you any feedback when no implicit can be found. Consider:
def foo()(implicitly b: Bar)...foo // no implicit found for b: Bar
Once the compiler has complained here, what I need is a UI where I can get a drop-down of in-scope implicits, and click the one that I think should have been used, and then get out an explanation for why it was not applicable. If the implicit arg relies on something else, then this process needs to be continued recursively. A truly interactive implicit debugging environment would be a godsend.
Matthew
On 30 December 2011 10:02, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
I had an issue recently where scalac was unable to provide a helpful error message in the case of ambiguous implicits. It's in the event that the ambiguity is 1-step-removed.
Here is a standard ambiguous implicitWelcome to Scala version 2.9.1.final (Java HotSpot(TM) Server VM, Java 1.6.0_18).Type in expressions to have them evaluated. Type :help for more information.
scala> trait Foo[T] { def foo: T }defined trait Foo
scala> def bar[T : Foo]: T = implicitly[Foo[T]].foobar: [T](implicit evidence$1: Foo[T])T
scala> implicit val f1 = new Foo[Int] { def foo = 1 }f1: java.lang.Object with Foo[Int] = $anon$1@6f6068
scala> implicit val f2 = new Foo[Int] { def foo = 2 } f2: java.lang.Object with Foo[Int] = $anon$1@ec9441
scala> bar[Int]<console>:12: error: ambiguous implicit values: both value f1 in object $iw of type => java.lang.Object with Foo[Int] and value f2 in object $iw of type => java.lang.Object with Foo[Int] match expected type Foo[Int] bar[Int] ^
So far so good. But what happens when we declare a second type, for which an implicit value only exists if there is an implicit value for the Foo?scala> trait Baz { def baz[T : Foo] = implicitly[Foo[T]].foo }defined trait Baz
scala> implicit def z[T : Foo] = new Baz {} z: [T](implicit evidence$1: Foo[T])java.lang.Object with Baz
Now, if we have some reliance on finding an implicit Baz instance...scala> def bat(implicit baz: Baz) = bazbat: (implicit baz: Baz)Baz
scala> bat.baz[Int]<console>:16: error: could not find implicit value for parameter baz: Baz bat.baz[Int] ^
There is no warning as to why the implicit baz method is not applicable. In practice this can be really hard to track down (especially with a library like scalaz). Is there any way in which you can generate an error which looks likecould not find implicit value for parameter baz: Baz. "implicit def z" not applicable here due to ambiguous implicit values for Foo[Int]:Would such an error message be feasible?
both value f1 in object $iw of type => java.lang.Object with Foo[Int] and value f2 in object $iw of type => java.lang.Object with Foo[Int] match expected type Foo[Int]
Chris
--
Dr Matthew PocockIntegrative Bioinformatics Group, School of Computing Science, Newcastle Universitymailto: turingatemyhamster@gmail.com gchat: turingatemyhamster@gmail.commsn: matthew_pocock@yahoo.co.uk irc.freenode.net: drdozerskype: matthew.pococktel: (0191) 2566550mob: +447535664143
I'd love an error message like this. However, I'm not sure what the workable heuristic would be - when would it know that the first-level implicit that failed due to a 2nd level one was the intended implicit? There will be a whole load of level-1 implicits that it tries and fails with. So, on failure, would it go back to the most specific implicit that failed, and then if that was itself a level-1 lookup that failed due to a level-2 lookup, give the error? If that level-2 implicit failed due to a level-3, do you recurse the messages?
I've been having an entertaining time trying to write some DSL stuff that uses implicits, and debugging them is a PITA. The intellij plugin can sometimes pop-up an implicit that is used, but doesn't always get them, and doesn't give you any feedback when no implicit can be found. Consider:
def foo()(implicitly b: Bar)...foo // no implicit found for b: Bar
Once the compiler has complained here, what I need is a UI where I can get a drop-down of in-scope implicits, and click the one that I think should have been used, and then get out an explanation for why it was not applicable. If the implicit arg relies on something else, then this process needs to be continued recursively. A truly interactive implicit debugging environment would be a godsend.
Matthew
On 30 December 2011 10:02, Chris Marshall <oxbow_lakes@hotmail.com> wrote:
--
Dr Matthew PocockIntegrative Bioinformatics Group, School of Computing Science, Newcastle Universitymailto: turingatemyhamster@gmail.com gchat: turingatemyhamster@gmail.commsn: matthew_pocock@yahoo.co.uk irc.freenode.net: drdozerskype: matthew.pococktel: (0191) 2566550mob: +447535664143