summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-08-15 14:51:59 +0000
committerMartin Odersky <odersky@gmail.com>2011-08-15 14:51:59 +0000
commit3d740f4f79703d60db80f2d0cea49f3a7a02d327 (patch)
tree33ba86b9c10ba1d468f7e1b2d6a029331f43dd3c
parent5522aeafa7ac3c5c8cdd6be4fa13afe52b558445 (diff)
downloadscala-3d740f4f79703d60db80f2d0cea49f3a7a02d327.tar.gz
scala-3d740f4f79703d60db80f2d0cea49f3a7a02d327.tar.bz2
scala-3d740f4f79703d60db80f2d0cea49f3a7a02d327.zip
Added debug output to track down Fregor's "fail...
Added debug output to track down Fregor's "failing to lift" problem.
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala131
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala103
2 files changed, 121 insertions, 113 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index 1103d1e608..ba90ed87e4 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -35,12 +35,19 @@ abstract class LiftCode extends Transform with TypingTransformers {
new Lifter(unit)
class Lifter(unit: CompilationUnit) extends TypingTransformer(unit) {
+
+ /** Set of mutable local variables that are free in some inner method. */
+ private val freeMutableVars: mutable.Set[Symbol] = new mutable.HashSet
+ private val converted: mutable.Set[Symbol] = new mutable.HashSet // debug
+
override def transformUnit(unit: CompilationUnit) {
freeMutableVars.clear()
- freeLocalsTraverser(unit.body)
+ freeLocalsTraverser(unit.body)
atPhase(phase.next) {
super.transformUnit(unit)
}
+ for (v <- freeMutableVars)
+ assert(converted contains v, "unconverted: "+v+" in "+v.owner+" in unit "+unit)
}
override def transform(tree: Tree): Tree = {
@@ -65,6 +72,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
}
sym resetFlag MUTABLE
sym removeAnnotation VolatileAttr
+ converted += sym
treeCopy.ValDef(tree, mods &~ MUTABLE, name, tpt1, rhs1)
case Ident(name) if freeMutableVars(sym) =>
localTyper.typedPos(tree.pos) {
@@ -219,70 +227,69 @@ abstract class LiftCode extends Transform with TypingTransformers {
New(TypeTree(appliedType(definitions.CodeClass.typeConstructor, List(tree.tpe))),
List(List(arg)))
}
- }
- /** Set of mutable local variables that are free in some inner method. */
- private val freeMutableVars: mutable.Set[Symbol] = new mutable.HashSet
-
- /** PP: There is apparently some degree of overlap between the CAPTURED
- * flag and the role being filled here. I think this is how this was able
- * to go for so long looking only at DefDef and Ident nodes, as bugs
- * would only emerge under more complicated conditions such as #3855.
- * I'll try to figure it all out, but if someone who already knows the
- * whole story wants to fill it in, that too would be great.
- */
- private val freeLocalsTraverser = new Traverser {
- var currentMethod: Symbol = NoSymbol
- var maybeEscaping = false
-
- def withEscaping(body: => Unit) {
- val saved = maybeEscaping
- maybeEscaping = true
- try body
- finally maybeEscaping = saved
- }
-
- override def traverse(tree: Tree) = tree match {
- case DefDef(_, _, _, _, _, _) =>
- val lastMethod = currentMethod
- currentMethod = tree.symbol
- try super.traverse(tree)
- finally currentMethod = lastMethod
- /** A method call with a by-name parameter represents escape. */
- case Apply(fn, args) if fn.symbol.paramss.nonEmpty =>
- traverse(fn)
- (fn.symbol.paramss.head, args).zipped foreach { (param, arg) =>
- if (param.tpe != null && isByNameParamType(param.tpe))
- withEscaping(traverse(arg))
- else
- traverse(arg)
- }
- /** The rhs of a closure represents escape. */
- case Function(vparams, body) =>
- vparams foreach traverse
- withEscaping(traverse(body))
+ /**
+ * PP: There is apparently some degree of overlap between the CAPTURED
+ * flag and the role being filled here. I think this is how this was able
+ * to go for so long looking only at DefDef and Ident nodes, as bugs
+ * would only emerge under more complicated conditions such as #3855.
+ * I'll try to figure it all out, but if someone who already knows the
+ * whole story wants to fill it in, that too would be great.
+ */
+ private val freeLocalsTraverser = new Traverser {
+ var currentMethod: Symbol = NoSymbol
+ var maybeEscaping = false
+
+ def withEscaping(body: => Unit) {
+ val saved = maybeEscaping
+ maybeEscaping = true
+ try body
+ finally maybeEscaping = saved
+ }
- /** The appearance of an ident outside the method where it was defined or
- * anytime maybeEscaping is true implies escape.
- */
- case Ident(_) =>
- val sym = tree.symbol
- if (sym.isVariable && sym.owner.isMethod && (maybeEscaping || sym.owner != currentMethod)) {
- freeMutableVars += sym
- val symTpe = sym.tpe
- val symClass = symTpe.typeSymbol
- atPhase(phase.next) {
- def refType(valueRef: Map[Symbol, Symbol], objectRefClass: Symbol) =
- if (isValueClass(symClass)) valueRef(symClass).tpe
- else appliedType(objectRefClass.typeConstructor, List(symTpe))
-
- sym updateInfo (
- if (sym.hasAnnotation(VolatileAttr)) refType(volatileRefClass, VolatileObjectRefClass)
- else refType(refClass, ObjectRefClass))
+ override def traverse(tree: Tree) = tree match {
+ case DefDef(_, _, _, _, _, _) =>
+ val lastMethod = currentMethod
+ currentMethod = tree.symbol
+ try super.traverse(tree)
+ finally currentMethod = lastMethod
+ /** A method call with a by-name parameter represents escape. */
+ case Apply(fn, args) if fn.symbol.paramss.nonEmpty =>
+ traverse(fn)
+ (fn.symbol.paramss.head, args).zipped foreach { (param, arg) =>
+ if (param.tpe != null && isByNameParamType(param.tpe))
+ withEscaping(traverse(arg))
+ else
+ traverse(arg)
}
- }
- case _ =>
- super.traverse(tree)
+ /** The rhs of a closure represents escape. */
+ case Function(vparams, body) =>
+ vparams foreach traverse
+ withEscaping(traverse(body))
+
+ /**
+ * The appearance of an ident outside the method where it was defined or
+ * anytime maybeEscaping is true implies escape.
+ */
+ case Ident(_) =>
+ val sym = tree.symbol
+ if (sym.isVariable && sym.owner.isMethod && (maybeEscaping || sym.owner != currentMethod)) {
+ freeMutableVars += sym
+ val symTpe = sym.tpe
+ val symClass = symTpe.typeSymbol
+ atPhase(phase.next) {
+ def refType(valueRef: Map[Symbol, Symbol], objectRefClass: Symbol) =
+ if (isValueClass(symClass)) valueRef(symClass).tpe
+ else appliedType(objectRefClass.typeConstructor, List(symTpe))
+
+ sym updateInfo (
+ if (sym.hasAnnotation(VolatileAttr)) refType(volatileRefClass, VolatileObjectRefClass)
+ else refType(refClass, ObjectRefClass))
+ }
+ }
+ case _ =>
+ super.traverse(tree)
+ }
}
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 1e7df19afe..19a5da6276 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -83,6 +83,9 @@ abstract class UnCurry extends InfoTransform
private lazy val serialVersionUIDAnnotation =
AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List())
+ /** Set of mutable local variables that are free in some inner method. */
+ private val freeMutableVars: mutable.Set[Symbol] = new mutable.HashSet
+
override def transformUnit(unit: CompilationUnit) {
freeMutableVars.clear()
freeLocalsTraverser(unit.body)
@@ -734,59 +737,57 @@ abstract class UnCurry extends InfoTransform
newMembers += forwtree
}
}
- }
-
- /** Set of mutable local variables that are free in some inner method. */
- private val freeMutableVars: mutable.Set[Symbol] = new mutable.HashSet
-
- /** PP: There is apparently some degree of overlap between the CAPTURED
- * flag and the role being filled here. I think this is how this was able
- * to go for so long looking only at DefDef and Ident nodes, as bugs
- * would only emerge under more complicated conditions such as #3855.
- * I'll try to figure it all out, but if someone who already knows the
- * whole story wants to fill it in, that too would be great.
- */
- private val freeLocalsTraverser = new Traverser {
- var currentMethod: Symbol = NoSymbol
- var maybeEscaping = false
-
- def withEscaping(body: => Unit) {
- val saved = maybeEscaping
- maybeEscaping = true
- try body
- finally maybeEscaping = saved
- }
- override def traverse(tree: Tree) = tree match {
- case DefDef(_, _, _, _, _, _) =>
- val lastMethod = currentMethod
- currentMethod = tree.symbol
- try super.traverse(tree)
- finally currentMethod = lastMethod
- /** A method call with a by-name parameter represents escape. */
- case Apply(fn, args) if fn.symbol.paramss.nonEmpty =>
- traverse(fn)
- (fn.symbol.paramss.head, args).zipped foreach { (param, arg) =>
- if (param.tpe != null && isByNameParamType(param.tpe))
- withEscaping(traverse(arg))
- else
- traverse(arg)
- }
- /** The rhs of a closure represents escape. */
- case Function(vparams, body) =>
- vparams foreach traverse
- withEscaping(traverse(body))
+ /**
+ * PP: There is apparently some degree of overlap between the CAPTURED
+ * flag and the role being filled here. I think this is how this was able
+ * to go for so long looking only at DefDef and Ident nodes, as bugs
+ * would only emerge under more complicated conditions such as #3855.
+ * I'll try to figure it all out, but if someone who already knows the
+ * whole story wants to fill it in, that too would be great.
+ */
+ val freeLocalsTraverser = new Traverser {
+ var currentMethod: Symbol = NoSymbol
+ var maybeEscaping = false
+
+ def withEscaping(body: => Unit) {
+ val saved = maybeEscaping
+ maybeEscaping = true
+ try body
+ finally maybeEscaping = saved
+ }
- /** The appearance of an ident outside the method where it was defined or
- * anytime maybeEscaping is true implies escape.
- */
- case Ident(_) =>
- val sym = tree.symbol
- if (sym.isVariable && sym.owner.isMethod && (maybeEscaping || sym.owner != currentMethod))
- assert(false, "Failure to lift "+sym+sym.locationString); freeMutableVars += sym
- case _ =>
- super.traverse(tree)
+ override def traverse(tree: Tree) = tree match {
+ case DefDef(_, _, _, _, _, _) =>
+ val lastMethod = currentMethod
+ currentMethod = tree.symbol
+ try super.traverse(tree)
+ finally currentMethod = lastMethod
+ /** A method call with a by-name parameter represents escape. */
+ case Apply(fn, args) if fn.symbol.paramss.nonEmpty =>
+ traverse(fn)
+ (fn.symbol.paramss.head, args).zipped foreach { (param, arg) =>
+ if (param.tpe != null && isByNameParamType(param.tpe))
+ withEscaping(traverse(arg))
+ else
+ traverse(arg)
+ }
+ /** The rhs of a closure represents escape. */
+ case Function(vparams, body) =>
+ vparams foreach traverse
+ withEscaping(traverse(body))
+
+ /**
+ * The appearance of an ident outside the method where it was defined or
+ * anytime maybeEscaping is true implies escape.
+ */
+ case Ident(_) =>
+ val sym = tree.symbol
+ if (sym.isVariable && sym.owner.isMethod && (maybeEscaping || sym.owner != currentMethod))
+ assert(false, "Failure to lift " + sym + " in "+sym.owner+" in unit "+unit); freeMutableVars += sym
+ case _ =>
+ super.traverse(tree)
+ }
}
}
-
}