Skip to content

Commit 53f95d1

Browse files
authored
Merge pull request #9071 from dotty-staging/fix-9067
2 parents d2bc109 + a6ab570 commit 53f95d1

File tree

6 files changed

+33
-31
lines changed

6 files changed

+33
-31
lines changed

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

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import config.Feature
1818
import typer.Applications._
1919
import typer.ProtoTypes._
2020
import typer.ForceDegree
21-
import typer.Inferencing.isFullyDefined
21+
import typer.Inferencing._
2222
import typer.IfBottom
2323

2424
import scala.annotation.internal.sharable
@@ -618,8 +618,9 @@ object TypeOps:
618618

619619
val childTp = if (child.isTerm) child.termRef else child.typeRef
620620

621-
instantiateToSubType(childTp, parent)(using ctx.fresh.setNewTyperState())
622-
.dealias
621+
inContext(ctx.fresh.setExploreTyperState().setFreshGADTBounds) {
622+
instantiateToSubType(childTp, parent).dealias
623+
}
623624
}
624625

625626
/** Instantiate type `tp1` to be a subtype of `tp2`
@@ -668,10 +669,11 @@ object TypeOps:
668669
def minTypeMap(implicit ctx: Context) = new AbstractTypeMap(maximize = false)
669670
def maxTypeMap(implicit ctx: Context) = new AbstractTypeMap(maximize = true)
670671

671-
// Fix subtype checking for child instantiation,
672-
// such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
672+
// Prefix inference, replace `p.C.this.Child` with `X.Child` where `X <: p.C`
673+
// Note: we need to strip ThisType in `p` recursively.
674+
//
673675
// See tests/patmat/i3938.scala
674-
class RemoveThisMap extends TypeMap {
676+
class InferPrefixMap extends TypeMap {
675677
var prefixTVar: Type = null
676678
def apply(tp: Type): Type = tp match {
677679
case ThisType(tref: TypeRef) if !tref.symbol.isStaticOwner =>
@@ -688,22 +690,14 @@ object TypeOps:
688690
}
689691
}
690692

691-
// replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
692-
def instUndetMap(implicit ctx: Context) = new TypeMap {
693-
def apply(t: Type): Type = t match {
694-
case tvar: TypeVar if !tvar.isInstantiated => WildcardType(tvar.origin.underlying.bounds)
695-
case _ => mapOver(t)
696-
}
697-
}
698-
699-
val removeThisType = new RemoveThisMap
693+
val inferThisMap = new InferPrefixMap
700694
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
701-
val protoTp1 = removeThisType.apply(tp1).appliedTo(tvars)
695+
val protoTp1 = inferThisMap.apply(tp1).appliedTo(tvars)
702696

703697
val force = new ForceDegree.Value(
704698
tvar =>
705699
!(ctx.typerState.constraint.entry(tvar.origin) `eq` tvar.origin.underlying) ||
706-
(tvar `eq` removeThisType.prefixTVar),
700+
(tvar `eq` inferThisMap.prefixTVar), // always instantiate prefix
707701
IfBottom.flip
708702
)
709703

@@ -718,14 +712,15 @@ object TypeOps:
718712
}
719713
}
720714

721-
if (protoTp1 <:< tp2)
722-
if (isFullyDefined(protoTp1, force)) protoTp1
723-
else instUndetMap.apply(protoTp1)
715+
if (protoTp1 <:< tp2) {
716+
maximizeType(protoTp1, NoSpan, fromScala2x = false)
717+
wildApprox(protoTp1)
718+
}
724719
else {
725720
val protoTp2 = maxTypeMap.apply(tp2)
726721
if (protoTp1 <:< protoTp2 || parentQualify)
727722
if (isFullyDefined(AndType(protoTp1, protoTp2), force)) protoTp1
728-
else instUndetMap.apply(protoTp1)
723+
else wildApprox(protoTp1)
729724
else {
730725
typr.println(s"$protoTp1 <:< $protoTp2 = false")
731726
NoType

compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,20 @@ object TypeTestsCasts {
5555
*/
5656
def checkable(X: Type, P: Type, span: Span)(using Context): Boolean = {
5757
def isAbstract(P: Type) = !P.dealias.typeSymbol.isClass
58-
def isPatternTypeSymbol(sym: Symbol) = !sym.isClass && sym.is(Case)
5958

6059
def replaceP(tp: Type)(implicit ctx: Context) = new TypeMap {
6160
def apply(tp: Type) = tp match {
62-
case tref: TypeRef
63-
if isPatternTypeSymbol(tref.typeSymbol) => WildcardType
64-
case AnnotatedType(_, annot)
65-
if annot.symbol == defn.UncheckedAnnot => WildcardType
61+
case tref: TypeRef if tref.typeSymbol.isPatternBound =>
62+
WildcardType
63+
case AnnotatedType(_, annot) if annot.symbol == defn.UncheckedAnnot =>
64+
WildcardType
6665
case _ => mapOver(tp)
6766
}
6867
}.apply(tp)
6968

7069
def replaceX(tp: Type)(implicit ctx: Context) = new TypeMap {
7170
def apply(tp: Type) = tp match {
72-
case tref: TypeRef
73-
if isPatternTypeSymbol(tref.typeSymbol) =>
71+
case tref: TypeRef if tref.typeSymbol.isPatternBound =>
7472
if (variance == 1) tref.info.hiBound
7573
else if (variance == -1) tref.info.loBound
7674
else OrType(defn.AnyType, defn.NothingType)

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
464464
* }
465465
*/
466466
private def erase(tp: Type, inArray: Boolean = false): Type = trace(i"$tp erased to", debug) {
467-
def isPatternTypeSymbol(sym: Symbol) = !sym.isClass && sym.is(Case)
468467

469468
tp match {
470469
case tp @ AppliedType(tycon, args) =>
@@ -476,7 +475,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
476475
AndType(erase(tp1, inArray), erase(tp2, inArray))
477476
case tp @ RefinedType(parent, _, _) =>
478477
erase(parent)
479-
case tref: TypeRef if isPatternTypeSymbol(tref.typeSymbol) =>
478+
case tref: TypeRef if tref.typeSymbol.isPatternBound =>
480479
if (inArray) tref.underlying else WildcardType
481480
case _ => tp
482481
}

tests/patmat/i3938.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
34: Pattern Match Exhaustivity: bar.C()

tests/patmat/i3938.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,15 @@ class Test {
2323
val foo = new Foo
2424
import foo.bar._
2525

26-
def test(a: A) = {
26+
def h(a: A) = {
2727
a match {
2828
case B() => 1
2929
case _ => 2 // unreachable code
3030
}
3131
}
32+
33+
def f(a: A) =
34+
a match {
35+
case B() => 1
36+
}
3237
}

tests/patmat/i9067.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
sealed trait Base[A, +B]
2+
case class Foo[A, +B](f: A => B) extends Base[A, B]
3+
4+
def bar(x: Base[Any, Any]): Unit = x match { case Foo(_) => }

0 commit comments

Comments
 (0)