- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Suspicious-looking order dependency in implicit resolution
Fri, 2011-07-01, 17:15
Hi folks,
I think this is probably a bug, but I thought I'd canvas opinions here
before opening a ticket.
Consider the following single compilation unit,
implicitorder.scala
object ImplicitConsumer {
import ImplicitProvider._
implicitly[String]
}
object ImplicitProvider {
implicit def foo = "foo"
}
This compiles (2.9.0-1 and trunk) with the error,
implicitorder.scala:3: error: could not find implicit value for
parameter e: String
implicitly[String]
We can fix that either by adding a type annotation to the definition
of foo or by moving the definition of ImplicitConsumer after the
definition of ImplicitProvider. That surprised me a little, because
I'd thought that requirement for explicit type annotations in the
forward-use case only applied within top-level definitions, not
between them. But whatever, not so big a deal.
But now take those same definitions and place them in two separate
compilation units,
implicitorder.scala
object ImplicitConsumer {
import ImplicitProvider._
implicitly[String]
}
implicitorder2.scala
object ImplicitProvider {
implicit def foo = "foo"
}
And compile both together (again, 2.9.0-1 and trunk). This time no error.
On the face of it, either both of these should compile successfully or
both should fail. And I think both should compile successfully,
because where we're dealing with top-level definitions, the textual
order within a compilation unit shouldn't be significant.
Is this a bug? If it is, is it a new one? I have't been able to find
anything (open) in Jira that looks similar.
Cheers,
Miles
Fri, 2011-07-01, 17:37
#2
Re: Suspicious-looking order dependency in implicit resolution
On Fri, Jul 1, 2011 at 5:22 PM, Alex Cruise wrote:
> On Fri, Jul 1, 2011 at 9:14 AM, Miles Sabin wrote:
>>
>> I think this is probably a bug, but I thought I'd canvas opinions here
>> before opening a ticket.
>
> No doubt you're aware of it already,
> but https://issues.scala-lang.org/browse/SI-801?focusedCommentId=41419 is
> useful for many others who might encounter this situation. :)
Yes, but, like I said, I only expected that rule to operate within
top-level definitions, not between them.
Cheers,
Miles
Fri, 2011-07-01, 18:37
#3
Re: Suspicious-looking order dependency in implicit resolution
On 7/1/11 9:14 AM, Miles Sabin wrote:
> I think this is probably a bug, but I thought I'd canvas opinions here
> before opening a ticket.
To my knowledge the behavior has not been specified. Attempting to reverse engineer the rule from the error message
"implicit method foo is not applicable here because it comes after the application point and it lacks an explicit result type"
one could argue the behavior is consistent with that. I think there will be reluctance to offer much in the way of guarantees. Here is some behavior one can currently witness.
// c.scala
object A {
import B._
implicitly[String]
implicitly[Int]
println(List(2): Set[Int])
println(List("def"): Set[String])
implicit def bippyc[T](x: List[T])(implicit p: T) = { println("bippyc converted " + x) ; x.toSet }
implicit def bippy = 5
}
// c2.scala
object B {
import A._
implicitly[String]
implicitly[Int]
println(List(1): Set[Int])
println(List("abc"): Set[String])
implicit def fooc[T](x: Seq[T])(implicit p: String) = { println("fooc converted " + x) ; x.toSet }
implicit def foo = "foo"
}
If we comment out "implicitly[Int]" in c.scala, then this compiles, which poses interesting questions which I'll skip past:
% scalac c.scala c2.scala
Not this though:
% scalac c2.scala c.scala
c2.scala:4: error: could not find implicit value for parameter e: String
implicitly[String]
^
c2.scala:8: error: could not find implicit value for parameter p: java.lang.String
println(List("abc"): Set[String])
^
two errors found
Or, with implicitly[Int] still commented out, add an explicit "Set[T]" result type to bippyc in c.scala, and:
% scalac c.scala c2.scala
c.scala:7: error: could not find implicit value for parameter p: Int
println(List(2): Set[Int])
^
one error found
I think one could do this all day.
Fri, 2011-07-01, 19:07
#4
Re: Suspicious-looking order dependency in implicit resolution
On Fri, Jul 1, 2011 at 6:30 PM, Paul Phillips wrote:
> If we comment out "implicitly[Int]" in c.scala, then this compiles, which poses interesting questions which I'll skip past:
>
> % scalac c.scala c2.scala
>
>
> Not this though:
>
> % scalac c2.scala c.scala
Oh, interesting. I'd tried swapping the order of the source files on
the command line to see if that was responsible for an implicit (sic)
textual ordering, but that didn't have any effect in my simpler
scenario.
I have to say that if the behaviour is as inscrutable as it seems to
be then it's really borderline reckless to ever allow the result type
of an implicit to be inferred ... which is annoying, to say the least.
Cheers,
Miles
Fri, 2011-07-01, 20:47
#5
Re: Suspicious-looking order dependency in implicit resolution
On Fri, Jul 1, 2011 at 7:56 PM, Miles Sabin <miles@milessabin.com> wrote:
On Fri, Jul 1, 2011 at 6:30 PM, Paul Phillips <paulp@improving.org> wrote:
> If we comment out "implicitly[Int]" in c.scala, then this compiles, which poses interesting questions which I'll skip past:
>
> % scalac c.scala c2.scala
>
>
> Not this though:
>
> % scalac c2.scala c.scala
Oh, interesting. I'd tried swapping the order of the source files on
the command line to see if that was responsible for an implicit (sic)
textual ordering, but that didn't have any effect in my simpler
scenario.
I have to say that if the behaviour is as inscrutable as it seems to
be then it's really borderline reckless to ever allow the result type
of an implicit to be inferred ... which is annoying, to say the least.
I think we probably have to demand explicit return types for implicits, yes. The current behavior is as far as we can possibly go, and as you say it is very fragile.
Cheers
-- Martin
No doubt you're aware of it already, but https://issues.scala-lang.org/browse/SI-801?focusedCommentId=41419 is useful for many others who might encounter this situation. :)
-0xe1a