Skip to content

Commit 6645d88

Browse files
committed
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.
1 parent 87d78dc commit 6645d88

13 files changed

+89
-54
lines changed

src/dotty/tools/dotc/core/Skolemization.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ trait Skolemization {
3030
case tp: TypeProxy =>
3131
ensureStableSingleton(tp.underlying)
3232
}
33-
33+
/*@@@
3434
/** If skolems were encountered, approximate a type `tp` with a type that
3535
* does not contain skolem types.
3636
* @param toSuper if true, return the smallest supertype of `tp` with this property
@@ -137,7 +137,7 @@ trait Skolemization {
137137
this.seen = savedSeen
138138
}
139139
}
140-
}
140+
}*/
141141
}
142142

143143
object Skolemization extends Enumeration {

src/dotty/tools/dotc/core/Substituters.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,21 +179,21 @@ trait Substituters { this: Context =>
179179
.mapOver(tp)
180180
}
181181

182-
final def substSkolem(tp: Type, from: Type, to: Type, theMap: SubstSkolemMap): Type =
182+
final def substRefinedThis(tp: Type, from: Type, to: Type, theMap: SubstRefinedThisMap): Type =
183183
tp match {
184-
case tp @ SkolemType(binder) =>
184+
case tp @ RefinedThis(binder) =>
185185
if (binder eq from) to else tp
186186
case tp: NamedType =>
187187
if (tp.currentSymbol.isStatic) tp
188-
else tp.derivedSelect(substSkolem(tp.prefix, from, to, theMap))
188+
else tp.derivedSelect(substRefinedThis(tp.prefix, from, to, theMap))
189189
case _: ThisType | _: BoundType | NoPrefix =>
190190
tp
191191
case tp: RefinedType =>
192-
tp.derivedRefinedType(substSkolem(tp.parent, from, to, theMap), tp.refinedName, substSkolem(tp.refinedInfo, from, to, theMap))
192+
tp.derivedRefinedType(substRefinedThis(tp.parent, from, to, theMap), tp.refinedName, substRefinedThis(tp.refinedInfo, from, to, theMap))
193193
case tp: TypeAlias =>
194-
tp.derivedTypeAlias(substSkolem(tp.alias, from, to, theMap))
194+
tp.derivedTypeAlias(substRefinedThis(tp.alias, from, to, theMap))
195195
case _ =>
196-
(if (theMap != null) theMap else new SubstSkolemMap(from, to))
196+
(if (theMap != null) theMap else new SubstRefinedThisMap(from, to))
197197
.mapOver(tp)
198198
}
199199

@@ -222,7 +222,7 @@ trait Substituters { this: Context =>
222222
case tp: NamedType =>
223223
if (tp.currentSymbol.isStatic) tp
224224
else tp.derivedSelect(substParams(tp.prefix, from, to, theMap))
225-
case _: ThisType | NoPrefix | _: SkolemType =>
225+
case _: ThisType | NoPrefix =>
226226
tp
227227
case tp: RefinedType =>
228228
tp.derivedRefinedType(substParams(tp.parent, from, to, theMap), tp.refinedName, substParams(tp.refinedInfo, from, to, theMap))
@@ -266,8 +266,8 @@ trait Substituters { this: Context =>
266266
def apply(tp: Type): Type = substThis(tp, from, to, this)
267267
}
268268

269-
final class SubstSkolemMap(from: Type, to: Type) extends DeepTypeMap {
270-
def apply(tp: Type): Type = substSkolem(tp, from, to, this)
269+
final class SubstRefinedThisMap(from: Type, to: Type) extends DeepTypeMap {
270+
def apply(tp: Type): Type = substRefinedThis(tp, from, to, this)
271271
}
272272

273273
final class SubstParamMap(from: ParamType, to: Type) extends DeepTypeMap {

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,9 @@ class TypeApplications(val self: Type) extends AnyVal {
387387
case _ => firstBaseArgInfo(defn.SeqClass)
388388
}
389389

390-
def containsSkolemType(target: Type)(implicit ctx: Context): Boolean = {
390+
def containsRefinedThis(target: Type)(implicit ctx: Context): Boolean = {
391391
def recur(tp: Type): Boolean = tp.stripTypeVar match {
392-
case SkolemType(tp) =>
392+
case RefinedThis(tp) =>
393393
tp eq target
394394
case tp: NamedType =>
395395
tp.info match {
@@ -446,7 +446,7 @@ class TypeApplications(val self: Type) extends AnyVal {
446446

447447
def replacements(rt: RefinedType): List[Type] =
448448
for (sym <- boundSyms)
449-
yield TypeRef(SkolemType(rt), correspondingParamName(sym))
449+
yield TypeRef(RefinedThis(rt), correspondingParamName(sym))
450450

451451
def rewrite(tp: Type): Type = tp match {
452452
case tp @ RefinedType(parent, name: TypeName) =>
@@ -489,7 +489,7 @@ class TypeApplications(val self: Type) extends AnyVal {
489489
val lambda = defn.lambdaTrait(boundSyms.map(_.variance))
490490
val substitutedRHS = (rt: RefinedType) => {
491491
val argRefs = boundSyms.indices.toList.map(i =>
492-
SkolemType(rt).select(tpnme.lambdaArgName(i)))
492+
RefinedThis(rt).select(tpnme.lambdaArgName(i)))
493493
tp.subst(boundSyms, argRefs).bounds.withVariance(1)
494494
}
495495
val res = RefinedType(lambda.typeRef, tpnme.Apply, substitutedRHS)

src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
536536
try {
537537
val rebindNeeded = tp2.refinementRefersToThis
538538
val base = if (rebindNeeded) ensureStableSingleton(tp1) else tp1
539-
val rinfo2 = if (rebindNeeded) tp2.refinedInfo.substSkolem(tp2, base) else tp2.refinedInfo
539+
val rinfo2 = if (rebindNeeded) tp2.refinedInfo.substRefinedThis(tp2, base) else tp2.refinedInfo
540540
def qualifies(m: SingleDenotation) = isSubType(m.info, rinfo2)
541541
def memberMatches(mbr: Denotation): Boolean = mbr match { // inlined hasAltWith for performance
542542
case mbr: SingleDenotation => qualifies(mbr)

src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import ast.tpd._
1212

1313
trait TypeOps { this: Context => // TODO: Make standalone object.
1414

15+
final def asSeenFrom(tp: Type, pre: Type, cls: Symbol): Type =
16+
asSeenFrom(tp, pre, cls, null)
17+
1518
final def asSeenFrom(tp: Type, pre: Type, cls: Symbol, theMap: AsSeenFromMap): Type = {
1619

1720
def toPrefix(pre: Type, cls: Symbol, thiscls: ClassSymbol): Type = /*>|>*/ ctx.conditionalTraceIndented(TypeOps.track, s"toPrefix($pre, $cls, $thiscls)") /*<|<*/ {

src/dotty/tools/dotc/core/Types.scala

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ object Types {
4848
* | | +--- SuperType
4949
* | | +--- ConstantType
5050
* | | +--- MethodParam
51+
* | | +----RefinedThis
5152
* | | +--- SkolemType
5253
* | +- PolyParam
5354
* | +- RefinedType
@@ -438,7 +439,7 @@ object Types {
438439
def goRefined(tp: RefinedType) = {
439440
val pdenot = go(tp.parent)
440441
val rinfo =
441-
if (tp.refinementRefersToThis) tp.refinedInfo.substSkolem(tp, pre)
442+
if (tp.refinementRefersToThis) tp.refinedInfo.substRefinedThis(tp, pre)
442443
else tp.refinedInfo
443444
if (name.isTypeName) { // simplified case that runs more efficiently
444445
val jointInfo =
@@ -583,7 +584,7 @@ object Types {
583584
*/
584585
final def asSeenFrom(pre: Type, cls: Symbol)(implicit ctx: Context): Type = track("asSeenFrom") {
585586
if (!cls.membersNeedAsSeenFrom(pre)) this
586-
else ctx.asSeenFrom(this, pre, cls, null)
587+
else ctx.asSeenFrom(this, pre, cls)
587588
}
588589

589590
// ----- Subtype-related --------------------------------------------
@@ -822,7 +823,7 @@ object Types {
822823
object instantiate extends TypeMap {
823824
var isSafe = true
824825
def apply(tp: Type): Type = tp match {
825-
case TypeRef(SkolemType(`pre`), name) if name.isLambdaArgName =>
826+
case TypeRef(RefinedThis(`pre`), name) if name.isLambdaArgName =>
826827
val TypeAlias(alias) = member(name).info
827828
alias
828829
case tp: TypeVar if !tp.inst.exists =>
@@ -845,13 +846,15 @@ object Types {
845846
if (pre.refinedName ne name) loop(pre.parent, pre.refinedName :: resolved)
846847
else if (!pre.refinementRefersToThis) alias
847848
else alias match {
848-
case TypeRef(SkolemType(`pre`), aliasName) => lookupRefined(aliasName) // (1)
849+
case TypeRef(RefinedThis(`pre`), aliasName) => lookupRefined(aliasName) // (1)
849850
case _ => if (name == tpnme.Apply) betaReduce(alias) else NoType // (2)
850851
}
851852
case _ => loop(pre.parent, resolved)
852853
}
853-
case SkolemType(binder) =>
854+
case RefinedThis(binder) =>
854855
binder.lookupRefined(name)
856+
case SkolemType(tp) =>
857+
tp.lookupRefined(name)
855858
case pre: WildcardType =>
856859
WildcardType
857860
case pre: TypeRef =>
@@ -1024,8 +1027,8 @@ object Types {
10241027
if (cls.isStaticOwner) this else ctx.substThis(this, cls, tp, null)
10251028

10261029
/** Substitute all occurrences of `SkolemType(binder)` by `tp` */
1027-
final def substSkolem(binder: Type, tp: Type)(implicit ctx: Context): Type =
1028-
ctx.substSkolem(this, binder, tp, null)
1030+
final def substRefinedThis(binder: Type, tp: Type)(implicit ctx: Context): Type =
1031+
ctx.substRefinedThis(this, binder, tp, null)
10291032

10301033
/** Substitute a bound type by some other type */
10311034
final def substParam(from: ParamType, to: Type)(implicit ctx: Context): Type =
@@ -1402,7 +1405,7 @@ object Types {
14021405
* to an (unbounded) wildcard type.
14031406
*
14041407
* (2) Reduce a type-ref `T { X = U; ... } # X` to `U`
1405-
* provided `U` does not refer with a SkolemType to the
1408+
* provided `U` does not refer with a RefinedThis to the
14061409
* refinement type `T { X = U; ... }`
14071410
*/
14081411
def reduceProjection(implicit ctx: Context): Type = {
@@ -1816,7 +1819,7 @@ object Types {
18161819

18171820
def refinementRefersToThis(implicit ctx: Context): Boolean = {
18181821
if (!refinementRefersToThisKnown) {
1819-
refinementRefersToThisCache = refinedInfo.containsSkolemType(this)
1822+
refinementRefersToThisCache = refinedInfo.containsRefinedThis(this)
18201823
refinementRefersToThisKnown = true
18211824
}
18221825
refinementRefersToThisCache
@@ -1852,7 +1855,7 @@ object Types {
18521855
derivedRefinedType(parent.EtaExpand, refinedName, refinedInfo)
18531856
else
18541857
if (false) RefinedType(parent, refinedName, refinedInfo)
1855-
else RefinedType(parent, refinedName, rt => refinedInfo.substSkolem(this, SkolemType(rt)))
1858+
else RefinedType(parent, refinedName, rt => refinedInfo.substRefinedThis(this, RefinedThis(rt)))
18561859
}
18571860

18581861
/** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */
@@ -2236,7 +2239,7 @@ object Types {
22362239
}
22372240
}
22382241

2239-
// ----- Bound types: MethodParam, PolyParam, SkolemType --------------------------
2242+
// ----- Bound types: MethodParam, PolyParam, RefinedThis --------------------------
22402243

22412244
abstract class BoundType extends CachedProxyType with ValueType {
22422245
type BT <: Type
@@ -2309,20 +2312,38 @@ object Types {
23092312
}
23102313
}
23112314

2312-
/** A skolem type reference with underlying type `binder`. */
2313-
case class SkolemType(binder: Type) extends BoundType with SingletonType {
2314-
type BT = Type
2315+
/** a this-reference to an enclosing refined type `binder`. */
2316+
case class RefinedThis(binder: RefinedType) extends BoundType with SingletonType {
2317+
type BT = RefinedType
23152318
override def underlying(implicit ctx: Context) = binder
2316-
def copyBoundType(bt: BT) = SkolemType(bt)
2319+
def copyBoundType(bt: BT) = RefinedThis(bt)
23172320

23182321
// need to customize hashCode and equals to prevent infinite recursion for
23192322
// refinements that refer to the refinement type via this
23202323
override def computeHash = addDelta(binder.identityHash, 41)
23212324
override def equals(that: Any) = that match {
2322-
case that: SkolemType => this.binder eq that.binder
2325+
case that: RefinedThis => this.binder eq that.binder
23232326
case _ => false
23242327
}
2325-
override def toString = s"SkolemType(${binder.hashCode})"
2328+
override def toString = s"RefinedThis(${binder.hashCode})"
2329+
}
2330+
2331+
// ----- Skolem types -----------------------------------------------
2332+
2333+
/** A skolem type reference with underlying type `binder`. */
2334+
abstract case class SkolemType(info: Type) extends CachedProxyType with ValueType with SingletonType {
2335+
override def underlying(implicit ctx: Context) = info
2336+
def derivedSkolemType(info: Type)(implicit ctx: Context) =
2337+
if (info eq this.info) this else SkolemType(info)
2338+
override def computeHash = doHash(info)
2339+
override def toString = s"Skolem($info)"
2340+
}
2341+
2342+
final class CachedSkolemType(info: Type) extends SkolemType(info)
2343+
2344+
object SkolemType {
2345+
def apply(info: Type)(implicit ctx: Context) =
2346+
unique(new CachedSkolemType(info))
23262347
}
23272348

23282349
// ------------ Type variables ----------------------------------------
@@ -2883,6 +2904,9 @@ object Types {
28832904
case tp: AndOrType =>
28842905
tp.derivedAndOrType(this(tp.tp1), this(tp.tp2))
28852906

2907+
case tp: SkolemType =>
2908+
tp.derivedSkolemType(this(tp.info))
2909+
28862910
case tp @ AnnotatedType(annot, underlying) =>
28872911
val underlying1 = this(underlying)
28882912
if (underlying1 eq underlying) tp else tp.derivedAnnotatedType(mapOver(annot), underlying1)
@@ -3022,6 +3046,9 @@ object Types {
30223046
case tp: AndOrType =>
30233047
this(this(x, tp.tp1), tp.tp2)
30243048

3049+
case tp: SkolemType =>
3050+
this(x, tp.info)
3051+
30253052
case AnnotatedType(annot, underlying) =>
30263053
this(applyToAnnot(x, annot), underlying)
30273054

src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ Standard-Section: "ASTs" TopLevelStat*
103103
TERMREFpkg fullyQualified_NameRef
104104
TERMREF possiblySigned_NameRef qual_Type
105105
THIS clsRef_Type
106-
SKOLEMtype refinedType_ASTRef
106+
REFINEDthis refinedType_ASTRef
107+
SKOLEMtype Type_ASTRef
107108
SHARED path_ASTRef
108109
109-
110110
Constant = UNITconst
111111
FALSEconst
112112
TRUEconst
@@ -262,15 +262,16 @@ object TastyFormat {
262262
final val TERMREFpkg = 67
263263
final val TYPEREFpkg = 68
264264
final val SKOLEMtype = 69
265-
final val BYTEconst = 70
266-
final val SHORTconst = 71
267-
final val CHARconst = 72
268-
final val INTconst = 73
269-
final val LONGconst = 74
270-
final val FLOATconst = 75
271-
final val DOUBLEconst = 76
272-
final val STRINGconst = 77
273-
final val IMPORTED = 78
265+
final val REFINEDthis = 70
266+
final val BYTEconst = 71
267+
final val SHORTconst = 72
268+
final val CHARconst = 73
269+
final val INTconst = 74
270+
final val LONGconst = 75
271+
final val FLOATconst = 76
272+
final val DOUBLEconst = 77
273+
final val STRINGconst = 78
274+
final val IMPORTED = 79
274275

275276
final val THIS = 96
276277
final val CLASSconst = 97

src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,12 @@ class TreePickler(pickler: TastyPickler) {
198198
case tpe: SuperType =>
199199
writeByte(SUPERtype)
200200
withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe)}
201+
case tpe: RefinedThis =>
202+
writeByte(REFINEDthis)
203+
writeRef(pickledTypes.get(tpe.binder).asInstanceOf[Addr])
201204
case tpe: SkolemType =>
202205
writeByte(SKOLEMtype)
203-
writeRef(pickledTypes.get(tpe.binder).asInstanceOf[Addr])
206+
pickleType(tpe.info)
204207
case tpe: RefinedType =>
205208
val args = tpe.argInfos(interpolate = false)
206209
if (args.isEmpty) {

src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
254254
}
255255
case THIS =>
256256
ThisType.raw(readType().asInstanceOf[TypeRef])
257+
case REFINEDthis =>
258+
RefinedThis(readTypeRef().asInstanceOf[RefinedType])
257259
case SKOLEMtype =>
258260
SkolemType(readTypeRef())
259261
case SHARED =>

src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
689689
else {
690690
def addRefinement(tp: Type, sym: Symbol) = {
691691
def subst(info: Type, rt: RefinedType) =
692-
if (clazz.isClass) info.substThis(clazz.asClass, SkolemType(rt))
692+
if (clazz.isClass) info.substThis(clazz.asClass, RefinedThis(rt))
693693
else info // turns out some symbols read into `clazz` are not classes, not sure why this is the case.
694694
RefinedType(tp, sym.name, subst(sym.info, _))
695695
}

src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,10 @@ class PlainPrinter(_ctx: Context) extends Printer {
228228
toText(value)
229229
case MethodParam(mt, idx) =>
230230
nameString(mt.paramNames(idx))
231-
case sk: SkolemType =>
232-
sk.binder match {
233-
case rt: RefinedType => s"${nameString(rt.typeSymbol)}{...}.this"
234-
case _ => "<skolem>"
235-
}
231+
case tp: RefinedThis =>
232+
s"${nameString(tp.binder.typeSymbol)}{...}.this"
233+
case tp: SkolemType =>
234+
"<skolem>" // !!! todo refine with unique identifier.
236235
}
237236
}
238237

src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
172172
* parent { type Apply = body; argBindings? }
173173
*
174174
* split it into
175-
175+
176176
* - the `parent`
177177
* - the simplified `body`
178178
* - the bindings HK$ members, if there are any
@@ -190,7 +190,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
190190
// LambdaI{...}.HK$i
191191
val simplifyArgs = new TypeMap {
192192
override def apply(tp: Type) = tp match {
193-
case tp @ TypeRef(SkolemType(_), name) if name.isLambdaArgName =>
193+
case tp @ TypeRef(RefinedThis(_), name) if name.isLambdaArgName =>
194194
TypeRef(NoPrefix, tp.symbol.asType)
195195
case _ =>
196196
mapOver(tp)

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
812812
if ((rsym.is(Method) || rsym.isType) && rsym.allOverriddenSymbols.isEmpty)
813813
ctx.error(i"refinement $rsym without matching type in parent $parent", refinement.pos)
814814
val rinfo = if (rsym is Accessor) rsym.info.resultType else rsym.info
815-
RefinedType(parent, rsym.name, rt => rinfo.substThis(refineCls, SkolemType(rt)))
815+
RefinedType(parent, rsym.name, rt => rinfo.substThis(refineCls, RefinedThis(rt)))
816816
// todo later: check that refinement is within bounds
817817
}
818818
val res = cpy.RefinedTypeTree(tree)(tpt1, refinements1) withType

0 commit comments

Comments
 (0)