Skip to content
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 11, 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
@@ -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
@@ -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.
You can’t perform that action at this time.