From 62d97d7f110894a0c2f36b1ed9dd7ad59c0115fa Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 29 Mar 2016 19:25:06 -0700 Subject: 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. --- src/compiler/scala/tools/nsc/transform/Erasure.scala | 4 ++++ test/files/run/sammy_restrictions_LMF.check | 2 ++ test/files/run/sammy_restrictions_LMF.scala | 8 +++++++- 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/files/run/sammy_restrictions_LMF.check diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index cdf3e18b5a..ebb55afca9 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -1213,6 +1213,10 @@ abstract class Erasure extends AddInterfaces // When we delay sam expansion until after explicit outer & lambda lift, we could decide there whether // to expand sam at compile time or use LMF, and this implementation restriction could be lifted. sym.isStatic && + // HACK: this is to rule out traits with an effectful initializer. + // The constructor only exists if the trait's template has statements. + // Sadly, we can't be more precise without access to the tree that defines the SAM's owner. + !sym.primaryConstructor.exists && (sym.isInterface || sym.info.decls.forall(mem => mem.isMethod || mem.isType)) // TODO OPT: && {sym setFlag INTERFACE; true}) // we still need to check our ancestors even if the INTERFACE flag is set, as it doesn't take inheritance into account diff --git a/test/files/run/sammy_restrictions_LMF.check b/test/files/run/sammy_restrictions_LMF.check new file mode 100644 index 0000000000..6ed281c757 --- /dev/null +++ b/test/files/run/sammy_restrictions_LMF.check @@ -0,0 +1,2 @@ +1 +1 diff --git a/test/files/run/sammy_restrictions_LMF.scala b/test/files/run/sammy_restrictions_LMF.scala index 40bb234a72..27a3d21dad 100644 --- a/test/files/run/sammy_restrictions_LMF.scala +++ b/test/files/run/sammy_restrictions_LMF.scala @@ -3,6 +3,11 @@ trait TInt extends T[Int] trait TWithVal { val x: Any = 1; def apply(x: Int): String } +trait TImpure { def apply(x: Int): String ; println(1) } + +trait Println { println(1) } +trait TImpureSuper extends Println { def apply(x: Int): String } + object Test extends App { final val AnonFunClass = "$anonfun$" final val LMFClass = "$$Lambda$" // LambdaMetaFactory names classes like this @@ -38,5 +43,6 @@ object Test extends App { notLMF(fVal) assert(fVal.x == 1) - + notLMF((x => "a"): TImpure) + notLMF((x => "a"): TImpureSuper) } -- cgit v1.2.3