Skip to content

Commit 4841ecb

Browse files
committed
Fix #9067: avoid instantiate child parameters to Wildcard if possible
In tests/patmat/i9067.scala, for Foo[X1, X2] <: Base[Any, Any], X1 and X2 can both be `Any` instead of `Wildcard`. Inferring `Wildcard` will lead to the signature of `Foo.unapply` be inferred as `Nothing => Nothing`, which causes the checker to issue a false unexhaustive warning.
1 parent 4fa9e5a commit 4841ecb

File tree

2 files changed

+18
-7
lines changed

2 files changed

+18
-7
lines changed

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

Lines changed: 14 additions & 7 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`
@@ -685,10 +686,15 @@ object TypeOps:
685686
}
686687
}
687688

689+
def isPatternTypeSymbol(sym: Symbol) = !sym.isClass && sym.is(Case)
690+
688691
// replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
689692
def instUndetMap(implicit ctx: Context) = new TypeMap {
690693
def apply(t: Type): Type = t match {
691-
case tvar: TypeVar if !tvar.isInstantiated => WildcardType(tvar.origin.underlying.bounds)
694+
case tvar: TypeVar if !tvar.isInstantiated =>
695+
WildcardType(tvar.origin.underlying.bounds)
696+
case tref: TypeRef if isPatternTypeSymbol(tref.typeSymbol) =>
697+
WildcardType(tref.underlying.bounds)
692698
case _ => mapOver(t)
693699
}
694700
}
@@ -715,9 +721,10 @@ object TypeOps:
715721
}
716722
}
717723

718-
if (protoTp1 <:< tp2)
719-
if (isFullyDefined(protoTp1, force)) protoTp1
720-
else instUndetMap.apply(protoTp1)
724+
if (protoTp1 <:< tp2) {
725+
maximizeType(protoTp1, NoSpan, fromScala2x = false)
726+
instUndetMap.apply(protoTp1)
727+
}
721728
else {
722729
val protoTp2 = maxTypeMap.apply(tp2)
723730
if (protoTp1 <:< protoTp2 || parentQualify)

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)