Skip to content

Commit 8c12eea

Browse files
committed
Simplify capture conversion scheme
Instead of computing a new type where each wildcard argument is replaced by `<some skolem>.CAP`, we can simply introduce a skolem for the tree's type instead. This well turn the type into a singleton so that then the capture conversions for singletons in isSubArgs can kick in.
1 parent abb8146 commit 8c12eea

File tree

5 files changed

+17
-46
lines changed

5 files changed

+17
-46
lines changed

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -755,10 +755,6 @@ class Definitions {
755755

756756
def Eql_eqlAny(implicit ctx: Context): TermSymbol = EqlModule.requiredMethod(nme.eqlAny)
757757

758-
lazy val TypeBoxType: TypeRef = ctx.requiredClassRef("scala.internal.TypeBox")
759-
760-
lazy val TypeBox_CAP: TypeSymbol = TypeBoxType.symbol.requiredType(tpnme.CAP)
761-
762758
lazy val NotType: TypeRef = ctx.requiredClassRef("scala.implicits.Not")
763759
def NotClass(implicit ctx: Context): ClassSymbol = NotType.symbol.asClass
764760
def NotModule(implicit ctx: Context): Symbol = NotClass.companionModule

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,6 @@ object StdNames {
326326
val AnnotatedType: N = "AnnotatedType"
327327
val AppliedTypeTree: N = "AppliedTypeTree"
328328
val ArrayAnnotArg: N = "ArrayAnnotArg"
329-
val CAP: N = "CAP"
330329
val Constant: N = "Constant"
331330
val ConstantType: N = "ConstantType"
332331
val doubleHash: N = "doubleHash"

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,8 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
10411041
arg1 match {
10421042
case arg1: TypeBounds =>
10431043
tparam match {
1044-
case tparam: Symbol if leftRoot.isStable || ctx.isAfterTyper =>
1044+
case tparam: Symbol
1045+
if leftRoot.isStable || ctx.isAfterTyper || ctx.mode.is(Mode.TypevarsMissContext) =>
10451046
val captured = TypeRef(leftRoot, tparam)
10461047
isSubArg(captured, arg2)
10471048
case _ =>

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

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2698,46 +2698,26 @@ class Typer extends Namer
26982698
case tree: Closure => cpy.Closure(tree)(tpt = TypeTree(pt)).withType(pt)
26992699
}
27002700

2701-
/** Replace every top-level occurrence of a wildcard type argument by
2702-
* a skolem type
2703-
*/
2704-
def captureWildcards(tp: Type)(implicit ctx: Context): Type = tp match {
2705-
case tp: AndOrType => tp.derivedAndOrType(captureWildcards(tp.tp1), captureWildcards(tp.tp2))
2706-
case tp: RefinedType => tp.derivedRefinedType(captureWildcards(tp.parent), tp.refinedName, tp.refinedInfo)
2707-
case tp: RecType => tp.derivedRecType(captureWildcards(tp.parent))
2708-
case tp: LazyRef => captureWildcards(tp.ref)
2709-
case tp: AnnotatedType => tp.derivedAnnotatedType(captureWildcards(tp.parent), tp.annot)
2710-
case tp @ AppliedType(tycon, args) if tp.hasWildcardArg =>
2711-
tycon.typeParams match {
2712-
case tparams @ ((_: Symbol) :: _) =>
2713-
val args1 = args.map {
2714-
case TypeBounds(lo, hi) =>
2715-
val skolem = SkolemType(defn.TypeBoxType.appliedTo(lo, hi))
2716-
TypeRef(skolem, defn.TypeBox_CAP)
2717-
case arg => arg
2718-
}
2719-
val boundss = tparams.map(_.paramInfo.subst(tparams.asInstanceOf[List[TypeSymbol]], args1))
2720-
for ((newArg, oldArg, bounds) <- (args1, args, boundss).zipped)
2721-
if (newArg `ne` oldArg) {
2722-
val TypeRef(skolem @ SkolemType(app @ AppliedType(typeBox, lo :: hi :: Nil)), _) = newArg
2723-
skolem.info = app.derivedAppliedType(
2724-
typeBox, (lo | bounds.loBound) :: (hi & bounds.hiBound) :: Nil)
2725-
}
2726-
tp.derivedAppliedType(tycon, args1)
2727-
case _ =>
2728-
tp
2729-
}
2730-
case _ => tp
2701+
def hasWildcardArg(tp: Type): Boolean = tp match {
2702+
case tp: AppliedType => tp.hasWildcardArg
2703+
case tp: AndOrType => hasWildcardArg(tp.tp1) || hasWildcardArg(tp.tp2)
2704+
case _: SingletonType | _: HKTypeLambda => false
2705+
case tp: TypeProxy => hasWildcardArg(tp.superType)
2706+
case _ => false
27312707
}
27322708

27332709
def adaptToSubType(wtp: Type): Tree = {
27342710
// try converting a constant to the target type
27352711
val folded = ConstFold(tree, pt)
2736-
if (folded ne tree) return adaptConstant(folded, folded.tpe.asInstanceOf[ConstantType])
2737-
2738-
// Try to capture wildcards in type
2739-
val captured = captureWildcards(wtp)
2740-
if (captured `ne` wtp) return readapt(tree.cast(captured))
2712+
if (folded ne tree)
2713+
return adaptConstant(folded, folded.tpe.asInstanceOf[ConstantType])
2714+
2715+
// If tree's type is not stable and has wildcard arguments, make it
2716+
// stable by casting it to a skolem. I.e. a tree `t` of widened type `T`
2717+
// gets widened to `t.$asInstanceOf$[SkolemType(T)]`. This will enable
2718+
// capture comversion in the subsequent subtype check.
2719+
if (!tree.tpe.isStable && hasWildcardArg(wtp) && !ctx.isAfterTyper)
2720+
return readapt(tree.cast(SkolemType(wtp)))
27412721

27422722
// drop type if prototype is Unit
27432723
if (pt isRef defn.UnitClass) {

library/src-bootstrapped/scala/internal/TypeBox.scala

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)