aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-08-27 10:48:16 +0200
committerMartin Odersky <odersky@gmail.com>2014-08-27 10:55:47 +0200
commitbfb328ff64dcfa103c91dd0cd55a617e370d6ef3 (patch)
treeb7003776657a486c8fbfac43a7812b10555b0d5a /src/dotty/tools/dotc/core
parent292ce6844a212b47defc671c91396d7cec86833b (diff)
downloaddotty-bfb328ff64dcfa103c91dd0cd55a617e370d6ef3.tar.gz
dotty-bfb328ff64dcfa103c91dd0cd55a617e370d6ef3.tar.bz2
dotty-bfb328ff64dcfa103c91dd0cd55a617e370d6ef3.zip
Make ThisTypes take TypeRefs instead of ClassSymbols
This avoids stale symbol errors and does not need the somewhat unsystematic symbol rebinding of the last commit.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/Substituters.scala4
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala21
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala18
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala6
-rw-r--r--src/dotty/tools/dotc/core/Types.scala39
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala8
6 files changed, 47 insertions, 49 deletions
diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala
index e05f76cd9..fdcc077b3 100644
--- a/src/dotty/tools/dotc/core/Substituters.scala
+++ b/src/dotty/tools/dotc/core/Substituters.scala
@@ -163,8 +163,8 @@ trait Substituters { this: Context =>
final def substThis(tp: Type, from: ClassSymbol, to: Type, theMap: SubstThisMap): Type =
tp match {
- case tp @ ThisType(clazz) =>
- if (clazz eq from) to else tp
+ case tp: ThisType =>
+ if (tp.cls eq from) to else tp
case tp: NamedType =>
if (tp.symbol.isStaticOwner) tp
else tp.derivedSelect(substThis(tp.prefix, from, to, theMap))
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index cb457bd73..660287089 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -471,9 +471,8 @@ object SymDenotations {
* or, if this symbol is protected, a subclass of the owner?
*/
def isCorrectThisType(pre: Type): Boolean = pre match {
- case ThisType(pclazz) =>
- (pclazz eq owner) ||
- (this is Protected) && pclazz.derivesFrom(owner)
+ case pre: ThisType =>
+ (pre.cls eq owner) || (this is Protected) && pre.cls.derivesFrom(owner)
case pre: TermRef =>
pre.symbol.moduleClass == owner
case _ =>
@@ -1000,18 +999,26 @@ object SymDenotations {
private[this] var myThisType: Type = null
+ /** The this-type depends on the kind of class:
+ * - for a package class `p`: ThisType(TypeRef(Noprefix, p))
+ * - for a module class `m`: A term ref to m's source module.
+ * - for all other classes `c` with owner `o`: ThisType(TypeRef(o.thisType, c))
+ */
override def thisType(implicit ctx: Context): Type = {
if (myThisType == null) myThisType = computeThisType
myThisType
}
private def computeThisType(implicit ctx: Context): Type =
- if (this.is(Module, butNot = Package)) {
+ if (this is Package)
+ ThisType.raw(TypeRef(NoPrefix, symbol.asType))
+ else {
val pre = owner.thisType
- if ((pre eq NoPrefix) || ctx.erasedTypes) pre select sourceModule
- else TermRef.withSig(pre, name.sourceModuleName, Signature.NotAMethod)
+ if (this is Module)
+ if (isMissing(pre)) TermRef(pre, sourceModule.asTerm)
+ else TermRef.withSig(pre, name.sourceModuleName, Signature.NotAMethod)
+ else ThisType.raw(TypeRef(pre, symbol.asType))
}
- else ThisType.raw(classSymbol)
private[this] var myTypeRef: TypeRef = null
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 29f6dda69..fda9667e9 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -323,7 +323,7 @@ class TypeComparer(initctx: Context) extends DotClass {
}
tp.prefix match {
case RefinedThis(rt) => rebaseFrom(rt)
- case ThisType(cls) => rebaseFrom(cls.info)
+ case pre: ThisType => rebaseFrom(pre.cls.info)
case _ => tp
}
}
@@ -443,11 +443,11 @@ class TypeComparer(initctx: Context) extends DotClass {
// We treat two prefixes A.this, B.this as equivalent if
// A's selftype derives from B and B's selftype derives from A.
def equivalentThisTypes(tp1: Type, tp2: Type) = tp1 match {
- case ThisType(cls1) =>
+ case tp1: ThisType =>
tp2 match {
- case ThisType(cls2) =>
- cls1.classInfo.selfType.derivesFrom(cls2) &&
- cls2.classInfo.selfType.derivesFrom(cls1)
+ case tp2: ThisType =>
+ tp1.cls.classInfo.selfType.derivesFrom(tp2.cls) &&
+ tp2.cls.classInfo.selfType.derivesFrom(tp1.cls)
case _ => false
}
case _ => false
@@ -483,8 +483,8 @@ class TypeComparer(initctx: Context) extends DotClass {
)
else (tp1.name eq tp2.name) && isSameType(tp1.prefix, tp2.prefix)
) || isHKSubType || secondTryNamed(tp1, tp2)
- case ThisType(cls) if cls eq tp2.symbol.moduleClass =>
- isSubType(cls.owner.thisType, tp2.prefix)
+ case tp1: ThisType if tp1.cls eq tp2.symbol.moduleClass =>
+ isSubType(tp1.cls.owner.thisType, tp2.prefix)
case _ =>
isHKSubType || secondTry(tp1, tp2)
}
@@ -529,8 +529,8 @@ class TypeComparer(initctx: Context) extends DotClass {
def secondTry(tp1: Type, tp2: Type): Boolean = tp1 match {
case tp1: NamedType =>
tp2 match {
- case ThisType(cls) if cls eq tp1.symbol.moduleClass =>
- isSubType(tp1.prefix, cls.owner.thisType)
+ case tp2: ThisType if tp2.cls eq tp1.symbol.moduleClass =>
+ isSubType(tp1.prefix, tp2.cls.owner.thisType)
case _ =>
secondTryNamed(tp1, tp2)
}
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index f9ff42709..efd7fcca3 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -30,8 +30,8 @@ trait TypeOps { this: Context =>
val sym = tp.symbol
if (sym.isStatic) tp
else tp.derivedSelect(asSeenFrom(tp.prefix, pre, cls, theMap))
- case ThisType(thiscls) =>
- toPrefix(pre, cls, thiscls)
+ case tp: ThisType =>
+ toPrefix(pre, cls, tp.cls)
case _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
@@ -224,7 +224,7 @@ trait TypeOps { this: Context =>
*/
def forwardRef(argSym: Symbol, from: Symbol, to: TypeBounds, cls: ClassSymbol, decls: Scope) =
argSym.info match {
- case info @ TypeBounds(lo2 @ TypeRef(ThisType(_), name), hi2) =>
+ case info @ TypeBounds(lo2 @ TypeRef(_: ThisType, name), hi2) =>
if (name == from.name &&
(lo2 eq hi2) &&
info.variance == to.variance &&
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 787c7c4e9..e09d54a23 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1416,7 +1416,7 @@ object Types {
if (ctx.phase.erasedTypes) NoPrefix else prefix
/** Is the prefix seen at current phase the same as NoPrefix? */
- private def isMissing(prefix: Type)(implicit ctx: Context) =
+ def isMissing(prefix: Type)(implicit ctx: Context) =
(prefix eq NoPrefix) || ctx.phase.erasedTypes
/** Assert current phase does not have erasure semantics */
@@ -1534,33 +1534,24 @@ object Types {
// --- Other SingletonTypes: ThisType/SuperType/ConstantType ---------------------------
- /** The type cls.this */
- abstract case class ThisType(private var myCls: ClassSymbol) extends CachedProxyType with SingletonType {
- def cls(implicit ctx: Context): ClassSymbol =
- try myCls.denot.symbol.asClass
- catch {
- case ex: StaleSymbol =>
- def prevDenot(implicit ctx: Context) = myCls.denot
- val prev = prevDenot(ctx.fresh.setPeriod(Period(myCls.defRunId, ctx.phaseId)))
- myCls = prev.owner.info.member(prev.name).symbol.asClass
- cls
- }
- override def underlying(implicit ctx: Context) =
- try cls.classInfo.selfType
- catch {
- case ex: StaleSymbol =>
- println(i"stale symbol when deref ${cls.id}")
- throw ex
- }
- override def computeHash = doHash(myCls)
+ /** The type cls.this
+ * @param tref A type ref which indicates the class `cls`.
+ * Note: we do not pass a class symbol directly, because symbols
+ * do not survive runs whereas typerefs do.
+ */
+ abstract case class ThisType(tref: TypeRef) extends CachedProxyType with SingletonType {
+ def cls(implicit ctx: Context): ClassSymbol = tref.symbol.asClass
+ override def underlying(implicit ctx: Context): Type =
+ if (ctx.erasedTypes) tref else cls.classInfo.selfType
+ override def computeHash = doHash(tref)
}
- final class CachedThisType(cls: ClassSymbol) extends ThisType(cls)
+ final class CachedThisType(tref: TypeRef) extends ThisType(tref)
- // TODO: consider hash before constructing types?
object ThisType {
- def raw(cls: ClassSymbol)(implicit ctx: Context) =
- unique(new CachedThisType(cls))
+ /** Normally one should use ClassSymbol#thisType instead */
+ def raw(tref: TypeRef)(implicit ctx: Context) =
+ unique(new CachedThisType(tref))
}
/** The type of a super reference cls.super where
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index e82002c9f..b80e2322a 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -629,18 +629,18 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
var pre = readTypeRef()
val sym = readSymbolRef()
pre match {
- case ThisType(cls) =>
+ case thispre: ThisType =>
// The problem is that class references super.C get pickled as
// this.C. Dereferencing the member might then get an overriding class
// instance. The problem arises for instance for LinkedHashMap#MapValues
// and also for the inner Transform class in all views. We fix it by
// replacing the this with the appropriate super.
- if (sym.owner != cls) {
- val overriding = cls.decls.lookup(sym.name)
+ if (sym.owner != thispre.cls) {
+ val overriding = thispre.cls.decls.lookup(sym.name)
if (overriding.exists && overriding != sym) {
val base = pre.baseTypeWithArgs(sym.owner)
assert(base.exists)
- pre = SuperType(pre, base)
+ pre = SuperType(thispre, base)
}
}
case _ =>