Skip to content

Commit 2ccf681

Browse files
authored
Merge pull request #12905 from lampepfl/i4004
Restricts `isInstanceOf[Null]` checks
2 parents 51f3487 + ca4aa16 commit 2ccf681

File tree

4 files changed

+26
-4
lines changed

4 files changed

+26
-4
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,8 @@ class Definitions {
11961196

11971197
@tu lazy val topClasses: Set[Symbol] = Set(AnyClass, MatchableClass, ObjectClass, AnyValClass)
11981198

1199+
@tu lazy val untestableClasses: Set[Symbol] = Set(NothingClass, NullClass, SingletonClass)
1200+
11991201
@tu lazy val AbstractFunctionType: Array[TypeRef] = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0)
12001202
val AbstractFunctionClassPerRun: PerRun[Array[Symbol]] = new PerRun(AbstractFunctionType.map(_.symbol.asClass))
12011203
def AbstractFunctionClass(n: Int)(using Context): Symbol = AbstractFunctionClassPerRun()(using ctx)(n)

compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala

+8-2
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,14 @@ object TypeTestsCasts {
339339
case AppliedType(tref: TypeRef, _) if tref.symbol == defn.PairClass =>
340340
ref(defn.RuntimeTuples_isInstanceOfNonEmptyTuple).appliedTo(expr)
341341
case _ =>
342-
val erasedTestType = erasure(testType)
343-
transformIsInstanceOf(expr, erasedTestType, erasedTestType, flagUnrelated)
342+
val testWidened = testType.widen
343+
defn.untestableClasses.find(testWidened.isRef(_)) match
344+
case Some(untestable) =>
345+
report.error(i"$untestable cannot be used in runtime type tests", tree.srcPos)
346+
constant(expr, Literal(Constant(false)))
347+
case _ =>
348+
val erasedTestType = erasure(testType)
349+
transformIsInstanceOf(expr, erasedTestType, erasedTestType, flagUnrelated)
344350
}
345351

346352
if (sym.isTypeTest) {
-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
def foo1[T <: Matchable](t: T) = t match { case t: Null => () }
2-
31
def foo2[T <: Matchable](t: T) = t match { case null => () }

tests/neg/i4004.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
@main def Test =
2+
"a".isInstanceOf[Null] // error
3+
null.isInstanceOf[Null] // error
4+
"a".isInstanceOf[Nothing] // error
5+
"a".isInstanceOf[Singleton] // error
6+
7+
"a" match
8+
case _: Null => () // error
9+
case _: Nothing => () // error
10+
case _: Singleton => () // error
11+
case _ => ()
12+
13+
null match
14+
case _: Null => () // error
15+
case _ => ()
16+

0 commit comments

Comments
 (0)