aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Types.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-06-05 18:49:36 +0200
committerMartin Odersky <odersky@gmail.com>2015-06-06 11:05:27 +0200
commit080ed2f3d8b5d8fd249691aacc0fe4f9596bb772 (patch)
tree1fac280aa6832c115037e04178d791cc92f9de25 /src/dotty/tools/dotc/core/Types.scala
parenteaf3095494af2b0ea028452450a6af44e27f5284 (diff)
downloaddotty-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.scala61
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)