Skip to content

Commit 940b011

Browse files
Fix scala#12800: Clarify MT reduction error on empty scrutinee
1 parent cb2df55 commit 940b011

File tree

3 files changed

+36
-2
lines changed

3 files changed

+36
-2
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ object MatchTypeTrace:
1313
case TryReduce(scrut: Type)
1414
case NoMatches(scrut: Type, cases: List[Type])
1515
case Stuck(scrut: Type, stuckCase: Type, otherCases: List[Type])
16+
case EmptyScrutinee(scrut: Type)
1617
import TraceEntry._
1718

1819
private class MatchTrace:
@@ -61,6 +62,12 @@ object MatchTypeTrace:
6162
def stuck(scrut: Type, stuckCase: Type, otherCases: List[Type])(using Context) =
6263
matchTypeFail(Stuck(scrut, stuckCase, otherCases))
6364

65+
/** Record a failure that scrutinee `scrut` is provably empty.
66+
* Only the first failure is recorded.
67+
*/
68+
def emptyScrutinee(scrut: Type)(using Context) =
69+
matchTypeFail(EmptyScrutinee(scrut))
70+
6471
/** Record in the trace that we are trying to reduce `scrut` when performing `op`
6572
* If `op` succeeds the entry is removed after exit. If `op` fails, it stays.
6673
*/
@@ -91,6 +98,9 @@ object MatchTypeTrace:
9198
| matches none of the cases
9299
|
93100
| ${casesText(cases)}"""
101+
case EmptyScrutinee(scrut) =>
102+
i""" failed since selector $scrut
103+
| is uninhabited."""
94104
case Stuck(scrut, stuckCase, otherCases) =>
95105
i""" failed since selector $scrut
96106
| does not match ${caseText(stuckCase)}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,8 +2921,11 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
29212921
// obviously sound, but quite restrictive. With the current formulation,
29222922
// we need to be careful that `provablyEmpty` covers all the conditions
29232923
// used to conclude disjointness in `provablyDisjoint`.
2924-
if (provablyEmpty(scrut)) NoType
2925-
else recur(cases)
2924+
if (provablyEmpty(scrut))
2925+
MatchTypeTrace.emptyScrutinee(scrut)
2926+
NoType
2927+
else
2928+
recur(cases)
29262929
}
29272930
}
29282931
}

tests/neg/12800.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
object Test {
2+
type FieldType2[K, +V] = V with KeyTag2[K, V]
3+
trait KeyTag2[K, +V] extends Any
4+
5+
type WrapUpper = Tuple
6+
type Wrap[A] = Tuple1[A]
7+
8+
type Extract[A <: WrapUpper] = A match {
9+
case Wrap[h] => h
10+
}
11+
12+
summon[Extract[Wrap[FieldType2["foo", Int]]] =:= FieldType2["foo", Int]] // error
13+
// ^
14+
// Cannot prove that Main.Extract[Tuple1[Main.FieldType2[("foo" : String), Int]]] =:= Main.FieldType2[("foo" : String), Int].
15+
//
16+
// Note: a match type could not be fully reduced:
17+
//
18+
// trying to reduce Main.Extract[Tuple1[Main.FieldType2[("foo" : String), Int]]]
19+
// failed since selector Tuple1[Main.FieldType2[("foo" : String), Int]]
20+
// is uninhabited.
21+
}

0 commit comments

Comments
 (0)