diff options
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/dotc/core/Skolemization.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Substituters.scala | 18 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeOps.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 61 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TastyFormat.scala | 23 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreePickler.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/PlainPrinter.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/RefinedPrinter.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 2 |
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 |