Can we fix `.asInstanceOf`'s type inference to do the right thing?

The current behavior of asInstanceOf without an explicit type parameter is (a) useless and (b) non-standard.

@ val x: String = ("hello": CharSequence).asInstanceOf 
java.lang.ClassCastException: class java.lang.String cannot be cast to class scala.runtime.Nothing$ (java.lang.String is in module java.base of loader 'bootstrap'; scala.runtime.Nothing$ is in unnamed module of loader 'app')
  ammonite.$sess.cmd2$.<clinit>(cmd2.sc:1)

@ def cast[T](x: Any): T = x.asInstanceOf[T] 
defined function cast

@ val x: String = cast("hello": CharSequence) 
x: String = "hello"

Apart from behaving totally different from any other generic method (e.g. the def cast shown above), this makes it considerably less useful than it could be. Because if you want to cast something you need to spell out the explicit type every time, which is often tedious or even impossible e.g. if the expected type is _$1 such as in the error below:

[error]  found   : variable.value.type (with underlying type _$1)
[error]  required: _$1
[error]       for ((variable, i) <- flattened.params.iterator.zipWithIndex) variable.mappedType.put(statement, i + 1, variable.value)
[error]      

A trivial cast function as defined above does the right thing due to type inference, even for these “impossible” types which cannot be spelled out in code.

Can we fix asInstanceOf to infer types the right way? That would both make it a lot more well-behaved, and also simplify a lot of scenarios where spelling out the type you want to cast to is either verbose or totally impossible. There are basically no scenarios where asInstanceOf blowing up 100% of the time with a ClassCastException is the desired behavior, so we wouldn’t be breaking anything that isn’t already broken

1 Like

I can’t reproduce this. In Scala 3,

val x: String = ("hello": CharSequence).asInstanceOf 

compiles and does the right thing. I don’t want to imply there are not other problems, but this one looks OK.

Huh you’re right. I was originally hit by this on Scala 2.13, but I guess it’s on the long list of things fixed in Scala 3!

This one breaks:

Welcome to Scala 3.3.1 (21, Java OpenJDK 64-Bit Server VM).

scala> inline def cast[T](x: Any): T = x.asInstanceOf
def cast[T](x: Any): T

scala> val x: String = cast("")
java.lang.ClassCastException: Cannot cast to scala.Nothing
  ... 33 elided

This might be difficult to avoid in general, the type argument of asInstanceOf does not behave like any other type argument, and special-cases for asInstanceOf aren’t enough when inlining is involved.

Hard to sympathize on 2.13.

➜  ~ scala -Xlint
Welcome to Scala 2.13.12 (OpenJDK 64-Bit Server VM, Java 21).
Type in expressions for evaluation. Or try :help.

scala> val x: String = ("hello": CharSequence).asInstanceOf
                                               ^
       warning: missing type argument to method asInstanceOf
java.lang.ClassCastException: class java.lang.String cannot be cast to class scala.runtime.Nothing$ (java.lang.String is in module java.base of loader 'bootstrap'; scala.runtime.Nothing$ is in unnamed module of loader 'bootstrap')
  ... 30 elided

Edit: I misread “hit by this” as “bit by this”.