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 {
570
570
lazy val ClassClass : ClassSymbol = ctx.requiredClass(" java.lang.Class" )
571
571
lazy val BoxedNumberClass : ClassSymbol = ctx.requiredClass(" java.lang.Number" )
572
572
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
573
577
lazy val ArithmeticExceptionClass : ClassSymbol = ctx.requiredClass(" java.lang.ArithmeticException" )
574
578
lazy val ArithmeticExceptionClass_stringConstructor : TermSymbol = ArithmeticExceptionClass .info.member(nme.CONSTRUCTOR ).suchThat(_.info.firstParamTypes match {
575
579
case List (pt) => (pt isRef StringClass )
Original file line number Diff line number Diff line change @@ -244,6 +244,13 @@ object TypeTestsCasts {
244
244
else if (isDerivedValueClass(testCls)) {
245
245
expr // adaptToType in Erasure will do the necessary type adaptation
246
246
}
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
+ }
247
254
else
248
255
derivedTree(expr, defn.Any_asInstanceOf , testType)
249
256
}
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