Closed
Description
The following code:
class Outer {
trait Inner {
def apply(x: Int): Int
}
val f: Inner = x => x
}
Becomes after frontend:
package <empty> {
class Outer() extends Object() {
<trait> trait Inner() extends Object {
def apply(x: Int): Int
}
val f: Outer.this.Inner = {
def $anonfun(x: Int): Int = x
closure($anonfun:Outer.this.Inner)
}
}
So far so good: Inner
is a SAM type (also known as a Functional Interface) so it can be the result of a closure, now watch what happens after ExplicitOuter:
class Outer() extends Object() {
<trait> trait Inner() extends Object() {
def apply(x: Int): Int
final def Outer$Inner$$$outer: Outer
}
...
Oh no! Inner now has two abstract methods, it's no longer a SAM type, and that's terrible.
I'm not sure but I think that there are two things wrong here:
- The
SAMType
extractor should not consider traits that may get an outer pointer as SAM types, not sure what the best way to ensure that is. - In this example, it seems like
Inner
should have the flagPureInterface
set, that way it won't get an outer pointer. I investigated a bit:NormalizeFlags
should setPureInterface
ifNoInits
is set but that flag isn't set onInner
either.Namer#denotsNamed
should setNoInits
, but it doesn't becauseTreeInfo#isNoInitMember
returns false when called on the applyDefDef
. That's where I stopped.
@odersky : Could you take a look at this and advise on the best way to fix it?
Metadata
Metadata
Assignees
Labels
No labels