diff options
author | Martin Odersky <odersky@gmail.com> | 2015-06-05 18:49:36 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-06-06 11:05:27 +0200 |
commit | 080ed2f3d8b5d8fd249691aacc0fe4f9596bb772 (patch) | |
tree | 1fac280aa6832c115037e04178d791cc92f9de25 /src/dotty/tools/dotc/core/Types.scala | |
parent | eaf3095494af2b0ea028452450a6af44e27f5284 (diff) | |
download | dotty-080ed2f3d8b5d8fd249691aacc0fe4f9596bb772.tar.gz dotty-080ed2f3d8b5d8fd249691aacc0fe4f9596bb772.tar.bz2 dotty-080ed2f3d8b5d8fd249691aacc0fe4f9596bb772.zip |
Split RefinedThis and SkolemType
SkolemTypes need to behave differently form RefinedThis types in TypeMap
and TypeAccumulator. For skolem types these should follow through to the
underlying type. For RefinedThis types, these need to do nothing, in order
not to start an infinite recursion.
Diffstat (limited to 'src/dotty/tools/dotc/core/Types.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 6b46e475b..109f39c2f 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -48,6 +48,7 @@ object Types { * | | +--- SuperType * | | +--- ConstantType * | | +--- MethodParam + * | | +----RefinedThis * | | +--- SkolemType * | +- PolyParam * | +- RefinedType @@ -438,7 +439,7 @@ object Types { def goRefined(tp: RefinedType) = { val pdenot = go(tp.parent) val rinfo = - if (tp.refinementRefersToThis) tp.refinedInfo.substSkolem(tp, pre) + if (tp.refinementRefersToThis) tp.refinedInfo.substRefinedThis(tp, pre) else tp.refinedInfo if (name.isTypeName) { // simplified case that runs more efficiently val jointInfo = @@ -583,7 +584,7 @@ object Types { */ final def asSeenFrom(pre: Type, cls: Symbol)(implicit ctx: Context): Type = track("asSeenFrom") { if (!cls.membersNeedAsSeenFrom(pre)) this - else ctx.asSeenFrom(this, pre, cls, null) + else ctx.asSeenFrom(this, pre, cls) } // ----- Subtype-related -------------------------------------------- @@ -822,7 +823,7 @@ object Types { object instantiate extends TypeMap { var isSafe = true def apply(tp: Type): Type = tp match { - case TypeRef(SkolemType(`pre`), name) if name.isLambdaArgName => + case TypeRef(RefinedThis(`pre`), name) if name.isLambdaArgName => val TypeAlias(alias) = member(name).info alias case tp: TypeVar if !tp.inst.exists => @@ -845,13 +846,15 @@ object Types { if (pre.refinedName ne name) loop(pre.parent, pre.refinedName :: resolved) else if (!pre.refinementRefersToThis) alias else alias match { - case TypeRef(SkolemType(`pre`), aliasName) => lookupRefined(aliasName) // (1) + case TypeRef(RefinedThis(`pre`), aliasName) => lookupRefined(aliasName) // (1) case _ => if (name == tpnme.Apply) betaReduce(alias) else NoType // (2) } case _ => loop(pre.parent, resolved) } - case SkolemType(binder) => + case RefinedThis(binder) => binder.lookupRefined(name) + case SkolemType(tp) => + tp.lookupRefined(name) case pre: WildcardType => WildcardType case pre: TypeRef => @@ -1024,8 +1027,8 @@ object Types { if (cls.isStaticOwner) this else ctx.substThis(this, cls, tp, null) /** Substitute all occurrences of `SkolemType(binder)` by `tp` */ - final def substSkolem(binder: Type, tp: Type)(implicit ctx: Context): Type = - ctx.substSkolem(this, binder, tp, null) + final def substRefinedThis(binder: Type, tp: Type)(implicit ctx: Context): Type = + ctx.substRefinedThis(this, binder, tp, null) /** Substitute a bound type by some other type */ final def substParam(from: ParamType, to: Type)(implicit ctx: Context): Type = @@ -1402,7 +1405,7 @@ object Types { * to an (unbounded) wildcard type. * * (2) Reduce a type-ref `T { X = U; ... } # X` to `U` - * provided `U` does not refer with a SkolemType to the + * provided `U` does not refer with a RefinedThis to the * refinement type `T { X = U; ... }` */ def reduceProjection(implicit ctx: Context): Type = { @@ -1816,7 +1819,7 @@ object Types { def refinementRefersToThis(implicit ctx: Context): Boolean = { if (!refinementRefersToThisKnown) { - refinementRefersToThisCache = refinedInfo.containsSkolemType(this) + refinementRefersToThisCache = refinedInfo.containsRefinedThis(this) refinementRefersToThisKnown = true } refinementRefersToThisCache @@ -1852,7 +1855,7 @@ object Types { derivedRefinedType(parent.EtaExpand, refinedName, refinedInfo) else if (false) RefinedType(parent, refinedName, refinedInfo) - else RefinedType(parent, refinedName, rt => refinedInfo.substSkolem(this, SkolemType(rt))) + else RefinedType(parent, refinedName, rt => refinedInfo.substRefinedThis(this, RefinedThis(rt))) } /** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */ @@ -2236,7 +2239,7 @@ object Types { } } - // ----- Bound types: MethodParam, PolyParam, SkolemType -------------------------- + // ----- Bound types: MethodParam, PolyParam, RefinedThis -------------------------- abstract class BoundType extends CachedProxyType with ValueType { type BT <: Type @@ -2309,20 +2312,38 @@ object Types { } } - /** A skolem type reference with underlying type `binder`. */ - case class SkolemType(binder: Type) extends BoundType with SingletonType { - type BT = Type + /** a this-reference to an enclosing refined type `binder`. */ + case class RefinedThis(binder: RefinedType) extends BoundType with SingletonType { + type BT = RefinedType override def underlying(implicit ctx: Context) = binder - def copyBoundType(bt: BT) = SkolemType(bt) + def copyBoundType(bt: BT) = RefinedThis(bt) // need to customize hashCode and equals to prevent infinite recursion for // refinements that refer to the refinement type via this override def computeHash = addDelta(binder.identityHash, 41) override def equals(that: Any) = that match { - case that: SkolemType => this.binder eq that.binder + case that: RefinedThis => this.binder eq that.binder case _ => false } - override def toString = s"SkolemType(${binder.hashCode})" + override def toString = s"RefinedThis(${binder.hashCode})" + } + + // ----- Skolem types ----------------------------------------------- + + /** A skolem type reference with underlying type `binder`. */ + abstract case class SkolemType(info: Type) extends CachedProxyType with ValueType with SingletonType { + override def underlying(implicit ctx: Context) = info + def derivedSkolemType(info: Type)(implicit ctx: Context) = + if (info eq this.info) this else SkolemType(info) + override def computeHash = doHash(info) + override def toString = s"Skolem($info)" + } + + final class CachedSkolemType(info: Type) extends SkolemType(info) + + object SkolemType { + def apply(info: Type)(implicit ctx: Context) = + unique(new CachedSkolemType(info)) } // ------------ Type variables ---------------------------------------- @@ -2883,6 +2904,9 @@ object Types { case tp: AndOrType => tp.derivedAndOrType(this(tp.tp1), this(tp.tp2)) + case tp: SkolemType => + tp.derivedSkolemType(this(tp.info)) + case tp @ AnnotatedType(annot, underlying) => val underlying1 = this(underlying) if (underlying1 eq underlying) tp else tp.derivedAnnotatedType(mapOver(annot), underlying1) @@ -3022,6 +3046,9 @@ object Types { case tp: AndOrType => this(this(x, tp.tp1), tp.tp2) + case tp: SkolemType => + this(x, tp.info) + case AnnotatedType(annot, underlying) => this(applyToAnnot(x, annot), underlying) |