-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix nested implicit functions #2146
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
Conversation
Here are some examples on how the implemented expansion behaves currently (for some arbitrary types def foo: implicit A => implicit B => Int = {
implicitly[A]
implicitly[B]
42
}
//=====>
def foo: implicit A => implicit B => Int = { implicit evidence$2 => implicit evidence$1 =>
implicitly[A](evidence$2)
implicitly[B](evidence$1)
42
} def foo: implicit A => implicit B => Int = { implicit a: A =>
implicitly[A]
implicitly[B]
42
}
//=====>
def foo: implicit A => implicit B => Int = { implicit a: A => implicit evidence$1 =>
implicitly[A](a)
implicitly[B](evidence$1)
42
} def foo: implicit A => implicit B => Int = { implicit a: A => implicit b: B =>
implicitly[A]
implicitly[B]
42
}
//=====>
def foo: implicit A => implicit B => Int = { implicit a: A => implicit b: B =>
implicitly[A](a)
implicitly[B](b)
42
} |
The newly added tests show some failure during typechecking which I haven't observed running The relevant line 1572:
|
@b-studios Yes, see https://github.com/lampepfl/dotty/blob/master/compiler/test/dotc/tests.scala#L30 and https://github.com/lampepfl/dotty/blob/master/compiler/test/dotc/tests.scala#L65 The stacktrace for your errors shows that it happens in |
@smarter Thanks, looks like the bug hides in the |
@smarter I must say, I am a bit confused how type IF = implicit Us => implicit Vs => (implicit ...) => R Would a method definition def m(xs: Ts): IF = implicit (ys: Us) => implicit (zs: Vs) => (implicit ...) => E be transformed into the following two methods def m(xs: Ts): IF = implicit (ys: Us) => implicit (zs: Vs) => (implicit ...) => m$direct(xs)(ys, zs, ...)
def m$direct(xs: Ts)(implicit ys: Us, zs: Vs, ...): R = E or into the following? def m(xs: Ts): IF = implicit (ys: Us) => implicit (zs: Vs) => (implicit ...) => m$direct(xs)(ys)(zs)(...)
def m$direct(xs: Ts)(implicit ys: Us)(implicit zs: Vs, ...): R = E Probably the second makes more sense, given that if |
I guess it's a matter of taste, but I agree the second makes more sense. Among other reasons, it keeps the same type for Two small nitpicks. Nitpick two: your example with the second should call
|
@Blaisorblade object shortcut {
trait A
def m(n: Int): implicit A => Int = n
} yields class shortcut$() extends Object() {
<trait> interface trait A() extends Object {}
def m(n: Int): implicit shortcut.A => Int = {
def $anonfun(implicit evidence$1: shortcut.A): Int =
shortcut.m$direct(n)(evidence$1)
closure($anonfun)
}
def m$direct(n: Int)(implicit x$0: shortcut.A): Int = n
} RE Nitpick 2: Thanks, I now got that fixed in place! |
@b-studios Thanks for the answer and fixes!
It'd be great if somebody fixed those docs then — wanna get one more patch under your belt? 😉 I pointed out I hadn't double-checked because I had my suspects: I looked at the code and couldn't see where |
Thanks for brining up the problem and proposing a fix. Your fix went into the right direction. I was able to simplify it considerably in the end. The new version is in #2235. Review comments very welcome! |
Fix #2146: Make nested implicit function types work
Currently nested implicit function types (#1775) are not successfully eta-expanded. That is the following is not valid:
While this PR drafts a solution, for now it should only serve for discussion purposes.
@smarter @odersky Is there a reason why automatic eta expansion of nested implicit function types is not implemented?