question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unexpected "java.lang.ClassCastException: Cannot cast to scala.Nothing"

See original GitHub issue

Compiler version

3.2.1 (as well as 3.1.0, 3.0.0, etc)

Minimized code

Scala3MatchCrash.scala

sealed trait Foo[A] {

  def last: Option[A] = this match {
    case _: FooEmpty.type => None
    case FooNode(_: FooEmpty.type, bar) => Some(bar)
    case FooNode(foo, _) => foo.last
  }
}

final case class FooNode[A](foo: Foo[A], bar: A) extends Foo[A]

case object FooEmpty extends Foo[Nothing]

object Scala3MatchCrash extends App {

  val foo0 = FooEmpty.asInstanceOf[Foo[Int]]
  val foo1 = FooNode(foo0, 1)

  println(foo1.last)
}

Output

Exception in thread "main" java.lang.ExceptionInInitializerError
	at Scala3MatchCrash.main(Scala3MatchCrash.scala)
Caused by: java.lang.ClassCastException: Cannot cast to scala.Nothing
	at Foo.last(Scala3MatchCrash.scala:5)
	at Foo.last$(Scala3MatchCrash.scala:1)
	at FooNode.last(Scala3MatchCrash.scala:10)
	at Scala3MatchCrash$.<clinit>(Scala3MatchCrash.scala:19)
	... 1 more

Expectation

Some(1)

Additional Info

This code snippet compiles and works as expected on previous Scala versions: 2.13.10, 2.13.0, 2.12.17, etc.

Issue Analytics

  • State:closed
  • Created 9 months ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
Linyxuscommented, Dec 13, 2022

CCE in the second case happens because of the cast we insert for it, the typed tree looks like:

case _:FooEmpty.type =>
  None
case FooNode.unapply[A](_:FooEmpty.type, bar @ _):FooNode[A] =>
  Some.apply[Nothing](bar.$asInstanceOf[(bar : A) & Nothing])

In the second case, we have to use the GADT constraint A =:= Nothing to make the clause well-typed, so we insert the cast bar.$asInstanceOf[bar.type & Nothing]. The cast should be safe as long as the constraint A =:= Nothing is sound, which is not the case here.

For the first case, no casts are inserted because no GADT constraint is used to type None as Option[A].

0reactions
satorgcommented, Dec 12, 2022

I see, thank you all for looking into it and the detailed explanation.

I’m still wondering though how come the first case does not cause CCE, what is the difference between the first and the second one from the prospective of GADT?

    case _: FooEmpty.type => None // does not cause any CCE
    case FooNode(_: FooEmpty.type, bar) => Some(bar)

because if I change the println line to this one:

println(foo0.last)

then it simply prints None and no CCE gets raised.

Just FYI: the snippet above is actually an excerpt from Diet which I’m currently trying to massage up a little bit.

Read more comments on GitHub >

github_iconTop Results From Across the Web

avoiding cast to Nothing in generic method - scala
No. The static type is U . If this is inferred as Nothing , the compiler won't allow a return value of type...
Read more >
Cannot be cast to class scala.runtime.BoxedUnit - Community
Hi! I encountered an unexpected behavior at runtime. Consider the following code: def execute[R](): R = (new Object).asInstanceOf[R] val r1: Unit ...
Read more >
java.lang.String cannot be cast to scala.runtime.Nothing ...
When doing vertext.toCC[Invitations].get or v.get[String]("code").get i kept getting the same error, [ClassCastException: java.lang.
Read more >
How to fix java.lang.classcastexception cannot be cast to in Java
As name suggests ClassCastException in Java comes when we try to type cast an object and object is not of the type we...
Read more >
TheNumber cannot be cast to scala.runtime.Nothing
Exception in thread "main" java.lang.ClassCastException: TheNumber cannot be cast to scala.runtime.Nothing$ at Moo$$anonfun$1.apply(Moo.scala:17)
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found