Skip to content

Commit 47f0b45

Browse files
committed
Fix class decls in TypeTypeMap
If definitions in a class are substituted by TreeTypeMap, the new symbols have to show up in the `decls` scope of the class instead of the old ones.
1 parent 81b27b1 commit 47f0b45

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

src/dotty/tools/dotc/ast/TreeTypeMap.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ final class TreeTypeMap(
4545
val parents1 = parents mapconserve transform
4646
var self1 = transformDefs(self :: Nil)._2.head
4747
val body1 = tmap.transformStats(body)
48+
body1 foreach {
49+
case mdef: MemberDef =>
50+
val member = mdef.symbol
51+
member.owner.asClass.enter(member, replace = true)
52+
case _ =>
53+
}
4854
cpy.Template(impl)(constr1, parents1, self1, body1).withType(tmap.mapType(impl.tpe))
4955
case tree1 =>
5056
tree1.withType(mapType(tree1.tpe)) match {

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,14 @@ object SymDenotations {
662662
if (cls.effectiveName == name || !cls.exists) cls else cls.owner.enclosingClassNamed(name)
663663
}
664664

665+
/** The closest enclosing method containing this definition.
666+
* A local dummy owner is mapped to the primary constructor of the class.
667+
*/
668+
final def enclosingMethod(implicit ctx: Context): Symbol =
669+
if (this is Method) symbol
670+
else if (this.isClass) primaryConstructor
671+
else owner.enclosingMethod
672+
665673
/** The top-level class containing this denotation,
666674
* except for a toplevel module, where its module class is returned.
667675
*/
@@ -901,7 +909,7 @@ object SymDenotations {
901909
privateWithin: Symbol = null,
902910
annotations: List[Annotation] = null)(implicit ctx: Context) =
903911
{ // simulate default parameters, while also passing implicit context ctx to the default values
904-
val initFlags1 = if (initFlags != UndefinedFlags) initFlags else this.flags
912+
val initFlags1 = if (initFlags != UndefinedFlags) initFlags else this.flags &~ Frozen
905913
val info1 = if (info != null) info else this.info
906914
val privateWithin1 = if (privateWithin != null) privateWithin else this.privateWithin
907915
val annotations1 = if (annotations != null) annotations else this.annotations
@@ -1172,23 +1180,28 @@ object SymDenotations {
11721180
/** Enter a symbol in current scope.
11731181
* Note: We require that this does not happen after the first time
11741182
* someone does a findMember on a subclass.
1183+
* @param scope The scope in which symbol should be entered.
1184+
* If this is EmptyScope, the scope is `decls`.
1185+
* @param replace Replace any existing symbol with same name.
1186+
* This is always done if this denotes a package class.
11751187
*/
1176-
def enter(sym: Symbol, scope: Scope = EmptyScope)(implicit ctx: Context): Unit = {
1188+
def enter(sym: Symbol, scope: Scope = EmptyScope, replace: Boolean = false)(implicit ctx: Context): Unit = {
11771189
val mscope = scope match {
11781190
case scope: MutableScope => scope
11791191
case _ => decls.asInstanceOf[MutableScope]
11801192
}
1181-
if (this is PackageClass) { // replace existing symbols
1193+
if (replace || (this is PackageClass)) {
11821194
val entry = mscope.lookupEntry(sym.name)
11831195
if (entry != null) {
1196+
if (entry.sym == sym) return
11841197
mscope.unlink(entry)
11851198
entry.sym.denot = sym.denot // to avoid stale symbols
11861199
}
11871200
}
11881201
enterNoReplace(sym, mscope)
11891202
}
11901203

1191-
/** Enter a symbol in current scope without potentially replacing the old copy. */
1204+
/** Enter a symbol in given `scope` without potentially replacing the old copy. */
11921205
def enterNoReplace(sym: Symbol, scope: MutableScope)(implicit ctx: Context): Unit = {
11931206
require(!(this is Frozen))
11941207
scope.enter(sym)

0 commit comments

Comments
 (0)