Skip to content

Inconsistent space analysis when singleton types are nested in And/Or types #21723

Open
@noti0na1

Description

@noti0na1

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 TermRefs 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
})

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions