Skip to content

Commit 7825d77

Browse files
committed
In compareMatch, check scrutinees are subtypes
From the Match Type paper, typing rule S-Match5 requires that the LHS scrutinee "Ss" is a subtype of the RHS scrutinee "Ts": Ss <: Ts. It's not required that they are the same type. This covers widening a skolem or inline proxy tp1 scrutinee, without erroneously widening the RHS tp2 scrutinee.
1 parent fcc753b commit 7825d77

File tree

3 files changed

+26
-4
lines changed

3 files changed

+26
-4
lines changed

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,10 +1007,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
10071007
case tp1: MatchType =>
10081008
def compareMatch = tp2 match {
10091009
case tp2: MatchType =>
1010-
def widen(tp: Type) = tp match
1011-
case tp: TermRef if tp.symbol.is(InlineProxy) => tp.info
1012-
case tp => tp.widenSkolem
1013-
isSameType(widen(tp1.scrutinee), widen(tp2.scrutinee)) &&
1010+
isSubType(tp1.scrutinee, tp2.scrutinee) &&
10141011
tp1.cases.corresponds(tp2.cases)(isSubType)
10151012
case _ => false
10161013
}

tests/neg/mt-scrutinee-widen2.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// A test case showing how we shouldn't widen
2+
// both IsX scrutinees and make "def test" typecheck
3+
import scala.util.Random
4+
val x = 42
5+
6+
type IsX[T] =
7+
T match
8+
case x.type => true
9+
case _ => false
10+
11+
def bothXOrNot(a: Int, b: Int)(using IsX[a.type] =:= IsX[b.type]) = ???
12+
13+
def test = bothXOrNot(Random.nextInt(), Random.nextInt()) // error

tests/pos/mt-scrutinee-widen3.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Like widen2, but using a.type only, meaning it should typecheck
2+
import scala.util.Random
3+
val x = 42
4+
5+
type IsX[T] =
6+
T match
7+
case x.type => true
8+
case _ => false
9+
10+
def bothXOrNot(a: Int, b: Int)(using IsX[a.type] =:= IsX[a.type]) = ???
11+
12+
def test = bothXOrNot(Random.nextInt(), Random.nextInt())

0 commit comments

Comments
 (0)