diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 2baae092a1f3..627adced33da 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -708,6 +708,8 @@ object SpaceEngine { else NoType }.filter(_.exists) parts + case tref: TypeRef if tref.symbol.isOpaqueAlias && !tref.info.hiBound.isNothingType => + rec(tref.info.hiBound, mixins) case _ => ListOfNoType end rec @@ -853,7 +855,11 @@ object SpaceEngine { }) || tpw.isRef(defn.BooleanClass) || classSym.isAllOf(JavaEnum) || - classSym.is(Case) + classSym.is(Case) || + (tpw.isInstanceOf[TypeRef] && { + val tref = tpw.asInstanceOf[TypeRef] + tref.symbol.isOpaqueAlias && !tref.info.hiBound.isNothingType + }) !sel.tpe.hasAnnotation(defn.UncheckedAnnot) && !sel.tpe.hasAnnotation(defn.RuntimeCheckedAnnot) diff --git a/tests/pos/i23620.scala b/tests/pos/i23620.scala new file mode 100644 index 000000000000..aa81f09ee182 --- /dev/null +++ b/tests/pos/i23620.scala @@ -0,0 +1,18 @@ +trait Foo +trait Bar + +type FooOrBar = FooOrBar.Type +object FooOrBar: + opaque type Type <: (Foo | Bar) = Foo | Bar + + def bar: FooOrBar = new Bar {} + +trait Buz + +@main def main = + val p: FooOrBar | Buz = FooOrBar.bar + + p match + case _: Foo => println("foo") + case _: Buz => println("buz") + case _: Bar => println("bar") diff --git a/tests/warn/i23620b.check b/tests/warn/i23620b.check new file mode 100644 index 000000000000..5a3aa7abb344 --- /dev/null +++ b/tests/warn/i23620b.check @@ -0,0 +1,16 @@ +-- [E029] Pattern Match Exhaustivity Warning: tests/warn/i23620b.scala:20:2 -------------------------------------------- +20 | p match // warn + | ^ + | match may not be exhaustive. + | + | It would fail on pattern case: _: Bar + | + | longer explanation available when compiling with `-explain` +-- [E029] Pattern Match Exhaustivity Warning: tests/warn/i23620b.scala:23:2 -------------------------------------------- +23 | p2 match { //warn + | ^^ + | match may not be exhaustive. + | + | It would fail on pattern case: _: Bar + | + | longer explanation available when compiling with `-explain` diff --git a/tests/warn/i23620b.scala b/tests/warn/i23620b.scala new file mode 100644 index 000000000000..beaf142276db --- /dev/null +++ b/tests/warn/i23620b.scala @@ -0,0 +1,25 @@ +trait Foo +trait Bar + +type FooOrBar = FooOrBar.Type +object FooOrBar: + opaque type Type <: (Foo | Bar) = Foo | Bar + + def bar: FooOrBar = new Bar {} + +type OnlyFoo = OnlyFoo.Type +object OnlyFoo: + opaque type Type <: (Foo | Bar) = Foo + + def foo: OnlyFoo = new Foo {} + +@main def main = + val p: FooOrBar= FooOrBar.bar + val p2: OnlyFoo = OnlyFoo.foo + + p match // warn + case _: Foo => println("foo") + + p2 match { //warn + case _: Foo => println("foo") + }