File tree Expand file tree Collapse file tree 6 files changed +81
-0
lines changed
compiler/src/dotty/tools/dotc Expand file tree Collapse file tree 6 files changed +81
-0
lines changed Original file line number Diff line number Diff line change @@ -570,6 +570,10 @@ class Definitions {
570570 lazy val ClassClass : ClassSymbol = ctx.requiredClass(" java.lang.Class" )
571571 lazy val BoxedNumberClass : ClassSymbol = ctx.requiredClass(" java.lang.Number" )
572572 lazy val ClassCastExceptionClass : ClassSymbol = ctx.requiredClass(" java.lang.ClassCastException" )
573+ lazy val ClassCastExceptionClass_stringConstructor : TermSymbol = ClassCastExceptionClass .info.member(nme.CONSTRUCTOR ).suchThat(_.info.firstParamTypes match {
574+ case List (pt) => (pt isRef StringClass )
575+ case _ => false
576+ }).symbol.asTerm
573577 lazy val ArithmeticExceptionClass : ClassSymbol = ctx.requiredClass(" java.lang.ArithmeticException" )
574578 lazy val ArithmeticExceptionClass_stringConstructor : TermSymbol = ArithmeticExceptionClass .info.member(nme.CONSTRUCTOR ).suchThat(_.info.firstParamTypes match {
575579 case List (pt) => (pt isRef StringClass )
Original file line number Diff line number Diff line change @@ -244,6 +244,13 @@ object TypeTestsCasts {
244244 else if (isDerivedValueClass(testCls)) {
245245 expr // adaptToType in Erasure will do the necessary type adaptation
246246 }
247+ else if (testCls eq defn.NothingClass ) {
248+ // In the JVM `x.asInstanceOf[Nothing]` would throw a class cast exception except when `x eq null`.
249+ // To avoid this loophole we execute `x` and then regardless of the result throw a `ClassCastException`
250+ val throwCCE = Throw (New (defn.ClassCastExceptionClass .typeRef, defn.ClassCastExceptionClass_stringConstructor ,
251+ Literal (Constant (" Cannot cast to scala.Nothing" )) :: Nil ))
252+ Block (expr :: Nil , throwCCE).withSpan(expr.span)
253+ }
247254 else
248255 derivedTree(expr, defn.Any_asInstanceOf , testType)
249256 }
Original file line number Diff line number Diff line change 1+ object X {
2+ val x : Int = null .asInstanceOf [Nothing ]
3+ }
Original file line number Diff line number Diff line change 1+ Test$.f1(i3340.scala:13)
2+ Test$.f2(i3340.scala:17)
3+ Test$.f3(i3340.scala:21)
4+ Test$.f4(i3340.scala:28)
5+ Test$.f5(i3340.scala:35)
6+ foo
7+ Test$.f6(i3340.scala:42)
Original file line number Diff line number Diff line change 1+ object Test {
2+ def main (args : Array [String ]): Unit = {
3+ printlnStackLine(f1)
4+ printlnStackLine(f2)
5+ printlnStackLine(f3)
6+ printlnStackLine(f4)
7+ printlnStackLine(f5)
8+ printlnStackLine(f6)
9+ }
10+
11+ def f1 : Unit = {
12+ val a : Nothing =
13+ null .asInstanceOf [Nothing ] // throws here
14+ }
15+
16+ def f2 : Unit = {
17+ null .asInstanceOf [Nothing ] // throws here
18+ }
19+
20+ def f3 : Unit = {
21+ null .asInstanceOf [Nothing ] // throws here
22+ ()
23+ }
24+
25+
26+ def f4 : Unit = {
27+ val n : Any = null
28+ n.asInstanceOf [Nothing ] // throws here
29+ ()
30+ }
31+
32+ def f5 : Unit = {
33+ val n : Any = null
34+ val a : Nothing =
35+ n.asInstanceOf [Nothing ] // throws here
36+ ()
37+ }
38+
39+ def f6 : Unit = {
40+ val n : Any = null
41+ val a : Nothing =
42+ { println(" foo" ); n }.asInstanceOf [Nothing ] // throws here
43+ ()
44+ }
45+
46+ def printlnStackLine (t : => Any ): Unit = {
47+ try t
48+ catch {
49+ case e : ClassCastException =>
50+ println(e.getStackTrace.head)
51+ }
52+ }
53+ }
Original file line number Diff line number Diff line change 1+ object Test {
2+ val a =
3+ try null .asInstanceOf [Nothing ]
4+ catch { case e : ClassCastException if e.getMessage == " Cannot cast to scala.Nothing" => /* As expected */ }
5+ def main (args : Array [String ]): Unit = {
6+ }
7+ }
You can’t perform that action at this time.
0 commit comments