summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala20
-rw-r--r--test/files/pos/t9050.scala13
2 files changed, 32 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 35de3adff6..ccf907e05d 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -1576,6 +1576,7 @@ trait Trees extends api.Trees {
*/
class TreeSymSubstituter(from: List[Symbol], to: List[Symbol]) extends Transformer {
val symSubst = new SubstSymMap(from, to)
+ private var mutatedSymbols: List[Symbol] = Nil
override def transform(tree: Tree): Tree = {
def subst(from: List[Symbol], to: List[Symbol]) {
if (!from.isEmpty)
@@ -1594,6 +1595,7 @@ trait Trees extends api.Trees {
|TreeSymSubstituter: updated info of symbol ${tree.symbol}
| Old: ${showRaw(tree.symbol.info, printTypes = true, printIds = true)}
| New: ${showRaw(newInfo, printTypes = true, printIds = true)}""")
+ mutatedSymbols ::= tree.symbol
tree.symbol updateInfo newInfo
}
case _ =>
@@ -1613,7 +1615,23 @@ trait Trees extends api.Trees {
} else
super.transform(tree)
}
- def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T]
+ def apply[T <: Tree](tree: T): T = {
+ val tree1 = transform(tree)
+ invalidateSingleTypeCaches(tree1)
+ tree1.asInstanceOf[T]
+ }
+ private def invalidateSingleTypeCaches(tree: Tree): Unit = {
+ if (mutatedSymbols.nonEmpty)
+ for (t <- tree)
+ for (tp <- t.tpe) {
+ tp match {
+ case s: SingleType if mutatedSymbols contains s.sym =>
+ s.underlyingPeriod = NoPeriod
+ s.underlyingCache = NoType
+ case _ =>
+ }
+ }
+ }
override def toString() = "TreeSymSubstituter/" + substituterString("Symbol", "Symbol", from, to)
}
diff --git a/test/files/pos/t9050.scala b/test/files/pos/t9050.scala
new file mode 100644
index 0000000000..b1ab09f901
--- /dev/null
+++ b/test/files/pos/t9050.scala
@@ -0,0 +1,13 @@
+final class Mu[F](val value: Any) extends AnyVal {
+ def cata(f: F) {
+ // crash
+ ((y: Mu[F]) => y.cata(f))
+ // crash
+ def foo(x : Mu[F]) = x.cata(f)
+
+ // // okay
+ def x: Mu[F] = ???
+ (() => x.cata(f))
+ assert(true, cata(f))
+ }
+}