Skip to content

Commit d86372f

Browse files
committed
Make computeDenot take overrides into account
If previous denotation was a sym denotation, it might be overridden by a different symbol in a new phase or run. So it is not correct to simply return the current version of the symbol, as was done before. We now recompute the member if there is a chance that the symbol could be overridden.
1 parent 4808d1d commit d86372f

File tree

1 file changed

+30
-18
lines changed

1 file changed

+30
-18
lines changed

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

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,17 @@ object Types {
126126
false
127127
}
128128

129+
/** Same as `isRef`, but follows more types: all type proxies as well as and- and or-types */
130+
private[Types] def isWeakRef(sym: Symbol)(implicit ctx: Context): Boolean = stripTypeVar match {
131+
case tp: NamedType => tp.info.isWeakRef(sym)
132+
case tp: ClassInfo => tp.cls eq sym
133+
case tp: Types.ThisType => tp.cls eq sym
134+
case tp: TypeProxy => tp.underlying.isWeakRef(sym)
135+
case tp: AndType => tp.tp1.isWeakRef(sym) && tp.tp2.isWeakRef(sym)
136+
case tp: OrType => tp.tp1.isWeakRef(sym) || tp.tp2.isWeakRef(sym)
137+
case _ => false
138+
}
139+
129140
/** Is this type an instance of a non-bottom subclass of the given class `cls`? */
130141
final def derivesFrom(cls: Symbol)(implicit ctx: Context): Boolean = this match {
131142
case tp: TypeRef =>
@@ -1216,27 +1227,17 @@ object Types {
12161227
val sym = lastSymbol
12171228
if (sym == null) loadDenot else denotOfSym(sym)
12181229
case d: SymDenotation =>
1219-
if ( d.validFor.runId == ctx.runId
1220-
|| ctx.stillValid(d)
1221-
|| this.isInstanceOf[WithFixedSym]) d.current
1230+
if (this.isInstanceOf[WithFixedSym]) d.current
1231+
else if (d.validFor.runId == ctx.runId || ctx.stillValid(d))
1232+
if (prefix.isWeakRef(d.owner) || d.isConstructor) d.current
1233+
else recomputeMember(d) // symbol could have been overridden, recompute membership
12221234
else {
12231235
val newd = loadDenot
12241236
if (newd.exists) newd else d.staleSymbolError
12251237
}
12261238
case d =>
1227-
if (d.validFor.runId != ctx.period.runId)
1228-
loadDenot
1229-
// The following branch was used to avoid an assertErased error.
1230-
// It's idea was to void keeping non-sym denotations after erasure
1231-
// since they violate the assertErased contract. But the problem is
1232-
// that when seen again in an earlier phase the denotation is
1233-
// still seen as a SymDenotation, whereas it should be a SingleDenotation.
1234-
// That's why the branch is disabled.
1235-
//
1236-
// else if (ctx.erasedTypes && lastSymbol != null)
1237-
// denotOfSym(lastSymbol)
1238-
else
1239-
d.current
1239+
if (d.validFor.runId != ctx.period.runId) loadDenot
1240+
else d.current
12401241
}
12411242
if (ctx.typerState.ephemeral) record("ephemeral cache miss: loadDenot")
12421243
else if (d.exists) {
@@ -1245,14 +1246,25 @@ object Types {
12451246
// phase but a defined denotation earlier (e.g. a TypeRef to an abstract type
12461247
// is undefined after erasure.) We need to be able to do time travel back and
12471248
// forth also in these cases.
1248-
setDenot(d)
1249+
1250+
// Don't use setDenot here; double binding checks can give spurious failures after erasure
1251+
lastDenotation = d
1252+
lastSymbol = d.symbol
12491253
checkedPeriod = ctx.period
12501254
}
12511255
d
12521256
}
12531257
finally ctx.typerState.ephemeral |= savedEphemeral
12541258
}
12551259

1260+
/** A member of `prefix` (disambiguated by `d.signature`) or, if none was found, `d.current`. */
1261+
private def recomputeMember(d: SymDenotation)(implicit ctx: Context): Denotation =
1262+
asMemberOf(prefix) match {
1263+
case NoDenotation => d.current
1264+
case newd: SingleDenotation => newd
1265+
case newd => newd.atSignature(d.signature).orElse(d.current)
1266+
}
1267+
12561268
private def denotOfSym(sym: Symbol)(implicit ctx: Context): Denotation = {
12571269
val d = sym.denot
12581270
val owner = d.owner
@@ -1275,7 +1287,7 @@ object Types {
12751287
// for overriddenBySynthetic symbols a TermRef such as SomeCaseClass.this.hashCode
12761288
// might be rewritten from Object#hashCode to the hashCode generated at SyntheticMethods
12771289
),
1278-
s"data race? overwriting symbol of ${this.show} / $this / ${this.getClass} / ${lastSymbol.id} / ${sym.id}")
1290+
s"data race? overwriting symbol of ${this.show} / $this / ${this.getClass} / ${lastSymbol.id} / ${sym.id} / ${sym.owner} / ${lastSymbol.owner} / ${ctx.phase}")
12791291

12801292
protected def sig: Signature = Signature.NotAMethod
12811293

0 commit comments

Comments
 (0)