Skip to content

Commit 62d97d7

Browse files
committed
LMF cannot run trait's "initializer" (constructor)
Thus, rule out traits that have a constructor (which we use as a proxy for having potentially side-effecting statements), and create an anonymous subclass for them at compile time.
1 parent 63f0175 commit 62d97d7

File tree

3 files changed

+13
-1
lines changed

3 files changed

+13
-1
lines changed

src/compiler/scala/tools/nsc/transform/Erasure.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,10 @@ abstract class Erasure extends AddInterfaces
12131213
// When we delay sam expansion until after explicit outer & lambda lift, we could decide there whether
12141214
// to expand sam at compile time or use LMF, and this implementation restriction could be lifted.
12151215
sym.isStatic &&
1216+
// HACK: this is to rule out traits with an effectful initializer.
1217+
// The constructor only exists if the trait's template has statements.
1218+
// Sadly, we can't be more precise without access to the tree that defines the SAM's owner.
1219+
!sym.primaryConstructor.exists &&
12161220
(sym.isInterface || sym.info.decls.forall(mem => mem.isMethod || mem.isType)) // TODO OPT: && {sym setFlag INTERFACE; true})
12171221

12181222
// we still need to check our ancestors even if the INTERFACE flag is set, as it doesn't take inheritance into account
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
1
2+
1

test/files/run/sammy_restrictions_LMF.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ trait TInt extends T[Int]
33

44
trait TWithVal { val x: Any = 1; def apply(x: Int): String }
55

6+
trait TImpure { def apply(x: Int): String ; println(1) }
7+
8+
trait Println { println(1) }
9+
trait TImpureSuper extends Println { def apply(x: Int): String }
10+
611
object Test extends App {
712
final val AnonFunClass = "$anonfun$"
813
final val LMFClass = "$$Lambda$" // LambdaMetaFactory names classes like this
@@ -38,5 +43,6 @@ object Test extends App {
3843
notLMF(fVal)
3944
assert(fVal.x == 1)
4045

41-
46+
notLMF((x => "a"): TImpure)
47+
notLMF((x => "a"): TImpureSuper)
4248
}

0 commit comments

Comments
 (0)