2

For the following case class:

scala> case class Foo[T](name: String) {}
defined class Foo

scala> val foo = Foo[Int]("foo")
foo: Foo[Int] = Foo(foo)

Why will Scala let me, as I think it's doing, match on Foo[Int]? Isn't the Int erased?

scala> foo match { 
     |   case _: Foo[Int] => "foo"
     |   case _        => "bar"
     | }
res2: String = foo

But it shows a compile-time error when including another pattern match case?

scala> foo match { 
     |  case _: Foo[String] => "string"
     |  case _: Foo[Int]    => "int"
     |  case _              => "other"
     | }
<console>:12: warning: non-variable type argument String in type pattern Foo[String] is unchecked since it is eliminated by erasure
               case _: Foo[String] => "string"
                       ^
    <console>:12: error: pattern type is incompatible with expected type;
     found   : Foo[String]

 required: Foo[Int]
               case _: Foo[String] => "string"
                       ^
Kevin Meredith
  • 38,251
  • 58
  • 190
  • 340
  • Why do you think it's erased? – Sotirios Delimanolis Jan 13 '15 at 02:01
  • I *think* that `Foo` falls into the same bucket as `List` per this [question](http://stackoverflow.com/questions/1094173/how-do-i-get-around-type-erasure-on-scala-or-why-cant-i-get-the-type-paramete). Again, I *think*, but am not entirely sure. – Kevin Meredith Jan 13 '15 at 02:04

2 Answers2

2
  class SuperFoo;
  case class Foo[T](name: String) extends SuperFoo {}
  val foo: SuperFoo = Foo[Int]("foo")
  foo match {
    case _: Foo[String] => "foo"
    case _        => "bar"
  }  //> res0: String = foo + warning

In your case compiler knows exact type of foo.

Victor Moroz
  • 8,871
  • 17
  • 22
0

It is erased. In your case compiler can statically check that foo is Foo[Int] and match expression here has sense only with Foo[Int], Foo[_] or Any (AnyRef, scala.Product, scala.Serializable).

But if you hide foo real class using, for example, base class Any:

val foo: Any = Foo[Int]("foo")
val res = foo match {
  case _: Foo[String] => "string"
  case _              => "other"
}
println(res) // string

You will get warning:

non-variable type argument String in type pattern Foo[String] is unchecked since it is eliminated by erasure

and program will print "string".

user5102379
  • 1,402
  • 8
  • 9