summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2013-02-08 00:05:55 +0100
committerLukas Rytz <lukas.rytz@epfl.ch>2013-02-08 09:33:16 +0100
commit5258b63740c9fb1be3c531e1dc1399fb0dc55569 (patch)
tree81c7aa0096e14512805187b319c07f6d5866d5f4 /src
parent0dd02d92a363ee13b13eb4536c938d24bb5dd98d (diff)
downloadscala-5258b63740c9fb1be3c531e1dc1399fb0dc55569.tar.gz
scala-5258b63740c9fb1be3c531e1dc1399fb0dc55569.tar.bz2
scala-5258b63740c9fb1be3c531e1dc1399fb0dc55569.zip
SI-7096 SubstSymMap copies trees before modifying their symbols
I removed some strange code in a06d31f6a2 and replaced it by something incorrect: SubstSymMap should never have side-effects: otherwise, calling 'tpe1 <: tpe2' for instance would modify the symbols in annotations of tpe2. SubstSymMap now always creates new trees before changing them.
Diffstat (limited to 'src')
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala42
1 files changed, 29 insertions, 13 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 0dd98fb6ae..b06ab6c929 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -4698,23 +4698,39 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
- override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
- object trans extends TypeMapTransformer {
+ object mapTreeSymbols extends TypeMapTransformer {
+ val strictCopy = newStrictTreeCopier
- def termMapsTo(sym: Symbol) = from indexOf sym match {
- case -1 => None
- case idx => Some(to(idx))
- }
+ def termMapsTo(sym: Symbol) = from indexOf sym match {
+ case -1 => None
+ case idx => Some(to(idx))
+ }
- override def transform(tree: Tree) = {
- termMapsTo(tree.symbol) match {
- case Some(tosym) => tree.symbol = tosym
- case None => ()
- }
- super.transform(tree)
+ // if tree.symbol is mapped to another symbol, passes the new symbol into the
+ // constructor `trans` and sets the symbol and the type on the resulting tree.
+ def transformIfMapped(tree: Tree)(trans: Symbol => Tree) = termMapsTo(tree.symbol) match {
+ case Some(toSym) => trans(toSym) setSymbol toSym setType tree.tpe
+ case None => tree
+ }
+
+ // changes trees which refer to one of the mapped symbols. trees are copied before attributes are modified.
+ override def transform(tree: Tree) = {
+ // super.transform maps symbol references in the types of `tree`. it also copies trees where necessary.
+ super.transform(tree) match {
+ case id @ Ident(_) =>
+ transformIfMapped(id)(toSym =>
+ strictCopy.Ident(id, toSym.name))
+
+ case sel @ Select(qual, name) =>
+ transformIfMapped(sel)(toSym =>
+ strictCopy.Select(sel, qual, toSym.name))
+
+ case tree => tree
}
}
- trans.transform(tree)
+ }
+ override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
+ mapTreeSymbols.transform(tree)
}
}