Skip to content

Commit

Permalink
Merge pull request #12905 from lampepfl/i4004
Browse files Browse the repository at this point in the history
Restricts `isInstanceOf[Null]` checks
  • Loading branch information
smarter authored Jun 23, 2021
2 parents 51f3487 + ca4aa16 commit 2ccf681
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 4 deletions.
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,8 @@ class Definitions {

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

@tu lazy val untestableClasses: Set[Symbol] = Set(NothingClass, NullClass, SingletonClass)

@tu lazy val AbstractFunctionType: Array[TypeRef] = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0)
val AbstractFunctionClassPerRun: PerRun[Array[Symbol]] = new PerRun(AbstractFunctionType.map(_.symbol.asClass))
def AbstractFunctionClass(n: Int)(using Context): Symbol = AbstractFunctionClassPerRun()(using ctx)(n)
Expand Down
10 changes: 8 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,14 @@ object TypeTestsCasts {
case AppliedType(tref: TypeRef, _) if tref.symbol == defn.PairClass =>
ref(defn.RuntimeTuples_isInstanceOfNonEmptyTuple).appliedTo(expr)
case _ =>
val erasedTestType = erasure(testType)
transformIsInstanceOf(expr, erasedTestType, erasedTestType, flagUnrelated)
val testWidened = testType.widen
defn.untestableClasses.find(testWidened.isRef(_)) match
case Some(untestable) =>
report.error(i"$untestable cannot be used in runtime type tests", tree.srcPos)
constant(expr, Literal(Constant(false)))
case _ =>
val erasedTestType = erasure(testType)
transformIsInstanceOf(expr, erasedTestType, erasedTestType, flagUnrelated)
}

if (sym.isTypeTest) {
Expand Down
2 changes: 0 additions & 2 deletions tests/explicit-nulls/pos/matchable.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
def foo1[T <: Matchable](t: T) = t match { case t: Null => () }

def foo2[T <: Matchable](t: T) = t match { case null => () }
16 changes: 16 additions & 0 deletions tests/neg/i4004.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@main def Test =
"a".isInstanceOf[Null] // error
null.isInstanceOf[Null] // error
"a".isInstanceOf[Nothing] // error
"a".isInstanceOf[Singleton] // error

"a" match
case _: Null => () // error
case _: Nothing => () // error
case _: Singleton => () // error
case _ => ()

null match
case _: Null => () // error
case _ => ()

0 comments on commit 2ccf681

Please sign in to comment.