scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
231 stars 21 forks source link

`fruitless type test` results in incorrect match #12143

Open som-snytt opened 3 years ago

som-snytt commented 3 years ago

reproduction steps

scala 2.13.3> object X ; object Y
object X
object Y

scala 2.13.3> (X: Any) match { case _: Y.type => 1 case _ => 2 }
val res0: Int = 2

scala 2.13.3> X match { case _: Y.type => 1 case _ => 2 }
                                 ^
              warning: fruitless type test: a value of type X.type cannot also be a Y.type (the underlying of Y.type)
error: Error while emitting <console>
assertion failed:
  Trying to access the this of another class: tree.symbol = class $read, class symbol = class iw compilation unit: <console>
     while compiling: <console>
        during phase: jvm
     library version: version 2.13.3
    compiler version: version 2.13.3
  reconstructed args: -deprecation -feature -Wconf:cat=feature:w -Wconf:cat=deprecation:w -Wconf:cat=deprecation:ws -Wconf:cat=feature:ws -Wconf:cat=optimizer:ws

  last tree to typer: Literal(Constant(type))
       tree position: <unknown>
            tree tpe: Class(classOf[])
              symbol: null
           call site: constructor $iw in package $line5

== Source file context for tree position ==

scala 2.13.3>

or

object X
object Y
object Test extends App {
  println {
    X match { case _: Y.type => 1 case _ => 2 }
  }
}
➜  snips scala xx.scala
xx.scala:6: warning: fruitless type test: a value of type X.type cannot also be a Y.type (the underlying of Y.type)
    X match { case _: Y.type => 1 case _ => 2 }
                       ^
1

problem

I expect the other answer (because X ne Y) and not a crash.

dwijnand commented 3 years ago
$ scala -Vprint:_ $(f 'object X; object Y; object Test extends App { println(X match { case _: Y.type => 1 case _ => 2 }) }')
[[syntax trees at end of                    patmat]] // scala-test.zaWc1LcN.scala
...
    scala.Predef.println({
      case <synthetic> val x1: X.type = X;
      case5(){
        if (x1.isInstanceOf[X.type with Y.type])
          matchEnd4(1)
        else
          case6()
      };
      case6(){
        matchEnd4(2)
      };
      matchEnd4(x: Any){
        x
      }
    })
[[syntax trees at end of                   erasure]] // scala-test.zaWc1LcN.scala
...
    scala.Predef.println({
      case <synthetic> val x1: X.type = X;
      case5(){
        if (X.eq(x1))
          matchEnd4(scala.Int.box(1))
        else
          case6()
      };
      case6(){
        matchEnd4(scala.Int.box(2))
      };
      matchEnd4(x: Object){
        x
      }
    })

o_O

som-snytt commented 1 year ago

No longer crashes REPL (by 2.13.6) but still a bad match.

Dotty warns:

scala> X match { case _: Y.type => 1 case _ => 2 }
1 warning found
-- [E030] Match case Unreachable Warning: ------------------------------------------------------------------------------
1 |X match { case _: Y.type => 1 case _ => 2 }
  |               ^^^^^^^^^
  |               Unreachable case
val res0: Int = 2