aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-04-04 10:18:33 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-04-08 17:02:20 +0200
commit09a4bc5d099de71de824a35a67a26e7091e3bb5a (patch)
tree0787d8e5e92507b6ad0f23ad5a8bafe2d03a8930 /src/dotty/tools/dotc/core
parent3486eb0088f78e8ca93c0bc8f883c2af53ee7d3d (diff)
downloaddotty-09a4bc5d099de71de824a35a67a26e7091e3bb5a.tar.gz
dotty-09a4bc5d099de71de824a35a67a26e7091e3bb5a.tar.bz2
dotty-09a4bc5d099de71de824a35a67a26e7091e3bb5a.zip
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.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/Signature.scala6
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala1
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala4
-rw-r--r--src/dotty/tools/dotc/core/Types.scala138
5 files changed, 126 insertions, 25 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 0622829c5..63b94efbd 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -334,7 +334,7 @@ object Denotations {
final def info(implicit ctx: Context) = infoOrCompleter
final def validFor = denot1.validFor & denot2.validFor
final def isType = false
- def signature(implicit ctx: Context) = multiHasNot("signature")
+ final def signature(implicit ctx: Context) = Signature.OverloadedSignature
def atSignature(sig: Signature)(implicit ctx: Context): SingleDenotation =
denot1.atSignature(sig) orElse denot2.atSignature(sig)
def current(implicit ctx: Context): Denotation =
diff --git a/src/dotty/tools/dotc/core/Signature.scala b/src/dotty/tools/dotc/core/Signature.scala
index 02b91b18e..eb85fbb99 100644
--- a/src/dotty/tools/dotc/core/Signature.scala
+++ b/src/dotty/tools/dotc/core/Signature.scala
@@ -1,7 +1,7 @@
package dotty.tools.dotc
package core
-import Names._, Types._, Contexts._
+import Names._, Types._, Contexts._, StdNames._
import transform.Erasure.sigName
/** The signature of a denotation.
@@ -49,6 +49,10 @@ object Signature {
* a type different from PolyType, MethodType, or ExprType.
*/
val NotAMethod = Signature(List(), EmptyTypeName)
+
+ /** The signature of an overloaded denotation.
+ */
+ val OverloadedSignature = Signature(List(tpnme.OVERLOADED), EmptyTypeName)
/** The signature of a method with no parameters and result type `resultType`. */
def apply(resultType: Type, isJava: Boolean)(implicit ctx: Context): Signature =
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 3982c51f0..d01971982 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -109,6 +109,7 @@ object StdNames {
val MODULE_VAR_SUFFIX: N = "$module"
val NAME_JOIN: N = NameTransformer.NAME_JOIN_STRING
val USCORE_PARAM_PREFIX: N = "_$"
+ val OVERLOADED: N = "<overloaded>"
val PACKAGE: N = "package"
val PACKAGE_CLS: N = "package$"
val PROTECTED_PREFIX: N = "protected$"
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index b4db26ae6..8f66830e8 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -245,7 +245,7 @@ trait Symbols { this: Context =>
for (name <- names) {
val tparam = newNakedSymbol[TypeName](NoCoord)
tparamBuf += tparam
- trefBuf += TypeRef(owner.thisType, name) withSym tparam
+ trefBuf += TypeRef(owner.thisType, name).withSym(tparam, Signature.NotAMethod)
}
val tparams = tparamBuf.toList
val bounds = boundsFn(trefBuf.toList)
@@ -319,7 +319,7 @@ object Symbols {
type ThisName <: Name
private[this] var _id: Int = nextId
- //assert(_id != 5859)
+ //assert(_id != 12325)
/** The unique id of this symbol */
def id = _id
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 8799f9fd0..7561abb10 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -656,6 +656,15 @@ object Types {
if (res.exists) res else TypeRef(this, name, denot)
}
+ /** The type <this . name> , reduced if possible, with given denotation if unreduced */
+ def selectNonMember(name: Name, denot: Denotation)(implicit ctx: Context): Type = name match {
+ case name: TermName =>
+ TermRef(this, name, denot)
+ case name: TypeName =>
+ val res = lookupRefined(name)
+ if (res.exists) res else TypeRef(this, name, denot)
+ }
+
/** The type <this . name> with given symbol, reduced if possible */
def select(sym: Symbol)(implicit ctx: Context): Type =
if (sym.isTerm) TermRef(this, sym.asTerm)
@@ -991,6 +1000,8 @@ object Types {
val prefix: Type
val name: Name
+ type ThisType >: this.type <: NamedType
+
assert(prefix.isValueType || (prefix eq NoPrefix), s"invalid prefix $prefix")
private[this] var lastDenotation: Denotation = _
@@ -1049,19 +1060,48 @@ object Types {
if (owner.isTerm) d else d.asSeenFrom(prefix)
}
- private[dotc] final def withDenot(denot: Denotation): this.type = {
+ private def checkSymAssign(sym: Symbol) =
+ assert(
+ (lastSymbol eq sym) ||
+ (lastSymbol eq null) ||
+ (lastSymbol.defRunId != sym.defRunId) ||
+ (lastSymbol.defRunId == NoRunId),
+ s"data race? overwriting symbol of $this / ${this.getClass} / ${lastSymbol.id} / ${sym.id}")
+
+ protected def sig: Signature = Signature.NotAMethod
+
+ private[dotc] def withDenot(denot: Denotation)(implicit ctx: Context): ThisType =
+ if (sig != denot.signature)
+ withSig(denot.signature).withDenot(denot).asInstanceOf[ThisType]
+ else {
+ setDenot(denot)
+ this
+ }
+
+ private[dotc] final def setDenot(denot: Denotation): Unit = {
+ if (Config.checkTermRefs) checkSymAssign(denot.symbol)
lastDenotation = denot
lastSymbol = denot.symbol
- this
}
- private[dotc] final def withSym(sym: Symbol): this.type = {
+ private[dotc] def withSym(sym: Symbol, signature: Signature)(implicit ctx: Context): ThisType =
+ if (sig != signature)
+ withSig(signature).withSym(sym, signature).asInstanceOf[ThisType]
+ else {
+ setSym(sym)
+ this
+ }
+
+ private[dotc] final def setSym(sym: Symbol): Unit = {
+ if (Config.checkTermRefs) checkSymAssign(sym)
lastDenotation = null
lastSymbol = sym
checkedPeriod = Nowhere
- this
}
+ private def withSig(sig: Signature)(implicit ctx: Context): NamedType =
+ TermRef.withSig(prefix, name.asTermName, sig)
+
protected def loadDenot(implicit ctx: Context) = {
val d = prefix.member(name)
if (d.exists || ctx.phaseId == FirstPhaseId)
@@ -1136,6 +1176,9 @@ object Types {
abstract case class TermRef(override val prefix: Type, name: TermName) extends NamedType with SingletonType {
+ type ThisType = TermRef
+
+ //assert(name.toString != "<local Coder>")
override def underlying(implicit ctx: Context): Type = {
val d = denot
if (d.isOverloaded) NoType else d.info
@@ -1156,16 +1199,31 @@ object Types {
}
abstract case class TypeRef(override val prefix: Type, name: TypeName) extends NamedType {
+
+ type ThisType = TypeRef
+
override def underlying(implicit ctx: Context): Type = info
}
- final class TermRefWithSignature(prefix: Type, name: TermName, val sig: Signature) extends TermRef(prefix, name) {
+ final class TermRefWithSignature(prefix: Type, name: TermName, override val sig: Signature) extends TermRef(prefix, name) {
assert(prefix ne NoPrefix)
override def signature(implicit ctx: Context) = sig
- override def loadDenot(implicit ctx: Context): Denotation =
- super.loadDenot.atSignature(sig)
- override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRef =
- TermRef.withSig(prefix, name, sig)
+ override def loadDenot(implicit ctx: Context): Denotation = {
+ val d = super.loadDenot
+ if (sig eq Signature.OverloadedSignature) d
+ else d.atSignature(sig)
+ }
+
+ override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRef = {
+ if (sig != Signature.NotAMethod &&
+ sig != Signature.OverloadedSignature &&
+ symbol.exists) {
+ val ownSym = symbol
+ TermRef(prefix, name).withDenot(prefix.member(name).disambiguate(_ eq ownSym))
+ }
+ else TermRef.withSig(prefix, name, sig)
+ }
+
override def equals(that: Any) = that match {
case that: TermRefWithSignature =>
this.prefix == that.prefix &&
@@ -1177,15 +1235,25 @@ object Types {
override def computeHash = doHash((name, sig), prefix)
}
- trait WithNoPrefix extends NamedType {
+ trait WithNonMemberSym extends NamedType {
def fixedSym: Symbol
assert(fixedSym ne NoSymbol)
- withSym(fixedSym)
+ setSym(fixedSym)
+
+ override def withDenot(denot: Denotation)(implicit ctx: Context): ThisType = {
+ assert(denot.symbol eq fixedSym)
+ setDenot(denot)
+ this
+ }
+
+ override def withSym(sym: Symbol, signature: Signature)(implicit ctx: Context): ThisType =
+ unsupported("withSym")
+
override def equals(that: Any) = that match {
- case that: WithNoPrefix => this.fixedSym eq that.fixedSym
+ case that: WithNonMemberSym => this.prefix == that.prefix && (this.fixedSym eq that.fixedSym)
case _ => false
}
- override def computeHash = doHash(fixedSym)
+ override def computeHash = doHash(fixedSym, prefix)
}
final class CachedTermRef(prefix: Type, name: TermName, hc: Int) extends TermRef(prefix, name) {
@@ -1200,8 +1268,8 @@ object Types {
override def computeHash = unsupported("computeHash")
}
- final class NoPrefixTermRef(name: TermName, val fixedSym: TermSymbol) extends TermRef(NoPrefix, name) with WithNoPrefix
- final class NoPrefixTypeRef(name: TypeName, val fixedSym: TypeSymbol) extends TypeRef(NoPrefix, name) with WithNoPrefix
+ 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
object NamedType {
def apply(prefix: Type, name: Name)(implicit ctx: Context) =
@@ -1210,20 +1278,42 @@ 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)
}
object TermRef {
def apply(prefix: Type, name: TermName)(implicit ctx: Context): TermRef =
ctx.uniqueNamedTypes.enterIfNew(prefix, name).asInstanceOf[TermRef]
+
def apply(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
withSymAndName(prefix, sym, sym.name)
+
+ def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef = {
+ if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm)
+ else denot match {
+ case denot: SymDenotation if denot.isCompleted => withSig(prefix, name, denot.signature)
+ case _ => apply(prefix, name)
+ }
+ } withDenot denot
+
+ def withNonMemberSym(prefix: Type, name: TermName, sym: TermSymbol)(implicit ctx: Context): TermRef =
+ unique(new NonMemberTermRef(prefix, name, sym))
+
def withSymAndName(prefix: Type, sym: TermSymbol, name: TermName)(implicit ctx: Context): TermRef =
- if (prefix eq NoPrefix) unique(new NoPrefixTermRef(name, sym))
- else apply(prefix, name) withSym sym
- def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef =
- (if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm) else apply(prefix, name)) withDenot denot
+ if (prefix eq NoPrefix) withNonMemberSym(prefix, name, sym)
+ else {
+ if (sym.defRunId != NoRunId && sym.isCompleted) withSig(prefix, name, sym.signature)
+ else apply(prefix, name)
+ } withSym (sym, Signature.NotAMethod)
+
+ def withSig(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
+ unique(withSig(prefix, sym.name, sym.signature).withSym(sym, sym.signature))
+
def withSig(prefix: Type, name: TermName, sig: Signature)(implicit ctx: Context): TermRef =
unique(new TermRefWithSignature(prefix, name, sig))
+
def withSig(prefix: Type, name: TermName, sig: Signature, denot: Denotation)(implicit ctx: Context): TermRef =
(if (prefix eq NoPrefix) apply(prefix, denot.symbol.asTerm)
else withSig(prefix, name, sig)) withDenot denot
@@ -1232,11 +1322,17 @@ object Types {
object TypeRef {
def apply(prefix: Type, name: TypeName)(implicit ctx: Context): TypeRef =
ctx.uniqueNamedTypes.enterIfNew(prefix, name).asInstanceOf[TypeRef]
+
def apply(prefix: Type, sym: TypeSymbol)(implicit ctx: Context): TypeRef =
withSymAndName(prefix, sym, sym.name)
+
+ def withNonMemberSym(prefix: Type, name: TypeName, sym: TypeSymbol)(implicit ctx: Context): TypeRef =
+ unique(new NonMemberTypeRef(prefix, name, sym))
+
def withSymAndName(prefix: Type, sym: TypeSymbol, name: TypeName)(implicit ctx: Context): TypeRef =
- if (prefix eq NoPrefix) unique(new NoPrefixTypeRef(name, sym))
- else apply(prefix, name) withSym sym
+ if (prefix eq NoPrefix) withNonMemberSym(prefix, name, sym)
+ else apply(prefix, name).withSym(sym, Signature.NotAMethod)
+
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
}