Open
Description
Compiler version
3.6.0-RC1-bin-SNAPSHOT-nonbootstrapped-git-6ceaab5
Minimized code
def test =
val x: String = "x"
val y: String = "y"
val a: x.type = x
a match
case `x` => println("x")
case _: String => println("_") // no warning
val b: x.type | y.type = x
b match
case `x` => println("x")
case `y` => println("y")
case _: String => println("_") // warning: unreachable case
Output
-- [E030] Match case Unreachable Warning: Stest.scala:1231:9 -------------------
1231 | case _: String => println("_") // warning: unreachable case
| ^^^^^^^^^
| Unreachable case
1 warning found
Expectation
Ideally, both wildcard cases should have the same unreachable warning.
Or at least, neither of the cases get any warning.
Issue
The current space engine is able to track some singleton types (for example, constant type and simple term refs).
However, only top level TermRef
s are widened in toUnderlying
, which causes inconsistency dependent on the complexity of the type.
I think one simple fix is to widen singleton types nested in and/or types as well, because supporting full singleton type analysis may require significant modification:
def toUnderlying(tp: Type)(using Context): Type = trace(i"toUnderlying($tp ${tp.className})")(tp match {
case _: ConstantType => tp
case tp: TermRef if tp.symbol.is(Module) => tp
case tp: TermRef if tp.symbol.isAllOf(EnumCase) => tp
case tp: SingletonType => toUnderlying(tp.underlying)
case tp: ExprType => toUnderlying(tp.resultType)
case AnnotatedType(tp, annot) => AnnotatedType(toUnderlying(tp), annot)
case tp: AndOrType => tp.derivedAndOrType(toUnderlying(tp.tp1), toUnderlying(tp.tp2))
case _ => tp
})