From 1a81244b68e58bde6a3d03551f1d92f15c3ff719 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 19 Oct 2014 16:57:14 +0200 Subject: Fix to TreeTypeMap Now handles the case where a class symbol itself is not changed by the map, but one of its declarations is. In this case we need to back out, and create new symbols for the class and all other symbols that are defined in the same scope as the class. --- src/dotty/tools/dotc/ast/TreeTypeMap.scala | 44 +++++++++++------------------- src/dotty/tools/dotc/core/Symbols.scala | 6 ++-- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/src/dotty/tools/dotc/ast/TreeTypeMap.scala index 22428edb6..32c89c94f 100644 --- a/src/dotty/tools/dotc/ast/TreeTypeMap.scala +++ b/src/dotty/tools/dotc/ast/TreeTypeMap.scala @@ -79,25 +79,13 @@ final class TreeTypeMap( override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = treeMap(tree) match { case impl @ Template(constr, parents, self, body) => - if (oldOwners contains impl.symbol.owner) { - val tmap = withMappedSyms(localSyms(impl :: self :: Nil)) - cpy.Template(impl)( + val tmap = withMappedSyms(localSyms(impl :: self :: Nil)) + cpy.Template(impl)( constr = tmap.transformSub(constr), parents = parents mapconserve transform, self = tmap.transformSub(self), body = body mapconserve tmap.transform ).withType(tmap.mapType(impl.tpe)) - } - else { - val tmap = withMappedSyms(impl.symbol :: impl.constr.symbol :: Nil) - val parents1 = parents mapconserve transform - val (_, constr1 :: self1 :: Nil) = transformDefs(constr :: self :: Nil) - val body1 = tmap.transformStats(body) - updateDecls(constr :: body, constr1 :: body1) - cpy.Template(impl)( - constr1.asInstanceOf[DefDef], parents1, self1.asInstanceOf[ValDef], body1) - .withType(tmap.mapType(impl.tpe)) - } case tree1 => tree1.withType(mapType(tree1.tpe)) match { case id: Ident if tpd.needsSelect(id.tpe) => @@ -171,24 +159,24 @@ final class TreeTypeMap( * and return a treemap that contains the substitution * between original and mapped symbols. */ - def withMappedSyms(syms: List[Symbol]): TreeTypeMap = - withMappedSyms(syms, ctx.mapSymbols(syms, this)) + def withMappedSyms(syms: List[Symbol], mapAlways: Boolean = false): TreeTypeMap = + withMappedSyms(syms, ctx.mapSymbols(syms, this, mapAlways)) /** The tree map with the substitution between originals `syms` * and mapped symbols `mapped`. Also goes into mapped classes * and substitutes their declarations. */ - def withMappedSyms(syms: List[Symbol], mapped: List[Symbol]): TreeTypeMap = - if (mapped eq syms) this - else { - val substMap = withSubstitution(syms, mapped) - val mappedClasses = mapped.filter(_.isClass) - (substMap /: mappedClasses) { (tmap, cls) => - val origDcls = cls.decls.toList - val mappedDcls = ctx.mapSymbols(origDcls, tmap) - val tmap1 = tmap.withMappedSyms(origDcls, mappedDcls) - (origDcls, mappedDcls).zipped.foreach(cls.asClass.replace) - tmap1 - } + def withMappedSyms(syms: List[Symbol], mapped: List[Symbol]): TreeTypeMap = { + val symsChanged = syms ne mapped + val substMap = withSubstitution(syms, mapped) + val fullMap = (substMap /: mapped.filter(_.isClass)) { (tmap, cls) => + val origDcls = cls.decls.toList + val mappedDcls = ctx.mapSymbols(origDcls, tmap) + val tmap1 = tmap.withMappedSyms(origDcls, mappedDcls) + if (symsChanged) (origDcls, mappedDcls).zipped.foreach(cls.asClass.replace) + tmap1 } + if (symsChanged || (fullMap eq substMap)) fullMap + else withMappedSyms(syms, mapAlways = true) + } } diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index cedc0adc8..83fb2c134 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -267,10 +267,10 @@ trait Symbols { this: Context => * Cross symbol references are brought over from originals to copies. * Do not copy any symbols if all attributes of all symbols stay the same. */ - def mapSymbols(originals: List[Symbol], ttmap: TreeTypeMap): List[Symbol] = - if (originals forall (sym => + def mapSymbols(originals: List[Symbol], ttmap: TreeTypeMap, mapAlways: Boolean = false): List[Symbol] = + if (originals.forall(sym => (ttmap.mapType(sym.info) eq sym.info) && - !(ttmap.oldOwners contains sym.owner))) + !(ttmap.oldOwners contains sym.owner)) && !mapAlways) originals else { val copies: List[Symbol] = for (original <- originals) yield -- cgit v1.2.3