summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-09-15 07:21:26 -0700
committerJason Zaugg <jzaugg@gmail.com>2013-09-15 07:21:26 -0700
commitc2f7ce5cbbc3ccd086764e49c47e139786e0ab24 (patch)
tree5779d4b901132c164a94e75f52916fb2cf3bdc92
parentf3d9bdc283a82b816218aefc3df7d287e0cdd271 (diff)
parent27d73ee7a92d8dd10d4d0598a29d3a3657053995 (diff)
downloadscala-c2f7ce5cbbc3ccd086764e49c47e139786e0ab24.tar.gz
scala-c2f7ce5cbbc3ccd086764e49c47e139786e0ab24.tar.bz2
scala-c2f7ce5cbbc3ccd086764e49c47e139786e0ab24.zip
Merge pull request #2884 from retronym/ticket/3832
SI-1909 SI-3832 SI-7007 SI-7223 Improved handling of larval objects
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala17
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala19
-rw-r--r--test/files/neg/t1909-object.check4
-rw-r--r--test/files/neg/t1909-object.flags1
-rw-r--r--test/files/neg/t1909-object.scala12
-rw-r--r--test/files/neg/t7007.check7
-rw-r--r--test/files/neg/t7007.scala14
-rw-r--r--test/files/run/t1909.check3
-rw-r--r--test/files/run/t1909.scala (renamed from test/files/pos/t1909.scala)4
-rw-r--r--test/files/run/t1909b.scala (renamed from test/files/pos/t1909b-pos.scala)5
-rw-r--r--test/files/run/t1909c.scala9
-rw-r--r--test/files/run/t3832.scala17
-rw-r--r--test/files/run/t7223.check1
-rw-r--r--test/files/run/t7223.scala11
16 files changed, 119 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 8c2eb3334f..a2bf5bf9e5 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -216,7 +216,7 @@ abstract class ExplicitOuter extends InfoTransform
* values for outer parameters of constructors.
* The class provides methods for referencing via outer.
*/
- abstract class OuterPathTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
+ abstract class OuterPathTransformer(unit: CompilationUnit) extends TypingTransformer(unit) with UnderConstructionTransformer {
/** The directly enclosing outer parameter, if we are in a constructor */
protected var outerParam: Symbol = NoSymbol
@@ -277,16 +277,6 @@ abstract class ExplicitOuter extends InfoTransform
}
- /** The stack of class symbols in which a call to this() or to the super
- * constructor, or early definition is active
- */
- protected def isUnderConstruction(clazz: Symbol) = selfOrSuperCalls contains clazz
- protected val selfOrSuperCalls = mutable.Stack[Symbol]()
- @inline protected def inSelfOrSuperCall[A](sym: Symbol)(a: => A) = {
- selfOrSuperCalls push sym
- try a finally selfOrSuperCalls.pop()
- }
-
override def transform(tree: Tree): Tree = {
val savedOuterParam = outerParam
try {
@@ -300,10 +290,7 @@ abstract class ExplicitOuter extends InfoTransform
}
case _ =>
}
- if ((treeInfo isSelfOrSuperConstrCall tree) || (treeInfo isEarlyDef tree))
- inSelfOrSuperCall(currentOwner.owner)(super.transform(tree))
- else
- super.transform(tree)
+ super.transform(tree)
}
finally outerParam = savedOuterParam
}
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index 515fa66cfa..acef2a50d8 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -436,8 +436,15 @@ abstract class LambdaLift extends InfoTransform {
private def liftDef(tree: Tree): Tree = {
val sym = tree.symbol
val oldOwner = sym.owner
- if (sym.owner.isAuxiliaryConstructor && sym.isMethod) // # bug 1909
- sym setFlag STATIC
+ if (sym.isMethod && isUnderConstruction(sym.owner.owner)) { // # bug 1909
+ if (sym.isModule) { // Yes, it can be a module and a method, see comments on `isModuleNotMethod`!
+ // TODO promote to an implementation restriction if we can reason that this *always* leads to VerifyError.
+ // See neg/t1909-object.scala
+ def msg = s"SI-1909 Unable to STATICally lift $sym, which is defined in the self- or super-constructor call of ${sym.owner.owner}. A VerifyError is likely."
+ devWarning(tree.pos, msg)
+ } else sym setFlag STATIC
+ }
+
sym.owner = sym.owner.enclClass
if (sym.isClass) sym.owner = sym.owner.toInterface
if (sym.isMethod) sym setFlag LIFTED
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 454f913412..9ac0b0835a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -135,7 +135,8 @@ trait Namers extends MethodSynthesis {
setPrivateWithin(tree, sym, tree.mods)
def inConstructorFlag: Long = {
- val termOwnedContexts: List[Context] = context.enclosingContextChain.takeWhile(_.owner.isTerm)
+ val termOwnedContexts: List[Context] =
+ context.enclosingContextChain.takeWhile(c => c.owner.isTerm && !c.owner.isAnonymousFunction)
val constructorNonSuffix = termOwnedContexts exists (c => c.owner.isConstructor && !c.inConstructorSuffix)
val earlyInit = termOwnedContexts exists (_.owner.isEarlyInitialized)
if (constructorNonSuffix || earlyInit) INCONSTRUCTOR else 0L
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index a54f86bdde..38f1f0f725 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -1606,6 +1606,25 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
}
+ /** Tracks the classes currently under construction during a transform */
+ trait UnderConstructionTransformer extends Transformer {
+ import collection.mutable
+
+ protected def isUnderConstruction(clazz: Symbol) = selfOrSuperCalls contains clazz
+
+ /** The stack of class symbols in which a call to this() or to the super
+ * constructor, or early definition is active */
+ private val selfOrSuperCalls = mutable.Stack[Symbol]()
+
+ abstract override def transform(tree: Tree) = {
+ if ((treeInfo isSelfOrSuperConstrCall tree) || (treeInfo isEarlyDef tree)) {
+ selfOrSuperCalls push currentOwner.owner
+ try super.transform(tree)
+ finally selfOrSuperCalls.pop()
+ } else super.transform(tree)
+ }
+ }
+
def duplicateAndKeepPositions(tree: Tree) = new Duplicator(focusPositions = false) transform tree
// ------ copiers -------------------------------------------
diff --git a/test/files/neg/t1909-object.check b/test/files/neg/t1909-object.check
new file mode 100644
index 0000000000..401c1f7ebf
--- /dev/null
+++ b/test/files/neg/t1909-object.check
@@ -0,0 +1,4 @@
+t1909-object.scala:4: error: !!! SI-1909 Unable to STATICally lift object InnerTrouble$1, which is defined in the self- or super-constructor call of class Kaboom. A VerifyError is likely.
+ object InnerTrouble
+ ^
+one error found
diff --git a/test/files/neg/t1909-object.flags b/test/files/neg/t1909-object.flags
new file mode 100644
index 0000000000..eb8b40661b
--- /dev/null
+++ b/test/files/neg/t1909-object.flags
@@ -0,0 +1 @@
+-Xdev -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t1909-object.scala b/test/files/neg/t1909-object.scala
new file mode 100644
index 0000000000..d6011ba4a5
--- /dev/null
+++ b/test/files/neg/t1909-object.scala
@@ -0,0 +1,12 @@
+class Kaboom(a: Any) {
+ def this() = {
+ this({
+ object InnerTrouble
+ InnerTrouble
+ })
+ }
+}
+
+object Test extends App {
+ new Kaboom()
+} \ No newline at end of file
diff --git a/test/files/neg/t7007.check b/test/files/neg/t7007.check
new file mode 100644
index 0000000000..e22ecb9e4e
--- /dev/null
+++ b/test/files/neg/t7007.check
@@ -0,0 +1,7 @@
+t7007.scala:5: error: Implementation restriction: <$anon: A => B> requires premature access to class Crash.
+ def this(a: Seq[A]) = this(a.collect{ case b: B => b}, a.collect{ case b: B => b})
+ ^
+t7007.scala:5: error: Implementation restriction: <$anon: A => B> requires premature access to class Crash.
+ def this(a: Seq[A]) = this(a.collect{ case b: B => b}, a.collect{ case b: B => b})
+ ^
+two errors found
diff --git a/test/files/neg/t7007.scala b/test/files/neg/t7007.scala
new file mode 100644
index 0000000000..e41dccf550
--- /dev/null
+++ b/test/files/neg/t7007.scala
@@ -0,0 +1,14 @@
+class A
+class B extends A
+
+class Crash(b1: Seq[B], b2: Seq[B]) {
+ def this(a: Seq[A]) = this(a.collect{ case b: B => b}, a.collect{ case b: B => b})
+}
+
+object Main extends App {
+
+ // runtime exception with either constructor
+ val c1 = new Crash(Seq(new B, new B))
+ val c2 = new Crash(Seq(new B), Seq(new B))
+
+}
diff --git a/test/files/run/t1909.check b/test/files/run/t1909.check
new file mode 100644
index 0000000000..7d25be60fd
--- /dev/null
+++ b/test/files/run/t1909.check
@@ -0,0 +1,3 @@
+t1909.scala:7: warning: A try without a catch or finally is equivalent to putting its body in a block; no exceptions are handled.
+ def this(p: String) = this(try 0)
+ ^
diff --git a/test/files/pos/t1909.scala b/test/files/run/t1909.scala
index 01213f62a3..8ead7bacf2 100644
--- a/test/files/pos/t1909.scala
+++ b/test/files/run/t1909.scala
@@ -6,3 +6,7 @@ class Ticket1909 {
def this(value: Int) = this()
def this(p: String) = this(try 0)
}
+
+object Test extends App {
+ new Ticket1909("")
+}
diff --git a/test/files/pos/t1909b-pos.scala b/test/files/run/t1909b.scala
index b914bee366..89b2af57dc 100644
--- a/test/files/pos/t1909b-pos.scala
+++ b/test/files/run/t1909b.scala
@@ -3,4 +3,7 @@ class Ticket1909 (x: Int) {
def bar() = 5
bar
})
-} \ No newline at end of file
+}
+object Test extends App {
+ new Ticket1909()
+}
diff --git a/test/files/run/t1909c.scala b/test/files/run/t1909c.scala
new file mode 100644
index 0000000000..87c0eb08b5
--- /dev/null
+++ b/test/files/run/t1909c.scala
@@ -0,0 +1,9 @@
+class Base(a: Any)
+
+// java.lang.VerifyError: (class: Sub, method: <init> signature: ()V) Expecting to find object/array on stack
+// at Test$.<init>(t1909c.scala)
+class Sub() extends Base({ def bippy = 5; bippy })
+
+object Test extends App {
+ new Sub()
+}
diff --git a/test/files/run/t3832.scala b/test/files/run/t3832.scala
new file mode 100644
index 0000000000..ac44358bc7
--- /dev/null
+++ b/test/files/run/t3832.scala
@@ -0,0 +1,17 @@
+class t3832 {
+ def this(un: Int) = {
+ this()
+ def bippy = this
+ ()
+ }
+ def this(un: Boolean) = {
+ this()
+ def boppy = () => this
+ ()
+ }
+}
+
+object Test extends App {
+ new t3832(0)
+ new t3832(true)
+}
diff --git a/test/files/run/t7223.check b/test/files/run/t7223.check
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/test/files/run/t7223.check
@@ -0,0 +1 @@
+0
diff --git a/test/files/run/t7223.scala b/test/files/run/t7223.scala
new file mode 100644
index 0000000000..a707e957df
--- /dev/null
+++ b/test/files/run/t7223.scala
@@ -0,0 +1,11 @@
+class D(val a: () => Int => () => Any) {
+ a()(0)()
+}
+
+object Crash extends D(() => {
+ (x: Int) => {() => { new { println(x.toString) } }}
+})
+
+object Test extends App {
+ Crash
+}