aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
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
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')
-rw-r--r--src/dotty/tools/dotc/core/Skolemization.scala4
-rw-r--r--src/dotty/tools/dotc/core/Substituters.scala18
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala8
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala3
-rw-r--r--src/dotty/tools/dotc/core/Types.scala61
-rw-r--r--src/dotty/tools/dotc/core/tasty/TastyFormat.scala23
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreePickler.scala5
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala2
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala2
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala9
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala2
13 files changed, 88 insertions, 53 deletions
diff --git a/src/dotty/tools/dotc/core/Skolemization.scala b/src/dotty/tools/dotc/core/Skolemization.scala
index eef5f0e5d..8baf612ba 100644
--- a/src/dotty/tools/dotc/core/Skolemization.scala
+++ b/src/dotty/tools/dotc/core/Skolemization.scala
@@ -30,7 +30,7 @@ trait Skolemization {
case tp: TypeProxy =>
ensureStableSingleton(tp.underlying)
}
-
+/*@@@
/** If skolems were encountered, approximate a type `tp` with a type that
* does not contain skolem types.
* @param toSuper if true, return the smallest supertype of `tp` with this property
@@ -137,7 +137,7 @@ trait Skolemization {
this.seen = savedSeen
}
}
- }
+ }*/
}
object Skolemization extends Enumeration {
diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala
index 77ecf7fba..e4bbf2305 100644
--- a/src/dotty/tools/dotc/core/Substituters.scala
+++ b/src/dotty/tools/dotc/core/Substituters.scala
@@ -179,21 +179,21 @@ trait Substituters { this: Context =>
.mapOver(tp)
}
- final def substSkolem(tp: Type, from: Type, to: Type, theMap: SubstSkolemMap): Type =
+ final def substRefinedThis(tp: Type, from: Type, to: Type, theMap: SubstRefinedThisMap): Type =
tp match {
- case tp @ SkolemType(binder) =>
+ case tp @ RefinedThis(binder) =>
if (binder eq from) to else tp
case tp: NamedType =>
if (tp.currentSymbol.isStatic) tp
- else tp.derivedSelect(substSkolem(tp.prefix, from, to, theMap))
+ else tp.derivedSelect(substRefinedThis(tp.prefix, from, to, theMap))
case _: ThisType | _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
- tp.derivedRefinedType(substSkolem(tp.parent, from, to, theMap), tp.refinedName, substSkolem(tp.refinedInfo, from, to, theMap))
+ tp.derivedRefinedType(substRefinedThis(tp.parent, from, to, theMap), tp.refinedName, substRefinedThis(tp.refinedInfo, from, to, theMap))
case tp: TypeAlias =>
- tp.derivedTypeAlias(substSkolem(tp.alias, from, to, theMap))
+ tp.derivedTypeAlias(substRefinedThis(tp.alias, from, to, theMap))
case _ =>
- (if (theMap != null) theMap else new SubstSkolemMap(from, to))
+ (if (theMap != null) theMap else new SubstRefinedThisMap(from, to))
.mapOver(tp)
}
@@ -222,7 +222,7 @@ trait Substituters { this: Context =>
case tp: NamedType =>
if (tp.currentSymbol.isStatic) tp
else tp.derivedSelect(substParams(tp.prefix, from, to, theMap))
- case _: ThisType | NoPrefix | _: SkolemType =>
+ case _: ThisType | NoPrefix =>
tp
case tp: RefinedType =>
tp.derivedRefinedType(substParams(tp.parent, from, to, theMap), tp.refinedName, substParams(tp.refinedInfo, from, to, theMap))
@@ -266,8 +266,8 @@ trait Substituters { this: Context =>
def apply(tp: Type): Type = substThis(tp, from, to, this)
}
- final class SubstSkolemMap(from: Type, to: Type) extends DeepTypeMap {
- def apply(tp: Type): Type = substSkolem(tp, from, to, this)
+ final class SubstRefinedThisMap(from: Type, to: Type) extends DeepTypeMap {
+ def apply(tp: Type): Type = substRefinedThis(tp, from, to, this)
}
final class SubstParamMap(from: ParamType, to: Type) extends DeepTypeMap {
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 7f3f8a446..f466cee77 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -387,9 +387,9 @@ class TypeApplications(val self: Type) extends AnyVal {
case _ => firstBaseArgInfo(defn.SeqClass)
}
- def containsSkolemType(target: Type)(implicit ctx: Context): Boolean = {
+ def containsRefinedThis(target: Type)(implicit ctx: Context): Boolean = {
def recur(tp: Type): Boolean = tp.stripTypeVar match {
- case SkolemType(tp) =>
+ case RefinedThis(tp) =>
tp eq target
case tp: NamedType =>
tp.info match {
@@ -446,7 +446,7 @@ class TypeApplications(val self: Type) extends AnyVal {
def replacements(rt: RefinedType): List[Type] =
for (sym <- boundSyms)
- yield TypeRef(SkolemType(rt), correspondingParamName(sym))
+ yield TypeRef(RefinedThis(rt), correspondingParamName(sym))
def rewrite(tp: Type): Type = tp match {
case tp @ RefinedType(parent, name: TypeName) =>
@@ -489,7 +489,7 @@ class TypeApplications(val self: Type) extends AnyVal {
val lambda = defn.lambdaTrait(boundSyms.map(_.variance))
val substitutedRHS = (rt: RefinedType) => {
val argRefs = boundSyms.indices.toList.map(i =>
- SkolemType(rt).select(tpnme.lambdaArgName(i)))
+ RefinedThis(rt).select(tpnme.lambdaArgName(i)))
tp.subst(boundSyms, argRefs).bounds.withVariance(1)
}
val res = RefinedType(lambda.typeRef, tpnme.Apply, substitutedRHS)
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index e90c30025..64faa6d93 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -536,7 +536,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
try {
val rebindNeeded = tp2.refinementRefersToThis
val base = if (rebindNeeded) ensureStableSingleton(tp1) else tp1
- val rinfo2 = if (rebindNeeded) tp2.refinedInfo.substSkolem(tp2, base) else tp2.refinedInfo
+ val rinfo2 = if (rebindNeeded) tp2.refinedInfo.substRefinedThis(tp2, base) else tp2.refinedInfo
def qualifies(m: SingleDenotation) = isSubType(m.info, rinfo2)
def memberMatches(mbr: Denotation): Boolean = mbr match { // inlined hasAltWith for performance
case mbr: SingleDenotation => qualifies(mbr)
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index acbd5b6f0..a01f8af9f 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -12,6 +12,9 @@ import ast.tpd._
trait TypeOps { this: Context => // TODO: Make standalone object.
+ final def asSeenFrom(tp: Type, pre: Type, cls: Symbol): Type =
+ asSeenFrom(tp, pre, cls, null)
+
final def asSeenFrom(tp: Type, pre: Type, cls: Symbol, theMap: AsSeenFromMap): Type = {
def toPrefix(pre: Type, cls: Symbol, thiscls: ClassSymbol): Type = /*>|>*/ ctx.conditionalTraceIndented(TypeOps.track, s"toPrefix($pre, $cls, $thiscls)") /*<|<*/ {
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)
diff --git a/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
index 106a6510d..1022fc4da 100644
--- a/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
+++ b/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
@@ -103,10 +103,10 @@ Standard-Section: "ASTs" TopLevelStat*
TERMREFpkg fullyQualified_NameRef
TERMREF possiblySigned_NameRef qual_Type
THIS clsRef_Type
- SKOLEMtype refinedType_ASTRef
+ REFINEDthis refinedType_ASTRef
+ SKOLEMtype Type_ASTRef
SHARED path_ASTRef
-
Constant = UNITconst
FALSEconst
TRUEconst
@@ -262,15 +262,16 @@ object TastyFormat {
final val TERMREFpkg = 67
final val TYPEREFpkg = 68
final val SKOLEMtype = 69
- final val BYTEconst = 70
- final val SHORTconst = 71
- final val CHARconst = 72
- final val INTconst = 73
- final val LONGconst = 74
- final val FLOATconst = 75
- final val DOUBLEconst = 76
- final val STRINGconst = 77
- final val IMPORTED = 78
+ final val REFINEDthis = 70
+ final val BYTEconst = 71
+ final val SHORTconst = 72
+ final val CHARconst = 73
+ final val INTconst = 74
+ final val LONGconst = 75
+ final val FLOATconst = 76
+ final val DOUBLEconst = 77
+ final val STRINGconst = 78
+ final val IMPORTED = 79
final val THIS = 96
final val CLASSconst = 97
diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
index 365b5d268..cd49f7c5a 100644
--- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
@@ -198,9 +198,12 @@ class TreePickler(pickler: TastyPickler) {
case tpe: SuperType =>
writeByte(SUPERtype)
withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe)}
+ case tpe: RefinedThis =>
+ writeByte(REFINEDthis)
+ writeRef(pickledTypes.get(tpe.binder).asInstanceOf[Addr])
case tpe: SkolemType =>
writeByte(SKOLEMtype)
- writeRef(pickledTypes.get(tpe.binder).asInstanceOf[Addr])
+ pickleType(tpe.info)
case tpe: RefinedType =>
val args = tpe.argInfos(interpolate = false)
if (args.isEmpty) {
diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index e753bdcab..d4260e679 100644
--- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -254,6 +254,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
}
case THIS =>
ThisType.raw(readType().asInstanceOf[TypeRef])
+ case REFINEDthis =>
+ RefinedThis(readTypeRef().asInstanceOf[RefinedType])
case SKOLEMtype =>
SkolemType(readTypeRef())
case SHARED =>
diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index b4549a8d8..9498cf43c 100644
--- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -689,7 +689,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
else {
def addRefinement(tp: Type, sym: Symbol) = {
def subst(info: Type, rt: RefinedType) =
- if (clazz.isClass) info.substThis(clazz.asClass, SkolemType(rt))
+ if (clazz.isClass) info.substThis(clazz.asClass, RefinedThis(rt))
else info // turns out some symbols read into `clazz` are not classes, not sure why this is the case.
RefinedType(tp, sym.name, subst(sym.info, _))
}
diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala
index 12c94677f..de1a439cf 100644
--- a/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -228,11 +228,10 @@ class PlainPrinter(_ctx: Context) extends Printer {
toText(value)
case MethodParam(mt, idx) =>
nameString(mt.paramNames(idx))
- case sk: SkolemType =>
- sk.binder match {
- case rt: RefinedType => s"${nameString(rt.typeSymbol)}{...}.this"
- case _ => "<skolem>"
- }
+ case tp: RefinedThis =>
+ s"${nameString(tp.binder.typeSymbol)}{...}.this"
+ case tp: SkolemType =>
+ "<skolem>" // !!! todo refine with unique identifier.
}
}
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index fa238f32c..cf80969bf 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -190,7 +190,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
// LambdaI{...}.HK$i
val simplifyArgs = new TypeMap {
override def apply(tp: Type) = tp match {
- case tp @ TypeRef(SkolemType(_), name) if name.isLambdaArgName =>
+ case tp @ TypeRef(RefinedThis(_), name) if name.isLambdaArgName =>
TypeRef(NoPrefix, tp.symbol.asType)
case _ =>
mapOver(tp)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index fd1d034fd..5f03d19e7 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -812,7 +812,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if ((rsym.is(Method) || rsym.isType) && rsym.allOverriddenSymbols.isEmpty)
ctx.error(i"refinement $rsym without matching type in parent $parent", refinement.pos)
val rinfo = if (rsym is Accessor) rsym.info.resultType else rsym.info
- RefinedType(parent, rsym.name, rt => rinfo.substThis(refineCls, SkolemType(rt)))
+ RefinedType(parent, rsym.name, rt => rinfo.substThis(refineCls, RefinedThis(rt)))
// todo later: check that refinement is within bounds
}
val res = cpy.RefinedTypeTree(tree)(tpt1, refinements1) withType