Skip to content

Commit d46f508

Browse files
committed
Fix subtyping flexible type with type parameters
1 parent e0072c8 commit d46f508

File tree

3 files changed

+25
-28
lines changed

3 files changed

+25
-28
lines changed

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -388,10 +388,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
388388
case OrType(tp21, tp22) =>
389389
if (tp21.stripTypeVar eq tp22.stripTypeVar) recur(tp1, tp21)
390390
else secondTry
391-
// tp1 <: Flex(T) = T|N..T
392-
// iff tp1 <: T|N
393-
case tp2: FlexibleType =>
394-
recur(tp1, tp2.lo)
395391
case TypeErasure.ErasedValueType(tycon1, underlying2) =>
396392
def compareErasedValueType = tp1 match {
397393
case TypeErasure.ErasedValueType(tycon2, underlying1) =>
@@ -529,10 +525,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
529525
constraint = constraint.hardenTypeVars(tp2)
530526

531527
res
532-
// invariant: tp2 is NOT a FlexibleType
533-
// is Flex(T) <: tp2?
534-
case tp1: FlexibleType =>
535-
recur(tp1.hi, tp2)
536528
case tp1 @ CapturingType(parent1, refs1) =>
537529
def compareCapturing =
538530
if tp2.isAny then true
@@ -871,6 +863,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
871863
false
872864
}
873865
compareClassInfo
866+
// tp1 <: Flex(T) = T|N..T
867+
// iff tp1 <: T|N
868+
case tp2: FlexibleType =>
869+
recur(tp1, tp2.lo)
874870
case _ =>
875871
fourthTry
876872
}
@@ -1066,6 +1062,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
10661062
case tp1: ExprType if ctx.phaseId > gettersPhase.id =>
10671063
// getters might have converted T to => T, need to compensate.
10681064
recur(tp1.widenExpr, tp2)
1065+
// invariant: tp2 is NOT a FlexibleType
1066+
// is Flex(T) <: tp2?
1067+
case tp1: FlexibleType =>
1068+
recur(tp1.hi, tp2)
10691069
case _ =>
10701070
false
10711071
}

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

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,6 @@ object Types extends TypeUtils {
281281
tp.bound.derivesFrom(cls) || tp.reduced.derivesFrom(cls)
282282
case tp: TypeProxy =>
283283
loop(tp.underlying)
284-
case tp: FlexibleType =>
285-
loop(tp.underlying)
286284
case tp: AndType =>
287285
loop(tp.tp1) || loop(tp.tp2)
288286
case tp: OrType =>
@@ -345,6 +343,7 @@ object Types extends TypeUtils {
345343
/** Is this type guaranteed not to have `null` as a value? */
346344
final def isNotNull(using Context): Boolean = this match {
347345
case tp: ConstantType => tp.value.value != null
346+
case tp: FlexibleType => false
348347
case tp: ClassInfo => !tp.cls.isNullableClass && tp.cls != defn.NothingClass
349348
case tp: AppliedType => tp.superType.isNotNull
350349
case tp: TypeBounds => tp.lo.isNotNull
@@ -754,8 +753,6 @@ object Types extends TypeUtils {
754753
case d: ClassDenotation => d.findMember(name, pre, required, excluded)
755754
case d => go(d.info)
756755
}
757-
case tp: FlexibleType =>
758-
go(tp.underlying)
759756
case tp: AppliedType =>
760757
tp.tycon match {
761758
case tc: TypeRef =>
@@ -968,8 +965,6 @@ object Types extends TypeUtils {
968965
if (keepOnly(pre, tp.refinedName)) ns + tp.refinedName else ns
969966
case tp: TypeProxy =>
970967
tp.superType.memberNames(keepOnly, pre)
971-
case tp: FlexibleType =>
972-
tp.underlying.memberNames(keepOnly, pre)
973968
case tp: AndType =>
974969
tp.tp1.memberNames(keepOnly, pre) | tp.tp2.memberNames(keepOnly, pre)
975970
case tp: OrType =>
@@ -1427,7 +1422,6 @@ object Types extends TypeUtils {
14271422
case tp: ExprType => tp.resType.atoms
14281423
case tp: OrType => tp.atoms // `atoms` overridden in OrType
14291424
case tp: AndType => tp.tp1.atoms & tp.tp2.atoms
1430-
case tp: FlexibleType => tp.underlying.atoms
14311425
case tp: TypeRef if tp.symbol.is(ModuleClass) =>
14321426
// The atom of a module class is the module itself,
14331427
// this corresponds to the special case in TypeComparer
@@ -3410,26 +3404,30 @@ object Types extends TypeUtils {
34103404
* in Kotlin. A FlexibleType(T) generally behaves like an abstract type with bad bounds
34113405
* T|Null .. T, so that T|Null <: FlexibleType(T) <: T.
34123406
*/
3413-
case class FlexibleType(underlying: Type, lo: Type, hi: Type) extends CachedGroundType with ValueType {
3414-
def derivedFlexibleType(underlying: Type)(using Context): Type =
3415-
if this.underlying eq underlying then this else FlexibleType(underlying)
3407+
case class FlexibleType(original: Type, lo: Type, hi: Type) extends CachedProxyType with ValueType {
3408+
def underlying(using Context): Type = original
34163409

3417-
override def computeHash(bs: Binders): Int = doHash(bs, underlying)
3410+
override def superType(using Context): Type = hi
34183411

3419-
override final def baseClasses(using Context): List[ClassSymbol] = underlying.baseClasses
3412+
def derivedFlexibleType(original: Type)(using Context): Type =
3413+
if this.original eq original then this else FlexibleType(original)
3414+
3415+
override def computeHash(bs: Binders): Int = doHash(bs, original)
3416+
3417+
override final def baseClasses(using Context): List[ClassSymbol] = original.baseClasses
34203418
}
34213419

34223420
object FlexibleType {
3423-
def apply(underlying: Type)(using Context): FlexibleType = underlying match {
3421+
def apply(original: Type)(using Context): FlexibleType = original match {
34243422
case ft: FlexibleType => ft
34253423
case _ =>
3426-
val hi = underlying.stripNull
3427-
val lo = if hi eq underlying then OrNull(hi) else underlying
3428-
new FlexibleType(underlying, lo, hi)
3424+
val hi = original.stripNull
3425+
val lo = if hi eq original then OrNull(hi) else original
3426+
new FlexibleType(original, lo, hi)
34293427
}
34303428

34313429
def unapply(tp: Type)(using Context): Option[Type] = tp match {
3432-
case ft: FlexibleType => Some(ft.underlying)
3430+
case ft: FlexibleType => Some(ft.original)
34333431
case _ => None
34343432
}
34353433
}
@@ -5699,6 +5697,7 @@ object Types extends TypeUtils {
56995697
val args1 = args.zipWithConserve(tparams):
57005698
case (arg @ TypeBounds(lo, hi), tparam) =>
57015699
boundFollowingVariance(lo, hi, tparam)
5700+
// TODO: why do we need this?
57025701
case (arg: FlexibleType, tparam) =>
57035702
boundFollowingVariance(arg.lo, arg.hi, tparam)
57045703
case (arg, _) => arg
@@ -5737,7 +5736,7 @@ object Types extends TypeUtils {
57375736
case tp: AnnotatedType =>
57385737
samClass(tp.underlying)
57395738
case tp: FlexibleType =>
5740-
samClass(tp.underlying)
5739+
samClass(tp.superType)
57415740
case _ =>
57425741
NoSymbol
57435742

compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Erasure.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,6 @@ object Scala2Erasure:
8888
tpw
8989
else
9090
sym
91-
case tpw: FlexibleType =>
92-
pseudoSymbol(tpw.underlying)
9391
case tpw: TypeProxy =>
9492
pseudoSymbol(tpw.underlying)
9593
case tpw: JavaArrayType =>

0 commit comments

Comments
 (0)