Skip to content

Commit 0c4c967

Browse files
authored
Merge pull request #15706 from dwijnand/one-tparam-used-twice
Allow refineUsingParent to infer GADT bounds
2 parents 7441a13 + c4f85a4 commit 0c4c967

File tree

6 files changed

+28
-4
lines changed

6 files changed

+28
-4
lines changed

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -1945,8 +1945,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
19451945
val tparam = tr.symbol
19461946
gadts.println(i"narrow gadt bound of $tparam: ${tparam.info} from ${if (isUpper) "above" else "below"} to $bound ${bound.toString} ${bound.isRef(tparam)}")
19471947
if (bound.isRef(tparam)) false
1948-
else if (isUpper) gadtAddUpperBound(tparam, bound)
1949-
else gadtAddLowerBound(tparam, bound)
1948+
else
1949+
val savedGadt = ctx.gadt.fresh
1950+
val success = if isUpper then gadtAddUpperBound(tparam, bound) else gadtAddLowerBound(tparam, bound)
1951+
if !success then ctx.gadt.restore(savedGadt)
1952+
success
19501953
}
19511954
}
19521955

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ object TypeOps:
712712

713713
val childTp = if (child.isTerm) child.termRef else child.typeRef
714714

715-
inContext(ctx.fresh.setExploreTyperState().setFreshGADTBounds) {
715+
inContext(ctx.fresh.setExploreTyperState().setFreshGADTBounds.addMode(Mode.GadtConstraintInference)) {
716716
instantiateToSubType(childTp, parent).dealias
717717
}
718718
}
@@ -829,6 +829,13 @@ object TypeOps:
829829
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
830830
val protoTp1 = inferThisMap.apply(tp1).appliedTo(tvars)
831831

832+
val getAbstractSymbols = new TypeAccumulator[List[Symbol]]:
833+
def apply(xs: List[Symbol], tp: Type) = tp.dealias match
834+
case tp: TypeRef if !tp.symbol.isClass => foldOver(tp.symbol :: xs, tp)
835+
case tp => foldOver(xs, tp)
836+
val syms2 = getAbstractSymbols(Nil, tp2).reverse
837+
if syms2.nonEmpty then ctx.gadt.addToConstraint(syms2)
838+
832839
// If parent contains a reference to an abstract type, then we should
833840
// refine subtype checking to eliminate abstract types according to
834841
// variance. As this logic is only needed in exhaustivity check,

compiler/test/dotty/tools/vulpix/ParallelTesting.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
168168
) extends TestSource {
169169
def sourceFiles: Array[JFile] = files.filter(isSourceFile)
170170

171-
override def toString() = outDir.toString
171+
override def toString() = sourceFiles match { case Array(f) => f.getPath case _ => outDir.getPath }
172172
}
173173

174174
/** A test source whose files will be compiled separately according to their

tests/neg-custom-args/fatal-warnings/suppressed-type-test-warnings.scala

+2
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ object Test {
1818
def err2[A, B](value: Foo[A, B], a: A => Int): B = value match {
1919
case b: Bar[B] => // spurious // error
2020
b.x
21+
case _ => ??? // avoid fatal inexhaustivity warnings suppressing the uncheckable warning
2122
}
2223

2324
def fail[A, B](value: Foo[A, B], a: A => Int): B = value match {
2425
case b: Bar[Int] => // error
2526
b.x
27+
case _ => ??? // avoid fatal inexhaustivity warnings suppressing the uncheckable warning
2628
}
2729
}

tests/pos/i13548.scala

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// scalac: -Werror
2+
sealed abstract class Foo[N, A]
3+
final case class Bar[B](foo: Foo[B, B]) extends Foo[B, B]
4+
class Test:
5+
def pmat[P, C](scr: Foo[P, C]): C = scr match
6+
case Bar(foo) => pmat(foo)

tests/pos/i15289.scala

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// scalac: -Werror
2+
sealed abstract class Foo[A, B]
3+
final case class Bar[C](baz: C) extends Foo[C, C]
4+
5+
class Test:
6+
def m1[X](f1: Foo[X, String]): String = f1 match { case Bar(_) => "" }

0 commit comments

Comments
 (0)