Skip to content

Commit 09b8754

Browse files
committed
Make SkolemTypes immutable and non-recursive.
Since we now map the info of a SkolemType as part of mapping the SkolemType itself, it follows that SkolemTypes can't recursively refer to themselves. So `captureWildcards` in `Typer` avoids recursion now by using an approximating substitution instead (I wonder now how we ever could live without approximating substitutions!). This means that SkolemTypes don't need to be mutable anymore since there is no fixed point to construct.
1 parent 788fac8 commit 09b8754

File tree

2 files changed

+11
-19
lines changed

2 files changed

+11
-19
lines changed

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3618,12 +3618,8 @@ object Types {
36183618

36193619
// ----- Skolem types -----------------------------------------------
36203620

3621-
/** A skolem type reference with underlying type `info`.
3622-
* Note: `info` is a var, since this allows one to create a number of skolem types
3623-
* and fill in their infos with types that refers to the skolem types recursively.
3624-
* This is used in `captureWildcards` in `Typer`.
3625-
*/
3626-
case class SkolemType(private[dotc] var info: Type) extends UncachedProxyType with ValueType with SingletonType {
3621+
/** A skolem type reference with underlying type `info` */
3622+
case class SkolemType(info: Type) extends UncachedProxyType with ValueType with SingletonType {
36273623
override def underlying(implicit ctx: Context): Type = info
36283624
def derivedSkolemType(info: Type)(implicit ctx: Context): SkolemType =
36293625
if (info eq this.info) this else SkolemType(info)

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

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,7 +2701,7 @@ class Typer extends Namer
27012701
/** Replace every top-level occurrence of a wildcard type argument by
27022702
* a fresh skolem type. The skolem types are of the form $i.CAP, where
27032703
* $i is a skolem of type `scala.internal.TypeBox`, and `CAP` is its
2704-
* type member.
2704+
* type member. See the documentation of `TypeBox` for a rationale why we do this.
27052705
*/
27062706
def captureWildcards(tp: Type)(implicit ctx: Context): Type = tp match {
27072707
case tp: AndOrType => tp.derivedAndOrType(captureWildcards(tp.tp1), captureWildcards(tp.tp2))
@@ -2712,19 +2712,15 @@ class Typer extends Namer
27122712
case tp @ AppliedType(tycon, args) if tp.hasWildcardArg =>
27132713
tycon.typeParams match {
27142714
case tparams @ ((_: Symbol) :: _) =>
2715-
val args1 = args.map {
2716-
case TypeBounds(lo, hi) =>
2717-
val skolem = SkolemType(defn.TypeBoxType.appliedTo(lo, hi))
2718-
TypeRef(skolem, defn.TypeBox_CAP)
2719-
case arg => arg
2720-
}
2721-
val boundss = tparams.map(_.paramInfo.subst(tparams.asInstanceOf[List[TypeSymbol]], args1))
2722-
for ((newArg, oldArg, bounds) <- (args1, args, boundss).zipped)
2723-
if (newArg `ne` oldArg) {
2724-
val TypeRef(skolem @ SkolemType(app @ AppliedType(typeBox, lo :: hi :: Nil)), _) = newArg
2725-
skolem.info = app.derivedAppliedType(
2726-
typeBox, (lo | bounds.loBound) :: (hi & bounds.hiBound) :: Nil)
2715+
val boundss = tparams.map(_.paramInfo.substApprox(tparams.asInstanceOf[List[TypeSymbol]], args))
2716+
val args1 = args.zipWithConserve(boundss) { (arg, bounds) =>
2717+
arg match {
2718+
case TypeBounds(lo, hi) =>
2719+
val skolem = SkolemType(defn.TypeBoxType.appliedTo(lo | bounds.loBound, hi & bounds.hiBound))
2720+
TypeRef(skolem, defn.TypeBox_CAP)
2721+
case arg => arg
27272722
}
2723+
}
27282724
tp.derivedAppliedType(tycon, args1)
27292725
case _ =>
27302726
tp

0 commit comments

Comments
 (0)