diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 8c41390a38d2..993df88f5544 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1945,8 +1945,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling val tparam = tr.symbol gadts.println(i"narrow gadt bound of $tparam: ${tparam.info} from ${if (isUpper) "above" else "below"} to $bound ${bound.toString} ${bound.isRef(tparam)}") if (bound.isRef(tparam)) false - else if (isUpper) gadtAddUpperBound(tparam, bound) - else gadtAddLowerBound(tparam, bound) + else + val savedGadt = ctx.gadt.fresh + val success = if isUpper then gadtAddUpperBound(tparam, bound) else gadtAddLowerBound(tparam, bound) + if !success then ctx.gadt.restore(savedGadt) + success } } diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 25e43efb7885..0174fb2f3da9 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -712,7 +712,7 @@ object TypeOps: val childTp = if (child.isTerm) child.termRef else child.typeRef - inContext(ctx.fresh.setExploreTyperState().setFreshGADTBounds) { + inContext(ctx.fresh.setExploreTyperState().setFreshGADTBounds.addMode(Mode.GadtConstraintInference)) { instantiateToSubType(childTp, parent).dealias } } @@ -829,6 +829,13 @@ object TypeOps: val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) } val protoTp1 = inferThisMap.apply(tp1).appliedTo(tvars) + val getAbstractSymbols = new TypeAccumulator[List[Symbol]]: + def apply(xs: List[Symbol], tp: Type) = tp.dealias match + case tp: TypeRef if !tp.symbol.isClass => foldOver(tp.symbol :: xs, tp) + case tp => foldOver(xs, tp) + val syms2 = getAbstractSymbols(Nil, tp2).reverse + if syms2.nonEmpty then ctx.gadt.addToConstraint(syms2) + // If parent contains a reference to an abstract type, then we should // refine subtype checking to eliminate abstract types according to // variance. As this logic is only needed in exhaustivity check, diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 9e898a68a1e8..fb60d98ea5cf 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -168,7 +168,7 @@ trait ParallelTesting extends RunnerOrchestration { self => ) extends TestSource { def sourceFiles: Array[JFile] = files.filter(isSourceFile) - override def toString() = outDir.toString + override def toString() = sourceFiles match { case Array(f) => f.getPath case _ => outDir.getPath } } /** A test source whose files will be compiled separately according to their diff --git a/tests/neg-custom-args/fatal-warnings/suppressed-type-test-warnings.scala b/tests/neg-custom-args/fatal-warnings/suppressed-type-test-warnings.scala index 175096fc6b21..92d86b3307e5 100644 --- a/tests/neg-custom-args/fatal-warnings/suppressed-type-test-warnings.scala +++ b/tests/neg-custom-args/fatal-warnings/suppressed-type-test-warnings.scala @@ -18,10 +18,12 @@ object Test { def err2[A, B](value: Foo[A, B], a: A => Int): B = value match { case b: Bar[B] => // spurious // error b.x + case _ => ??? // avoid fatal inexhaustivity warnings suppressing the uncheckable warning } def fail[A, B](value: Foo[A, B], a: A => Int): B = value match { case b: Bar[Int] => // error b.x + case _ => ??? // avoid fatal inexhaustivity warnings suppressing the uncheckable warning } } diff --git a/tests/pos/i13548.scala b/tests/pos/i13548.scala new file mode 100644 index 000000000000..2f2f62e17878 --- /dev/null +++ b/tests/pos/i13548.scala @@ -0,0 +1,6 @@ +// scalac: -Werror +sealed abstract class Foo[N, A] +final case class Bar[B](foo: Foo[B, B]) extends Foo[B, B] +class Test: + def pmat[P, C](scr: Foo[P, C]): C = scr match + case Bar(foo) => pmat(foo) diff --git a/tests/pos/i15289.scala b/tests/pos/i15289.scala new file mode 100644 index 000000000000..5eea2fe9f91f --- /dev/null +++ b/tests/pos/i15289.scala @@ -0,0 +1,6 @@ +// scalac: -Werror +sealed abstract class Foo[A, B] +final case class Bar[C](baz: C) extends Foo[C, C] + +class Test: + def m1[X](f1: Foo[X, String]): String = f1 match { case Bar(_) => "" }