summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-12-22 22:08:03 +0100
committerPaul Phillips <paulp@improving.org>2011-12-22 19:33:06 -0800
commite72e1686bb8d06937fe93f181fbda5cc6c2041da (patch)
tree70d54bf4524e62b4b7549966e6dacef72693e056
parent8ce9494d60ac5e5dd41690b82105628972142849 (diff)
downloadscala-e72e1686bb8d06937fe93f181fbda5cc6c2041da.tar.gz
scala-e72e1686bb8d06937fe93f181fbda5cc6c2041da.tar.bz2
scala-e72e1686bb8d06937fe93f181fbda5cc6c2041da.zip
Hardening of resetAllAttrs.
Now works in the case where TypeTrees refer to locally erased symbols.
-rw-r--r--src/compiler/scala/reflect/runtime/ToolBoxes.scala8
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala77
2 files changed, 44 insertions, 41 deletions
diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala
index 7ef625b2ad..9f44e2047a 100644
--- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala
+++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala
@@ -64,7 +64,8 @@ trait ToolBoxes extends { self: Universe =>
trace("wrapping ")(defOwner(expr) -> meth)
val methdef = DefDef(meth, expr changeOwner (defOwner(expr) -> meth))
trace("wrapped: ")(showAttributed(methdef))
- val objdef = ModuleDef(
+ resetAllAttrs(
+ ModuleDef(
obj,
Template(
List(TypeTree(ObjectClass.tpe)),
@@ -73,8 +74,7 @@ trait ToolBoxes extends { self: Universe =>
List(),
List(List()),
List(methdef),
- NoPosition))
- resetAllAttrs(objdef)
+ NoPosition)))
}
def wrapInPackage(clazz: Tree): PackageDef =
@@ -125,7 +125,7 @@ trait ToolBoxes extends { self: Universe =>
val saved = settings.printtypes.value
try {
settings.printtypes.value = true
- settings.uniqid.value = true
+ //settings.uniqid.value = true
tree.toString
} finally
compiler.settings.printtypes.value = saved
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 9668debbbb..f3eaff8db0 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -232,59 +232,62 @@ trait Trees extends reflect.internal.Trees { self: Global =>
/** resets symbol and tpe fields in a tree, @see ResetAttrsTraverse
*/
- def resetAllAttrs[A<:Tree](x:A): A = { new ResetAttrsTraverser().traverse(x); x }
- def resetLocalAttrs[A<:Tree](x:A): A = { new ResetLocalAttrsTraverser().traverse(x); x }
-
- /** A traverser which resets symbol and tpe fields of all nodes in a given tree
- * except for (1) TypeTree nodes, whose <code>.tpe</code> field is kept, and
- * (2) This(pkg) nodes, where pkg refers to a package symbol -- their attributes are kept, and
- * (3) if a <code>.symbol</code> field refers to a symbol which is defined
- * outside the tree, it is also kept.
- *
- * (2) is necessary because some This(pkg) are generated where pkg is not
- * an enclosing package.n In that case, resetting the symbol would cause the
- * next type checking run to fail. See #3152.
+// def resetAllAttrs[A<:Tree](x:A): A = { new ResetAttrsTraverser().traverse(x); x }
+// def resetLocalAttrs[A<:Tree](x:A): A = { new ResetLocalAttrsTraverser().traverse(x); x }
+
+ def resetAllAttrs[A<:Tree](x:A): A = new ResetAttrsTransformer(false).transformPoly(x)
+ def resetLocalAttrs[A<:Tree](x:A): A = new ResetAttrsTransformer(true).transformPoly(x)
+
+ /** A transformer which resets symbol and tpe fields of all nodes in a given tree,
+ * with special treatment of:
+ * TypeTree nodes: are replaced by their original if it exists, otherwise tpe field is reset
+ * to empty if it started out empty or refers to local symbols (which are erased).
+ * TypeApply nodes: are deleted if type arguments end up reverted to empty
+ * This(pkg) notes where pkg is a pckage: these are kept.
*
* (bq:) This traverser has mutable state and should be discarded after use
*/
- private class ResetAttrsTraverser extends Traverser {
- protected def isLocal(sym: Symbol): Boolean = true
- protected def resetDef(tree: Tree) {
+ private class ResetAttrsTransformer(localOnly: Boolean) extends Transformer {
+ private val erasedSyms = util.HashSet[Symbol](8)
+ private def resetDef(tree: Tree) {
+ if (tree.symbol != null && tree.symbol != NoSymbol)
+ erasedSyms addEntry tree.symbol
tree.symbol = NoSymbol
}
- override def traverse(tree: Tree): Unit = {
+ override def transform(tree: Tree): Tree = super.transform {
tree match {
+ case Template(_, _, body) =>
+ body foreach resetDef
+ resetDef(tree)
+ tree.tpe = null
+ tree
case _: DefTree | Function(_, _) | Template(_, _, _) =>
resetDef(tree)
tree.tpe = null
+ tree
case tpt: TypeTree =>
- if (tpt.wasEmpty) tree.tpe = null
+ if (tpt.original != null)
+ tpt.original
+ else if (tpt.tpe != null && (tpt.wasEmpty || (tpt.tpe exists (tp => erasedSyms contains tp.typeSymbol))))
+ tpt.tpe = null
+ tree
+ case TypeApply(fn, args) if args map transform exists (_.isEmpty) =>
+ fn
case This(_) if tree.symbol != null && tree.symbol.isPackageClass =>
- ;
+ tree
case EmptyTree =>
- ;
+ tree
case _ =>
- if (tree.hasSymbol && isLocal(tree.symbol)) tree.symbol = NoSymbol
+ if (tree.hasSymbol && (!localOnly || (erasedSyms contains tree.symbol)))
+ tree.symbol = NoSymbol
tree.tpe = null
+ tree
}
- super.traverse(tree)
- }
- }
-
- private class ResetLocalAttrsTraverser extends ResetAttrsTraverser {
- private val erasedSyms = util.HashSet[Symbol](8)
- override protected def isLocal(sym: Symbol) = erasedSyms(sym)
- override protected def resetDef(tree: Tree) {
- erasedSyms addEntry tree.symbol
- super.resetDef(tree)
}
- override def traverse(tree: Tree): Unit = tree match {
- case Template(parents, self, body) =>
- for (stat <- body)
- if (stat.isDef) erasedSyms.addEntry(stat.symbol)
- super.traverse(tree)
- case _ =>
- super.traverse(tree)
+ def transformPoly[T <: Tree](x: T): T = {
+ val x1 = transform(x)
+ assert(x.getClass isInstance x1)
+ x1.asInstanceOf[T]
}
}