Permalink
Browse files

Forbid forward refs from self constructor invocations.

Prevents the wheels falling off during later compiler phases,
or, worse, during bytecode verification.

Closes SI-4098.
  • Loading branch information...
retronym committed May 10, 2012
1 parent df10f92 commit d35e74eb6bc13f1f354029c9439cef35aecd972b
@@ -1279,6 +1279,15 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
def transformStat(tree: Tree, index: Int): List[Tree] = tree match {
+ case Apply(Select(This(_), nme.CONSTRUCTOR), args) =>
+ assert(index == 0, index)
+ val t = transform(tree)
+ if (currentLevel.maxindex > 0) {
+ // An implementation restriction to avoid VerifyErrors and lazyvals mishaps; see SI-4717
+ debuglog("refsym = " + currentLevel.refsym)
+ unit.error(currentLevel.refpos, "forward reference not allowed from self constructor invocation")
+ }
+ List(t)
case ModuleDef(_, _, _) => eliminateModuleDefs(tree)
case ValDef(_, _, _, _) =>
val tree1 @ ValDef(_, _, _, rhs) = transform(tree) // important to do before forward reference check
View
@@ -0,0 +1,13 @@
+t4098.scala:3: error: forward reference not allowed from self constructor invocation
+ this(b)
+ ^
+t4098.scala:8: error: forward reference not allowed from self constructor invocation
+ this(b)
+ ^
+t4098.scala:13: error: forward reference not allowed from self constructor invocation
+ this(b)
+ ^
+t4098.scala:18: error: forward reference not allowed from self constructor invocation
+ this(b)
+ ^
+four errors found
View
@@ -0,0 +1,22 @@
+class A(a: Any) {
+ def this() = {
+ this(b)
+ def b = new {}
+ }
+
+ def this(x: Int) = {
+ this(b)
+ lazy val b = new {}
+ }
+
+ def this(x: Int, y: Int) = {
+ this(b)
+ val b = new {}
+ }
+
+ def this(x: Int, y: Int, z: Int) = {
+ this(b)
+ println(".")
+ def b = new {}
+ }
+}

0 comments on commit d35e74e

Please sign in to comment.