Skip to content

Commit 09a4bc5

Browse files
oderskyDarkDimius
authored andcommitted
Reworked TermRef handling
The main problem with TermRef handling was that signatures were not always tracked correctly. New invariant: A TermRef that points to a symbol is always a TermRefWithSig, and the signature is the one of the corresponding member. We achieve this by sometimes generating a new TermRefWithSig if a TermRef gets a denotation. One possible simplification would be to always store a signature in a TermRef. There's still a problem in TermRefWithSig#newLikeThis, which currently works only if the previously stored denotation references a symbol. We will need to generalize JointRefDenotation to contain multiple symbols for a complete fix.
1 parent 3486eb0 commit 09a4bc5

File tree

7 files changed

+137
-27
lines changed

7 files changed

+137
-27
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
2929
untpd.Select(qualifier, tp.name).withType(tp)
3030

3131
def Select(qualifier: Tree, sym: Symbol)(implicit ctx: Context): Select =
32-
untpd.Select(qualifier, sym.name).withType(qualifier.tpe select sym)
32+
untpd.Select(qualifier, sym.name).withType(
33+
TermRef.withSig(qualifier.tpe, sym.name.asTermName, sym.signature, sym.denot))
3334

3435
def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit ctx: Context) =
3536
untpd.SelectWithSig(qualifier, name, sig)
@@ -259,10 +260,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
259260
/** new C(args) */
260261
def New(tp: Type, args: List[Tree])(implicit ctx: Context): Apply = {
261262
val targs = tp.argTypes
263+
val constr = tp.typeSymbol.primaryConstructor.asTerm
262264
Apply(
263265
Select(
264266
New(tp withoutArgs targs),
265-
TermRef(tp.normalizedPrefix, tp.typeSymbol.primaryConstructor.asTerm))
267+
TermRef.withSig(tp.normalizedPrefix, constr))
266268
.appliedToTypes(targs),
267269
args)
268270
}

