Skip to content

ClassCastException when matching on ValueOf #12366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
OlivierBlanvillain opened this issue May 7, 2021 · 1 comment
Open

ClassCastException when matching on ValueOf #12366

OlivierBlanvillain opened this issue May 7, 2021 · 1 comment
Assignees

Comments

@OlivierBlanvillain
Copy link
Contributor

OlivierBlanvillain commented May 7, 2021

Here is a variation of tests/run/i12194.scala that leads to a ClassCastException:

import scala.compiletime.package$package.summonAll

@main def Test(): Unit = {
  val list: List[ValueOf["foo"] | ValueOf["bar"]] =
    summonAll[Tuple.Map[("foo", "bar"), ValueOf]].toList

  println(list.map {
    case str: ValueOf[_]  str.value
    // java.lang.ClassCastException: scala.ValueOf cannot be cast to java.lang.String              
  })
}
@abgruszecki
Copy link
Contributor

This doesn't look like a GADT problem. We infer no GADT constraints here. It seems like a problem with value classes perhaps?
After typer, the tree looks like this:

    @main() def Test(): Unit = 
      {
        val list: List[ValueOf["foo".type] | ValueOf["bar".type]] = compiletime.summonAll[Tuple.Map[Tuple2["foo".type, "bar".type], ValueOf]].toList
        println(
          list.map[String](
            {
              def $anonfun(x$1: ValueOf[("foo" : String)] | ValueOf[("bar" : String)]): String = 
                x$1 match 
                  {
                    case str @ _:ValueOf[_ @  >: Nothing <: Any] => 
                      str.value:("foo" : String) | ("bar" : String)
                  }
              closure($anonfun)
            }
          )
        )
      }

After genBCode, we have this fragment:

    private final def Test$$anonfun$1(x$1: Object): String = 
      matchResult1[String]: 
        {
          case val x1: Object = x$1
          if x1.isInstanceOf[ValueOf] then 
            {
              case val str: Object = new ValueOf(x1.asInstanceOf[Object])
              {
                return[matchResult1] str.asInstanceOf[ValueOf].value().asInstanceOf[String]:String
              }
            }
           else ()
          throw new MatchError(x1)
        }
  }

Note the call to new ValueOf when creating val str, it looks like that is the source of the problem. A wrong-looking tree appears sooner, but it's too big to paste here.

I can keep debugging this in my spare time, but perhaps it'd be trivial to fix for someone with an understanding of how value types are desugared?

Additional data point:

scala> import scala.compiletime.package$package.summonAll                                                                                                                                                      
     | 
     | @main def Test(): Unit = {
     |   val list: List[ValueOf["foo"] | ValueOf["bar"]] =
     |     summonAll[Tuple.Map[("foo", "bar"), ValueOf]].toList
     | 
     |   println(list.map {
     |     case str: ValueOf[_] =>
     |       println(str)
     |       val str1 : ValueOf[_ <: String] = str
     |       println(str1)
     |       str1.value : String
     |     // java.lang.ClassCastException: scala.ValueOf cannot be cast to java.lang.String              
     |   })
     | }
def Test(): Unit

scala> Test()                                                                                                                                                                                                  
scala.ValueOf@18cc6
java.lang.ClassCastException: scala.ValueOf cannot be cast to java.lang.String
  at rs$line$9$.Test$$anonfun$1(rs$line$9:10)
  at scala.collection.immutable.List.map(List.scala:246)
  at rs$line$9$.Test(rs$line$9:14)
  ... 28 elided

Note how only one println happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants