-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
SAMTypeextractor 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
Innershould have the flagPureInterfaceset, that way it won't get an outer pointer. I investigated a bit:NormalizeFlagsshould setPureInterfaceifNoInitsis set but that flag isn't set onInnereither.Namer#denotsNamedshould setNoInits, but it doesn't becauseTreeInfo#isNoInitMemberreturns 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