Re: [scala-internals] Suspicious-looking order dependency in implicit resolution

瀏覽次數:28 次
跳到第一則未讀訊息

Alex Cruise

未讀,
2011年7月1日 中午12:22:422011/7/1
收件者:scala-i...@googlegroups.com
On Fri, Jul 1, 2011 at 9:14 AM, Miles Sabin <mi...@milessabin.com> 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. :)

-0xe1a

Miles Sabin

未讀,
2011年7月1日 中午12:28:212011/7/1
收件者:scala-i...@googlegroups.com

Yes, but, like I said, I only expected that rule to operate within
top-level definitions, not between them.

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
gtalk: mi...@milessabin.com
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin

Miles Sabin

未讀,
2011年7月1日 中午12:14:592011/7/1
收件者:scala-i...@googlegroups.com
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.

Paul Phillips

未讀,
2011年7月1日 下午1:30:242011/7/1
收件者:scala-i...@googlegroups.com、Miles Sabin
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.

Miles Sabin

未讀,
2011年7月1日 下午1:56:412011/7/1
收件者:Paul Phillips、scala-i...@googlegroups.com
On Fri, Jul 1, 2011 at 6:30 PM, Paul Phillips <pa...@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.

martin odersky

未讀,
2011年7月1日 下午3:45:552011/7/1
收件者:scala-i...@googlegroups.com、Paul Phillips
On Fri, Jul 1, 2011 at 7:56 PM, Miles Sabin <mi...@milessabin.com> wrote:
On Fri, Jul 1, 2011 at 6:30 PM, Paul Phillips <pa...@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

回覆所有人
回覆作者
轉寄
0 則新訊息