src/dotty/tools/dotc/config/Config.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ object Config {
1313
final val checkConstraintsNonCyclic = true
1414

1515
final val flagInstantiationToNothing = false
16+
17+
/** Enable noDoubleDef checking if option "-YnoDoubleDefs" is set.
18+
* The reason to have an option as well as the present global switch is
19+
* that the noDoubleDef checking is done in a hotspot, and we do not
20+
* want to incur the overhead of checking an option each time.
21+
*/
22+
final val checkTermRefs = false
1623

1724
/** Throw an exception if a deep subtype recursion is detected */
1825
final val flagDeepSubTypeRecursions = true

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ object Denotations {
334334
final def info(implicit ctx: Context) = infoOrCompleter
335335
final def validFor = denot1.validFor & denot2.validFor
336336
final def isType = false
337-
def signature(implicit ctx: Context) = multiHasNot("signature")
337+
final def signature(implicit ctx: Context) = Signature.OverloadedSignature
338338
def atSignature(sig: Signature)(implicit ctx: Context): SingleDenotation =
339339
denot1.atSignature(sig) orElse denot2.atSignature(sig)
340340
def current(implicit ctx: Context): Denotation =

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package dotty.tools.dotc
22
package core
33

4-
import Names._, Types._, Contexts._
4+
import Names._, Types._, Contexts._, StdNames._
55
import transform.Erasure.sigName
66

77
/** The signature of a denotation.
@@ -49,6 +49,10 @@ object Signature {
4949
* a type different from PolyType, MethodType, or ExprType.
5050
*/
5151
val NotAMethod = Signature(List(), EmptyTypeName)
52+
53+
/** The signature of an overloaded denotation.
54+
*/
55+
val OverloadedSignature = Signature(List(tpnme.OVERLOADED), EmptyTypeName)
5256

5357
/** The signature of a method with no parameters and result type `resultType`. */
5458
def apply(resultType: Type, isJava: Boolean)(implicit ctx: Context): Signature =

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ object StdNames {
109109
val MODULE_VAR_SUFFIX: N = "$module"
110110
val NAME_JOIN: N = NameTransformer.NAME_JOIN_STRING
111111
val USCORE_PARAM_PREFIX: N = "_$"
112+
val OVERLOADED: N = "<overloaded>"
112113
val PACKAGE: N = "package"
113114
val PACKAGE_CLS: N = "package$"
114115
val PROTECTED_PREFIX: N = "protected$"

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ trait Symbols { this: Context =>
245245
for (name <- names) {
246246
val tparam = newNakedSymbol[TypeName](NoCoord)
247247
tparamBuf += tparam
248-
trefBuf += TypeRef(owner.thisType, name) withSym tparam
248+
trefBuf += TypeRef(owner.thisType, name).withSym(tparam, Signature.NotAMethod)
249249
}
250250
val tparams = tparamBuf.toList
251251
val bounds = boundsFn(trefBuf.toList)
@@ -319,7 +319,7 @@ object Symbols {
319319
type ThisName <: Name
320320

321321
private[this] var _id: Int = nextId
322-
//assert(_id != 5859)
322+
//assert(_id != 12325)
323323

324324
/** The unique id of this symbol */
325325
def id = _id

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

Lines changed: 117 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,15 @@ object Types {
656656
if (res.exists) res else TypeRef(this, name, denot)
657657
}
658658

659+
/** The type <this . name> , reduced if possible, with given denotation if unreduced */
660+
def selectNonMember(name: Name, denot: Denotation)(implicit ctx: Context): Type = name match {
661+
case name: TermName =>
662+
TermRef(this, name, denot)
663+
case name: TypeName =>
664+
val res = lookupRefined(name)
665+
if (res.exists) res else TypeRef(this, name, denot)
666+
}
667+
659668
/** The type <this . name> with given symbol, reduced if possible */
660669
def select(sym: Symbol)(implicit ctx: Context): Type =
661670
if (sym.isTerm) TermRef(this, sym.asTerm)
@@ -991,6 +1000,8 @@ object Types {
9911000
val prefix: Type
9921001
val name: Name
9931002

1003+
type ThisType >: this.type <: NamedType
1004+
9941005
assert(prefix.isValueType || (prefix eq NoPrefix), s"invalid prefix $prefix")
9951006

9961007
private[this] var lastDenotation: Denotation = _
@@ -1049,19 +1060,48 @@ object Types {
10491060
if (owner.isTerm) d else d.asSeenFrom(prefix)
10501061
}
10511062

1052-
private[dotc] final def withDenot(denot: Denotation): this.type = {
1063+
private def checkSymAssign(sym: Symbol) =
1064+
assert(
1065+
(lastSymbol eq sym) ||
1066+
(lastSymbol eq null) ||
1067+
(lastSymbol.defRunId != sym.defRunId) ||
1068+
(lastSymbol.defRunId == NoRunId),
1069+
s"data race? overwriting symbol of $this / ${this.getClass} / ${lastSymbol.id} / ${sym.id}")
1070+
1071+
protected def sig: Signature = Signature.NotAMethod
1072+
1073+
private[dotc] def withDenot(denot: Denotation)(implicit ctx: Context): ThisType =
1074+
if (sig != denot.signature)
1075+
withSig(denot.signature).withDenot(denot).asInstanceOf[ThisType]
1076+
else {
1077+
setDenot(denot)
1078+
this
1079+
}
1080+
1081+
private[dotc] final def setDenot(denot: Denotation): Unit = {
1082+
if (Config.checkTermRefs) checkSymAssign(denot.symbol)
10531083
lastDenotation = denot
10541084
lastSymbol = denot.symbol
1055-
this
10561085
}
10571086

1058-
private[dotc] final def withSym(sym: Symbol): this.type = {
1087+
private[dotc] def withSym(sym: Symbol, signature: Signature)(implicit ctx: Context): ThisType =
1088+
if (sig != signature)
1089+
withSig(signature).withSym(sym, signature).asInstanceOf[ThisType]
1090+
else {
1091+
setSym(sym)
1092+
this
1093+
}
1094+
1095+
private[dotc] final def setSym(sym: Symbol): Unit = {
1096+
if (Config.checkTermRefs) checkSymAssign(sym)
10591097
lastDenotation = null
10601098
lastSymbol = sym
10611099
checkedPeriod = Nowhere
1062-
this
10631100
}
10641101

1102+
private def withSig(sig: Signature)(implicit ctx: Context): NamedType =
1103+
TermRef.withSig(prefix, name.asTermName, sig)
1104+
10651105
protected def loadDenot(implicit ctx: Context) = {
10661106
val d = prefix.member(name)
10671107
if (d.exists || ctx.phaseId == FirstPhaseId)
@@ -1136,6 +1176,9 @@ object Types {
11361176

11371177
abstract case class TermRef(override val prefix: Type, name: TermName) extends NamedType with SingletonType {
11381178

1179+
type ThisType = TermRef
1180+
1181+
//assert(name.toString != "<local Coder>")
11391182
override def underlying(implicit ctx: Context): Type = {
11401183
val d = denot
11411184
if (d.isOverloaded) NoType else d.info
@@ -1156,16 +1199,31 @@ object Types {
11561199
}
11571200

11581201
abstract case class TypeRef(override val prefix: Type, name: TypeName) extends NamedType {
1202+
1203+
type ThisType = TypeRef
1204+
11591205
override def underlying(implicit ctx: Context): Type = info
11601206
}
11611207

1162-
final class TermRefWithSignature(prefix: Type, name: TermName, val sig: Signature) extends TermRef(prefix, name) {
1208+
final class TermRefWithSignature(prefix: Type, name: TermName, override val sig: Signature) extends TermRef(prefix, name) {
11631209
assert(prefix ne NoPrefix)
11641210
override def signature(implicit ctx: Context) = sig
1165-
override def loadDenot(implicit ctx: Context): Denotation =
1166-
super.loadDenot.atSignature(sig)
1167-
override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRef =
1168-
TermRef.withSig(prefix, name, sig)
1211+
override def loadDenot(implicit ctx: Context): Denotation = {
1212+
val d = super.loadDenot
1213+
if (sig eq Signature.OverloadedSignature) d
1214+
else d.atSignature(sig)
1215+
}
1216+
1217+
override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRef = {
1218+
if (sig != Signature.NotAMethod &&
1219+
sig != Signature.OverloadedSignature &&
1220+
symbol.exists) {
1221+
val ownSym = symbol
1222+
TermRef(prefix, name).withDenot(prefix.member(name).disambiguate(_ eq ownSym))
1223+
}
1224+
else TermRef.withSig(prefix, name, sig)
1225+
}
1226+
11691227
override def equals(that: Any) = that match {
11701228
case that: TermRefWithSignature =>
11711229
this.prefix == that.prefix &&
@@ -1177,15 +1235,25 @@ object Types {
11771235
override def computeHash = doHash((name, sig), prefix)
11781236
}
11791237

1180-
trait WithNoPrefix extends NamedType {
1238+
trait WithNonMemberSym extends NamedType {
11811239
def fixedSym: Symbol
11821240
assert(fixedSym ne NoSymbol)
1183-
withSym(fixedSym)
1241+
setSym(fixedSym)
1242+
1243+
override def withDenot(denot: Denotation)(implicit ctx: Context): ThisType = {
1244+
assert(denot.symbol eq fixedSym)
1245+
setDenot(denot)
1246+
this
1247+
}
1248+
1249+
override def withSym(sym: Symbol, signature: Signature)(implicit ctx: Context): ThisType =
1250+
unsupported("withSym")
1251+
11841252
override def equals(that: Any) = that match {
1185-
case that: WithNoPrefix => this.fixedSym eq that.fixedSym
1253+
case that: WithNonMemberSym => this.prefix == that.prefix && (this.fixedSym eq that.fixedSym)
11861254
case _ => false
11871255
}
1188-
override def computeHash = doHash(fixedSym)
1256+
override def computeHash = doHash(fixedSym, prefix)
11891257
}
11901258

11911259
final class CachedTermRef(prefix: Type, name: TermName, hc: Int) extends TermRef(prefix, name) {
@@ -1200,8 +1268,8 @@ object Types {
12001268
override def computeHash = unsupported("computeHash")
12011269
}
12021270

1203-
final class NoPrefixTermRef(name: TermName, val fixedSym: TermSymbol) extends TermRef(NoPrefix, name) with WithNoPrefix
1204-
final class NoPrefixTypeRef(name: TypeName, val fixedSym: TypeSymbol) extends TypeRef(NoPrefix, name) with WithNoPrefix
1271+
final class NonMemberTermRef(prefix: Type, name: TermName, val fixedSym: TermSymbol) extends TermRef(prefix, name) with WithNonMemberSym
1272+
final class NonMemberTypeRef(prefix: Type, name: TypeName, val fixedSym: TypeSymbol) extends TypeRef(prefix, name) with WithNonMemberSym
12051273

12061274
object NamedType {
12071275
def apply(prefix: Type, name: Name)(implicit ctx: Context) =
@@ -1210,20 +1278,42 @@ object Types {
12101278
def apply(prefix: Type, name: Name, denot: Denotation)(implicit ctx: Context) =
12111279
if (name.isTermName) TermRef(prefix, name.asTermName, denot)
12121280
else TypeRef(prefix, name.asTypeName, denot)
1281+
def withNonMemberSym(prefix: Type, sym: Symbol)(implicit ctx: Context) =
1282+
if (sym.isType) TypeRef.withNonMemberSym(prefix, sym.name.asTypeName, sym.asType)
1283+
else TermRef.withNonMemberSym(prefix, sym.name.asTermName, sym.asTerm)
12131284
}
12141285

12151286
object TermRef {
12161287
def apply(prefix: Type, name: TermName)(implicit ctx: Context): TermRef =
12171288
ctx.uniqueNamedTypes.enterIfNew(prefix, name).asInstanceOf[TermRef]
1289+
12181290
def apply(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
12191291
withSymAndName(prefix, sym, sym.name)
1292+
1293+
def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef = {
1294+
if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm)
1295+
else denot match {
1296+
case denot: SymDenotation if denot.isCompleted => withSig(prefix, name, denot.signature)
1297+
case _ => apply(prefix, name)
1298+
}
1299+
} withDenot denot
1300+
1301+
def withNonMemberSym(prefix: Type, name: TermName, sym: TermSymbol)(implicit ctx: Context): TermRef =
1302+
unique(new NonMemberTermRef(prefix, name, sym))
1303+
12201304
def withSymAndName(prefix: Type, sym: TermSymbol, name: TermName)(implicit ctx: Context): TermRef =
1221-
if (prefix eq NoPrefix) unique(new NoPrefixTermRef(name, sym))
1222-
else apply(prefix, name) withSym sym
1223-
def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef =
1224-
(if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm) else apply(prefix, name)) withDenot denot
1305+
if (prefix eq NoPrefix) withNonMemberSym(prefix, name, sym)
1306+
else {
1307+
if (sym.defRunId != NoRunId && sym.isCompleted) withSig(prefix, name, sym.signature)
1308+
else apply(prefix, name)
1309+
} withSym (sym, Signature.NotAMethod)
1310+
1311+
def withSig(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
1312+
unique(withSig(prefix, sym.name, sym.signature).withSym(sym, sym.signature))
1313+
12251314
def withSig(prefix: Type, name: TermName, sig: Signature)(implicit ctx: Context): TermRef =
12261315
unique(new TermRefWithSignature(prefix, name, sig))
1316+
12271317
def withSig(prefix: Type, name: TermName, sig: Signature, denot: Denotation)(implicit ctx: Context): TermRef =
12281318
(if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm)
12291319
else withSig(prefix, name, sig)) withDenot denot
@@ -1232,11 +1322,17 @@ object Types {
12321322
object TypeRef {
12331323
def apply(prefix: Type, name: TypeName)(implicit ctx: Context): TypeRef =
12341324
ctx.uniqueNamedTypes.enterIfNew(prefix, name).asInstanceOf[TypeRef]
1325+
12351326
def apply(prefix: Type, sym: TypeSymbol)(implicit ctx: Context): TypeRef =
12361327
withSymAndName(prefix, sym, sym.name)
1328+
1329+
def withNonMemberSym(prefix: Type, name: TypeName, sym: TypeSymbol)(implicit ctx: Context): TypeRef =
1330+
unique(new NonMemberTypeRef(prefix, name, sym))
1331+
12371332
def withSymAndName(prefix: Type, sym: TypeSymbol, name: TypeName)(implicit ctx: Context): TypeRef =
1238-
if (prefix eq NoPrefix) unique(new NoPrefixTypeRef(name, sym))
1239-
else apply(prefix, name) withSym sym
1333+
if (prefix eq NoPrefix) withNonMemberSym(prefix, name, sym)
1334+
else apply(prefix, name).withSym(sym, Signature.NotAMethod)
1335+
12401336
def apply(prefix: Type, name: TypeName, denot: Denotation)(implicit ctx: Context): TypeRef =
12411337
(if (prefix eq NoPrefix) apply(prefix, denot.symbol.asType) else apply(prefix, name)) withDenot denot
12421338
}

0 commit comments

Comments
 (0)