summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Iry <jamesiry@gmail.com>2013-02-08 07:35:28 -0800
committerJames Iry <jamesiry@gmail.com>2013-02-08 07:35:28 -0800
commit3b6300b14b8aaac4c6bb7c70b51ef1df3dc3c536 (patch)
treea61374b070df32a04643be7d2ac348034d8cdf77
parentc0d1bc4cc4cb2958af69305d286ff684306617a5 (diff)
parent5258b63740c9fb1be3c531e1dc1399fb0dc55569 (diff)
downloadscala-3b6300b14b8aaac4c6bb7c70b51ef1df3dc3c536.tar.gz
scala-3b6300b14b8aaac4c6bb7c70b51ef1df3dc3c536.tar.bz2
scala-3b6300b14b8aaac4c6bb7c70b51ef1df3dc3c536.zip
Merge pull request #2092 from lrytz/t7096
SI-7096 SubstSymMap copies trees before modifying their symbols
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala42
-rw-r--r--test/files/run/t7096.check2
-rw-r--r--test/files/run/t7096.scala36
3 files changed, 67 insertions, 13 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index b708ca0fd6..fb493fabd8 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)
}
}
diff --git a/test/files/run/t7096.check b/test/files/run/t7096.check
new file mode 100644
index 0000000000..6f1cef6c43
--- /dev/null
+++ b/test/files/run/t7096.check
@@ -0,0 +1,2 @@
+testing symbol List(method foo, class Base, package ano, package <root>), param value x, xRefs List(x)
+testing symbol List(method foo, class Sub, package ano, package <root>), param value x, xRefs List(x)
diff --git a/test/files/run/t7096.scala b/test/files/run/t7096.scala
new file mode 100644
index 0000000000..e9c0323c2e
--- /dev/null
+++ b/test/files/run/t7096.scala
@@ -0,0 +1,36 @@
+import scala.tools.partest._
+import scala.tools.nsc._
+
+object Test extends CompilerTest {
+ import global._
+ import definitions._
+
+ override def code = """
+package ano
+
+class ann(x: Any) extends annotation.TypeConstraint
+
+abstract class Base {
+ def foo(x: String): String @ann(x.trim())
+}
+
+class Sub extends Base {
+ def foo(x: String): String @ann(x.trim()) = x
+}
+ """
+
+ object syms extends SymsInPackage("ano")
+ import syms._
+
+ def check(source: String, unit: global.CompilationUnit) {
+ afterTyper {
+ terms.filter(_.name.toString == "foo").foreach(sym => {
+ val xParam = sym.tpe.paramss.flatten.head
+ val annot = sym.tpe.finalResultType.annotations.head
+ val xRefs = annot.args.head.filter(t => t.symbol == xParam)
+ println(s"testing symbol ${sym.ownerChain}, param $xParam, xRefs $xRefs")
+ assert(xRefs.length == 1, xRefs)
+ })
+ }
+ }
+}