aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-09-13 16:37:06 +0200
committerMartin Odersky <odersky@gmail.com>2014-09-13 17:59:06 +0200
commit5634dcc1490de05dbf5b3f2637a7e0eb4be8d6d0 (patch)
tree3ba58f946ecb4efcef86a25cfdc52bc7b0cffab6 /src/dotty/tools
parent2317764b683fe548f7c5e3b5ee5ede9760433c61 (diff)
downloaddotty-5634dcc1490de05dbf5b3f2637a7e0eb4be8d6d0.tar.gz
dotty-5634dcc1490de05dbf5b3f2637a7e0eb4be8d6d0.tar.bz2
dotty-5634dcc1490de05dbf5b3f2637a7e0eb4be8d6d0.zip
Better TreeTypeMaps
1. They now keep track of changed constructors in templates, updating the class scope as for other members. 2. Any changed members are now entered into the new class scope at exactly the same position as the old one. That ensures that things like caseAccessors still work. 3. ChangeOwners now is reflected in the prefixes of any named types. 4. Newly created classes now get their own ClassInfo type. 5. TreeTypeMaps always crete "fresh" symbols. Fresh symbols do not share a NamedType reference with an existing reference to some other symbol. This obviates b2e0e7b4, which will be reverted. To make it work, the interface of TreeMap changed from an ownerMap function to a substitution-like data structure working with two lists.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/ast/TreeTypeMap.scala80
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala4
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala4
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala6
-rw-r--r--src/dotty/tools/dotc/core/Scopes.scala16
-rw-r--r--src/dotty/tools/dotc/core/Substituters.scala2
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala19
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala19
-rw-r--r--src/dotty/tools/dotc/core/Types.scala53
-rw-r--r--src/dotty/tools/dotc/transform/FullParameterization.scala6
10 files changed, 151 insertions, 58 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
index 2adc6cd5d..bb8937aed 100644
--- a/src/dotty/tools/dotc/ast/TreeTypeMap.scala
+++ b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
@@ -15,9 +15,13 @@ import Denotations._, Decorators._
* @param ownerMap A function that translates owners of top-level local symbols
* defined in the mapped tree.
* @param treeMap A transformer that translates all encountered subtrees in
- * prefix traversal order.
- * @param substFrom The symbols that need to be substituted
- * @param substTo The substitution targets
+ * prefix traversal orders
+ * @param oldOwners Previous owners. If a top-level local symbol in the mapped tree
+ * has one of these as an owner, the owner is replaced by the corresponding
+ * symbol in `newOwners`.
+ * @param newOwners New owners, replacing previous owners.
+ * @param substFrom The symbols that need to be substituted.
+ * @param substTo The substitution targets.
*
* The reason the substitution is broken out from the rest of the type map is
* that all symbols have to be substituted at the same time. If we do not do this,
@@ -30,28 +34,64 @@ import Denotations._, Decorators._
*/
final class TreeTypeMap(
val typeMap: Type => Type = IdentityTypeMap,
- val ownerMap: Symbol => Symbol = identity _,
val treeMap: tpd.Tree => tpd.Tree = identity _,
+ val oldOwners: List[Symbol] = Nil,
+ val newOwners: List[Symbol] = Nil,
val substFrom: List[Symbol] = Nil,
val substTo: List[Symbol] = Nil)(implicit ctx: Context) extends tpd.TreeMap {
import tpd._
- def mapType(tp: Type) = typeMap(tp).substSym(substFrom, substTo)
+ /** If `sym` is one of `oldOwners`, replace by corresponding symbol in `newOwners` */
+ def mapOwner(sym: Symbol) = {
+ def loop(from: List[Symbol], to: List[Symbol]): Symbol =
+ if (from.isEmpty) sym
+ else if (sym eq from.head) to.head
+ else loop(from.tail, to.tail)
+ loop(oldOwners, newOwners)
+ }
+
+ /** Replace occurrences of `This(oldOwner)` in some prefix of a type
+ * by the corresponding `This(newOwner)`.
+ */
+ private val mapOwnerThis = new TypeMap {
+ private def mapPrefix(from: List[Symbol], to: List[Symbol], tp: Type): Type = from match {
+ case Nil => tp
+ case (cls: ClassSymbol) :: from1 => mapPrefix(from1, to.tail, tp.substThis(cls, to.head.thisType))
+ case _ :: from1 => mapPrefix(from1, to.tail, tp)
+ }
+ def apply(tp: Type): Type = tp match {
+ case tp: NamedType => tp.derivedSelect(mapPrefix(oldOwners, newOwners, tp.prefix))
+ case _ => mapOver(tp)
+ }
+ }
+
+ def mapType(tp: Type) =
+ mapOwnerThis(typeMap(tp).substSym(substFrom, substTo))
+
+ private def updateDecls(prevStats: List[Tree], newStats: List[Tree]): Unit =
+ if (prevStats.isEmpty) assert(newStats.isEmpty)
+ else {
+ prevStats.head match {
+ case pdef: MemberDef =>
+ val prevSym = pdef.symbol
+ val newSym = newStats.head.symbol
+ val newCls = newSym.owner.asClass
+ if (prevSym != newSym) newCls.replace(prevSym, newSym)
+ case _ =>
+ }
+ updateDecls(prevStats.tail, newStats.tail)
+ }
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = treeMap(tree) match {
case impl @ Template(constr, parents, self, body) =>
val tmap = withMappedSyms(impl.symbol :: impl.constr.symbol :: Nil)
- val constr1 = tmap.transformSub(constr)
val parents1 = parents mapconserve transform
- var self1 = transformDefs(self :: Nil)._2.head
+ val (_, constr1 :: self1 :: Nil) = transformDefs(constr :: self :: Nil)
val body1 = tmap.transformStats(body)
- body1 foreach {
- case mdef: MemberDef =>
- val member = mdef.symbol
- member.owner.asClass.enter(member, replace = true)
- case _ =>
- }
- cpy.Template(impl)(constr1, parents1, self1, body1).withType(tmap.mapType(impl.tpe))
+ 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) =>
@@ -104,15 +144,19 @@ final class TreeTypeMap(
if (from eq to) this
else {
// assert that substitution stays idempotent, assuming its parts are
+ // TODO: It might be better to cater for the asserted-away conditions, by
+ // setting up a proper substitution abstraction with a compose operator that
+ // guarantees idempotence. But this might be too inefficient in some cases.
+ // We'll cross that bridge when we need to.
assert(!from.exists(substTo contains _))
assert(!to.exists(substFrom contains _))
+ assert(!from.exists(oldOwners contains _))
+ assert(!to.exists(newOwners contains _))
new TreeTypeMap(
typeMap,
- ownerMap andThen { sym =>
- val idx = from.indexOf(sym)
- if (idx >= 0) to(idx) else sym
- },
treeMap,
+ from ++ oldOwners,
+ to ++ newOwners,
from ++ substFrom,
to ++ substTo)
}
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index 49294718b..ab8cf89a7 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -244,12 +244,12 @@ object Trees {
private[this] var myTpe: T = _
/** Destructively set the type of the tree. This should be called only when it is known that
- * it is safe under sharing to do so. One user-case is in the withType method below
+ * it is safe under sharing to do so. One use-case is in the withType method below
* which implements copy-on-write. Another use-case is in method interpolateAndAdapt in Typer,
* where we overwrite with a simplified version of the type itself.
*/
private[dotc] def overwriteType(tpe: T) = {
- if (this.isInstanceOf[Template[_]]) assert(tpe.isInstanceOf[WithNonMemberSym], s"$this <--- $tpe")
+ if (this.isInstanceOf[Template[_]]) assert(tpe.isInstanceOf[WithFixedSym], s"$this <--- $tpe")
myTpe = tpe
}
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index c0ebf4d61..cb1a265c3 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -512,7 +512,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
new TreeTypeMap(substFrom = from, substTo = to).apply(tree)
def changeOwner(from: Symbol, to: Symbol)(implicit ctx: Context): ThisTree =
- new TreeTypeMap(ownerMap = (sym => if (sym == from) to else sym)).apply(tree)
+ new TreeTypeMap(oldOwners = from :: Nil, newOwners = to :: Nil).apply(tree)
def select(name: Name)(implicit ctx: Context): Select =
Select(tree, name)
@@ -522,7 +522,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def select(sym: Symbol)(implicit ctx: Context): Select =
untpd.Select(tree, sym.name).withType(
- if (ctx.erasedTypes) TermRef.withNonMemberSym(tree.tpe, sym.name.asTermName, sym.asTerm)
+ if (ctx.erasedTypes) TermRef.withFixedSym(tree.tpe, sym.name.asTermName, sym.asTerm)
else TermRef.withSigAndDenot(tree.tpe, sym.name.asTermName, sym.signature, sym.denot.asSeenFrom(tree.tpe)))
def selectWithSig(name: Name, sig: Signature)(implicit ctx: Context) =
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index f89a5ce46..896de25fd 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -356,6 +356,9 @@ object Flags {
// Flags following this one are not pickled
+ /** Symbol always defines a fresh named type */
+ final val Fresh = commonFlag(45, "<fresh>")
+
/** Symbol is defined in a super call */
final val InSuperCall = commonFlag(46, "<in supercall>")
@@ -434,7 +437,8 @@ object Flags {
final val FromStartFlags =
AccessFlags | Module | Package | Deferred | MethodOrHKCommon | Param | ParamAccessor | Scala2ExistentialCommon |
InSuperCall | Touched | Static | CovariantOrOuter | ContravariantOrLabel | ExpandedName | AccessorOrSealed |
- CaseAccessorOrTypeArgument | Frozen | Erroneous | ImplicitCommon | Permanent | SelfNameOrImplClass
+ CaseAccessorOrTypeArgument | Fresh | Frozen | Erroneous | ImplicitCommon | Permanent |
+ SelfNameOrImplClass
assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags)
// TODO: Should check that FromStartFlags do not change in completion
diff --git a/src/dotty/tools/dotc/core/Scopes.scala b/src/dotty/tools/dotc/core/Scopes.scala
index c8252e02e..54317a496 100644
--- a/src/dotty/tools/dotc/core/Scopes.scala
+++ b/src/dotty/tools/dotc/core/Scopes.scala
@@ -37,7 +37,9 @@ object Scopes {
*/
private final val MaxRecursions = 1000
- class ScopeEntry private[Scopes] (val name: Name, val sym: Symbol, val owner: Scope) {
+ class ScopeEntry private[Scopes] (val name: Name, _sym: Symbol, val owner: Scope) {
+
+ var sym: Symbol = _sym
/** the next entry in the hash bucket
*/
@@ -249,6 +251,18 @@ object Scopes {
}
}
+ /** Replace symbol `prev` (if it exists in current scope) by symbol `replacement`.
+ * @pre `prev` and `replacement` have the same name.
+ */
+ final def replace(prev: Symbol, replacement: Symbol)(implicit ctx: Context): Unit = {
+ require(prev.name == replacement.name)
+ var e = lookupEntry(prev.name)
+ while (e ne null) {
+ if (e.sym == prev) e.sym = replacement
+ e = lookupNextEntry(e)
+ }
+ }
+
/** Lookup a symbol entry matching given name.
*/
override final def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = {
diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala
index a7977dc2b..02d09d542 100644
--- a/src/dotty/tools/dotc/core/Substituters.scala
+++ b/src/dotty/tools/dotc/core/Substituters.scala
@@ -132,7 +132,7 @@ trait Substituters { this: Context =>
while (fs.nonEmpty) {
if (fs.head eq sym)
return tp match {
- case tp: WithNonMemberSym => NamedType.withNonMemberSym(tp.prefix, ts.head)
+ case tp: WithFixedSym => NamedType.withFixedSym(tp.prefix, ts.head)
case _ => substSym(tp.prefix, from, to, theMap) select ts.head
}
fs = fs.tail
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index c9777ebf6..aed55e49a 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -867,7 +867,7 @@ object SymDenotations {
TermRef.withSigAndDenot(owner.thisType, name.asTermName, signature, this)
def nonMemberTermRef(implicit ctx: Context): TermRef =
- TermRef.withNonMemberSym(owner.thisType, name.asTermName, symbol.asTerm)
+ TermRef.withFixedSym(owner.thisType, name.asTermName, symbol.asTerm)
/** The variance of this type parameter or type member as an Int, with
* +1 = Covariant, -1 = Contravariant, 0 = Nonvariant, or not a type parameter
@@ -1182,15 +1182,13 @@ object SymDenotations {
* someone does a findMember on a subclass.
* @param scope The scope in which symbol should be entered.
* If this is EmptyScope, the scope is `decls`.
- * @param replace Replace any existing symbol with same name.
- * This is always done if this denotes a package class.
*/
- def enter(sym: Symbol, scope: Scope = EmptyScope, replace: Boolean = false)(implicit ctx: Context): Unit = {
+ def enter(sym: Symbol, scope: Scope = EmptyScope)(implicit ctx: Context): Unit = {
val mscope = scope match {
case scope: MutableScope => scope
case _ => decls.asInstanceOf[MutableScope]
}
- if (replace || (this is PackageClass)) {
+ if (this is PackageClass) {
val entry = mscope.lookupEntry(sym.name)
if (entry != null) {
if (entry.sym == sym) return
@@ -1212,6 +1210,17 @@ object SymDenotations {
myMemberCache invalidate sym.name
}
+ /** Replace symbol `prev` (if defined in current class) by symbol `replacement`.
+ * If `prev` is not defined in current class, do nothing.
+ * @pre `prev` and `replacement` have the same name.
+ */
+ def replace(prev: Symbol, replacement: Symbol)(implicit ctx: Context): Unit = {
+ require(!(this is Frozen))
+ decls.asInstanceOf[MutableScope].replace(prev, replacement)
+ if (myMemberCache != null)
+ myMemberCache invalidate replacement.name
+ }
+
/** Delete symbol from current scope.
* Note: We require that this does not happen after the first time
* someone does a findMember on a subclass.
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index 96819f627..0174f75cf 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -269,7 +269,8 @@ trait Symbols { this: Context =>
*/
def mapSymbols(originals: List[Symbol], ttmap: TreeTypeMap) =
if (originals forall (sym =>
- (ttmap.mapType(sym.info) eq sym.info) && (ttmap.ownerMap(sym.owner) eq sym.owner)))
+ (ttmap.mapType(sym.info) eq sym.info) &&
+ !(ttmap.oldOwners contains sym.owner)))
originals
else {
val copies: List[Symbol] = for (original <- originals) yield
@@ -285,11 +286,18 @@ trait Symbols { this: Context =>
}
(originals, copies).zipped foreach {(original, copy) =>
val odenot = original.denot
+ val oinfo = original.info match {
+ case ClassInfo(pre, _, parents, decls, selfInfo) =>
+ assert(original.isClass)
+ ClassInfo(pre, copy.asClass, parents, decls, selfInfo)
+ case oinfo => oinfo
+ }
copy.denot = odenot.copySymDenotation(
symbol = copy,
- owner = ttmap1.ownerMap(odenot.owner),
- info = ttmap1.mapType(odenot.info),
- privateWithin = ttmap1.ownerMap(odenot.privateWithin), // since this refers to outer symbols, need not include copies (from->to) in ownermap here.
+ owner = ttmap1.mapOwner(odenot.owner),
+ initFlags = odenot.flags &~ Frozen | Fresh,
+ info = ttmap1.mapType(oinfo),
+ privateWithin = ttmap1.mapOwner(odenot.privateWithin), // since this refers to outer symbols, need not include copies (from->to) in ownermap here.
annotations = odenot.annotations.mapConserve(ttmap1.apply))
}
copies
@@ -362,6 +370,9 @@ object Symbols {
final def asType(implicit ctx: Context): TypeSymbol = { assert(isType, s"isType called on not-a-Type $this"); asInstanceOf[TypeSymbol] }
final def asClass: ClassSymbol = asInstanceOf[ClassSymbol]
+ final def isFresh(implicit ctx: Context) =
+ lastDenot != null && (lastDenot is Fresh)
+
/** Special cased here, because it may be used on naked symbols in substituters */
final def isStatic(implicit ctx: Context): Boolean =
lastDenot != null && denot.isStatic
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index c8c5bd80e..bbec70404 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1150,7 +1150,7 @@ object Types {
case d: SymDenotation =>
if ( d.validFor.runId == ctx.runId
|| ctx.stillValid(d)
- || this.isInstanceOf[WithNonMemberSym]) d.current
+ || this.isInstanceOf[WithFixedSym]) d.current
else {
val newd = loadDenot
if (newd.exists) newd else d.staleSymbolError
@@ -1402,7 +1402,7 @@ object Types {
override def computeHash = doHash((name, sig), prefix)
}
- trait WithNonMemberSym extends NamedType {
+ trait WithFixedSym extends NamedType {
def fixedSym: Symbol
assert(fixedSym ne NoSymbol)
uncheckedSetSym(fixedSym)
@@ -1416,8 +1416,11 @@ object Types {
override def withSym(sym: Symbol, signature: Signature)(implicit ctx: Context): ThisType =
unsupported("withSym")
+ override def newLikeThis(prefix: Type)(implicit ctx: Context): NamedType =
+ NamedType.withFixedSym(prefix, fixedSym)
+
override def equals(that: Any) = that match {
- case that: WithNonMemberSym => this.prefix == that.prefix && (this.fixedSym eq that.fixedSym)
+ case that: WithFixedSym => this.prefix == that.prefix && (this.fixedSym eq that.fixedSym)
case _ => false
}
override def computeHash = doHash(fixedSym, prefix)
@@ -1435,8 +1438,8 @@ object Types {
override def computeHash = unsupported("computeHash")
}
- final class NonMemberTermRef(prefix: Type, name: TermName, val fixedSym: TermSymbol) extends TermRef(prefix, name) with WithNonMemberSym
- final class NonMemberTypeRef(prefix: Type, name: TypeName, val fixedSym: TypeSymbol) extends TypeRef(prefix, name) with WithNonMemberSym
+ final class TermRefWithFixedSym(prefix: Type, name: TermName, val fixedSym: TermSymbol) extends TermRef(prefix, name) with WithFixedSym
+ final class TypeRefWithFixedSym(prefix: Type, name: TypeName, val fixedSym: TypeSymbol) extends TypeRef(prefix, name) with WithFixedSym
/** Assert current phase does not have erasure semantics */
private def assertUnerased()(implicit ctx: Context) =
@@ -1449,9 +1452,9 @@ object Types {
def apply(prefix: Type, name: Name, denot: Denotation)(implicit ctx: Context) =
if (name.isTermName) TermRef(prefix, name.asTermName, denot)
else TypeRef(prefix, name.asTypeName, denot)
- def withNonMemberSym(prefix: Type, sym: Symbol)(implicit ctx: Context) =
- if (sym.isType) TypeRef.withNonMemberSym(prefix, sym.name.asTypeName, sym.asType)
- else TermRef.withNonMemberSym(prefix, sym.name.asTermName, sym.asTerm)
+ def withFixedSym(prefix: Type, sym: Symbol)(implicit ctx: Context) =
+ if (sym.isType) TypeRef.withFixedSym(prefix, sym.name.asTypeName, sym.asType)
+ else TermRef.withFixedSym(prefix, sym.name.asTermName, sym.asTerm)
def withSymAndName(prefix: Type, sym: Symbol, name: Name)(implicit ctx: Context): NamedType =
if (sym.isType) TypeRef.withSymAndName(prefix, sym.asType, name.asTypeName)
else TermRef.withSymAndName(prefix, sym.asTerm, name.asTermName)
@@ -1479,7 +1482,8 @@ object Types {
* signature, if denotation is not yet completed.
*/
def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef = {
- if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm)
+ if ((prefix eq NoPrefix) || denot.symbol.isFresh)
+ apply(prefix, denot.symbol.asTerm)
else denot match {
case denot: SymDenotation if denot.isCompleted => withSig(prefix, name, denot.signature)
case _ => all(prefix, name)
@@ -1489,8 +1493,8 @@ object Types {
/** Create a non-member term ref (which cannot be reloaded using `member`),
* with given prefix, name, and signature
*/
- def withNonMemberSym(prefix: Type, name: TermName, sym: TermSymbol)(implicit ctx: Context): TermRef =
- unique(new NonMemberTermRef(prefix, name, sym))
+ def withFixedSym(prefix: Type, name: TermName, sym: TermSymbol)(implicit ctx: Context): TermRef =
+ unique(new TermRefWithFixedSym(prefix, name, sym))
/** Create a term ref referring to given symbol with given name, taking the signature
* from the symbol if it is completed, or creating a term ref without
@@ -1500,8 +1504,8 @@ object Types {
* (2) The name in the term ref need not be the same as the name of the Symbol.
*/
def withSymAndName(prefix: Type, sym: TermSymbol, name: TermName)(implicit ctx: Context): TermRef =
- if (prefix eq NoPrefix)
- withNonMemberSym(prefix, name, sym)
+ if ((prefix eq NoPrefix) || sym.isFresh)
+ withFixedSym(prefix, name, sym)
else if (sym.defRunId != NoRunId && sym.isCompleted)
withSig(prefix, name, sym.signature) withSym (sym, sym.signature)
else
@@ -1511,7 +1515,7 @@ object Types {
* (which must be completed).
*/
def withSig(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
- if (prefix eq NoPrefix) withNonMemberSym(prefix, sym.name, sym)
+ if ((prefix eq NoPrefix) || sym.isFresh) withFixedSym(prefix, sym.name, sym)
else withSig(prefix, sym.name, sym.signature).withSym(sym, sym.signature)
/** Create a term ref with given prefix, name and signature */
@@ -1519,9 +1523,12 @@ object Types {
unique(new TermRefWithSignature(prefix, name, sig))
/** Create a term ref with given prefix, name, signature, and initial denotation */
- def withSigAndDenot(prefix: Type, name: TermName, sig: Signature, denot: Denotation)(implicit ctx: Context): TermRef =
- (if (prefix eq NoPrefix) withNonMemberSym(prefix, denot.symbol.asTerm.name, denot.symbol.asTerm)
- else withSig(prefix, name, sig)) withDenot denot
+ def withSigAndDenot(prefix: Type, name: TermName, sig: Signature, denot: Denotation)(implicit ctx: Context): TermRef = {
+ if ((prefix eq NoPrefix) || denot.symbol.isFresh)
+ withFixedSym(prefix, denot.symbol.asTerm.name, denot.symbol.asTerm)
+ else
+ withSig(prefix, name, sig)
+ } withDenot denot
}
object TypeRef {
@@ -1536,8 +1543,8 @@ object Types {
/** Create a non-member type ref (which cannot be reloaded using `member`),
* with given prefix, name, and symbol.
*/
- def withNonMemberSym(prefix: Type, name: TypeName, sym: TypeSymbol)(implicit ctx: Context): TypeRef =
- unique(new NonMemberTypeRef(prefix, name, sym))
+ def withFixedSym(prefix: Type, name: TypeName, sym: TypeSymbol)(implicit ctx: Context): TypeRef =
+ unique(new TypeRefWithFixedSym(prefix, name, sym))
/** Create a type ref referring to given symbol with given name.
* This is very similar to TypeRef(Type, Symbol),
@@ -1546,12 +1553,14 @@ object Types {
* (2) The name in the type ref need not be the same as the name of the Symbol.
*/
def withSymAndName(prefix: Type, sym: TypeSymbol, name: TypeName)(implicit ctx: Context): TypeRef =
- if (prefix eq NoPrefix) withNonMemberSym(prefix, name, sym)
+ if ((prefix eq NoPrefix) || sym.isFresh) withFixedSym(prefix, name, sym)
else apply(prefix, name).withSym(sym, Signature.NotAMethod)
/** Create a type ref with given name and initial denotation */
- def apply(prefix: Type, name: TypeName, denot: Denotation)(implicit ctx: Context): TypeRef =
- (if (prefix eq NoPrefix) apply(prefix, denot.symbol.asType) else apply(prefix, name)) withDenot denot
+ def apply(prefix: Type, name: TypeName, denot: Denotation)(implicit ctx: Context): TypeRef = {
+ if ((prefix eq NoPrefix) || denot.symbol.isFresh) apply(prefix, denot.symbol.asType)
+ else apply(prefix, name)
+ } withDenot denot
}
// --- Other SingletonTypes: ThisType/SuperType/ConstantType ---------------------------
diff --git a/src/dotty/tools/dotc/transform/FullParameterization.scala b/src/dotty/tools/dotc/transform/FullParameterization.scala
index cdea5754c..698a57c61 100644
--- a/src/dotty/tools/dotc/transform/FullParameterization.scala
+++ b/src/dotty/tools/dotc/transform/FullParameterization.scala
@@ -204,11 +204,13 @@ trait FullParameterization {
.substDealias(origTParams, trefs)
.subst(origVParams, argRefs.map(_.tpe))
.substThisUnlessStatic(origClass, thisRef.tpe),
- ownerMap = (sym => if (sym eq origMeth) derived else sym),
treeMap = {
case tree: This if tree.symbol == origClass => thisRef
case tree => rewireTree(tree, Nil) orElse tree
- }).transform(originalDef.rhs)
+ },
+ oldOwners = origMeth :: Nil,
+ newOwners = derived :: Nil
+ ).transform(originalDef.rhs)
})
/** A forwarder expression which calls `derived`, passing along