Skip to content

Commit bf1b9a6

Browse files
committed
Address review
1 parent 5781514 commit bf1b9a6

File tree

1 file changed

+25
-4
lines changed

1 file changed

+25
-4
lines changed

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,9 @@ object TypeOps:
658658
* Otherwise, return NoType.
659659
*/
660660
private def instantiateToSubType(tp1: NamedType, tp2: Type)(using Context): Type = {
661-
/** expose abstract type references to their bounds or tvars according to variance */
661+
// In order for a child type S to qualify as a valid subtype of the parent
662+
// T, we need to test whether it is possible S <: T. Therefore, we replace
663+
// type parameters in T with tvars, and see if the subtyping is true.
662664
val approximateTypeParams = new TypeMap {
663665
val boundTypeParams = util.HashMap[TypeRef, TypeVar]()
664666

@@ -683,8 +685,27 @@ object TypeOps:
683685
end if
684686

685687
case AppliedType(tycon: TypeRef, _) if !tycon.dealias.typeSymbol.isClass =>
686-
// Type inference cannot handle X[Y] <:< Int
687-
// See tests/patmat/i3645g.scala
688+
689+
// In tests/patmat/i3645g.scala, we need to tell whether it's possible
690+
// that K1 <: K[Foo]. If yes, we issue a warning; otherwise, no
691+
// warnings.
692+
//
693+
// - K1 <: K[Foo] is possible <==>
694+
// - K[Int] <: K[Foo] is possible <==>
695+
// - Int <: Foo is possible <==>
696+
// - Int <: Module.Foo.Type is possible
697+
//
698+
// If we remove this special case, we will encounter the case Int <:
699+
// X[Y], where X and Y are tvars. The subtype checking will simply
700+
// return false. But depending on the bounds of X and Y, the subtyping
701+
// can be true.
702+
//
703+
// As a workaround, we approximate higher-kinded type parameters with
704+
// the value types that can be instantiated from its bounds.
705+
//
706+
// Note that `HKTypeLambda.resType` may contain TypeParamRef that are
707+
// bound in the HKTypeLambda. This is fine, as the TypeComparer will
708+
// recurse on the bounds of `TypeParamRef`.
688709
val bounds: TypeBounds = tycon.underlying match {
689710
case TypeBounds(tl1: HKTypeLambda, tl2: HKTypeLambda) =>
690711
TypeBounds(tl1.resType, tl2.resType)
@@ -730,7 +751,7 @@ object TypeOps:
730751
// refine subtype checking to eliminate abstract types according to
731752
// variance. As this logic is only needed in exhaustivity check,
732753
// we manually patch subtyping check instead of changing TypeComparer.
733-
// See tests/patmat/3645b.scala
754+
// See tests/patmat/i3645b.scala
734755
def parentQualify(tp1: Type, tp2: Type) = tp1.widen.classSymbol.info.parents.exists { parent =>
735756
parent.argInfos.nonEmpty && approximateTypeParams(parent) <:< tp2
736757
}

0 commit comments

Comments
 (0)