From a38f11d4fc4e8a774c2b5b3299e3bffe3f222530 Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Wed, 26 Jul 2023 17:19:50 -0400 Subject: [PATCH] fix #18282: consider Predef.eq/ne in nullability flow typing --- compiler/src/dotty/tools/dotc/typer/Nullables.scala | 11 +++++++++++ tests/explicit-nulls/pos/flow-predef-eq.scala | 7 +++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/explicit-nulls/pos/flow-predef-eq.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Nullables.scala b/compiler/src/dotty/tools/dotc/typer/Nullables.scala index 9104418d406f..e7ef771a414a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Nullables.scala +++ b/compiler/src/dotty/tools/dotc/typer/Nullables.scala @@ -115,6 +115,10 @@ object Nullables: testSym(tree.symbol, l) case Apply(Select(Literal(Constant(null)), _), r :: Nil) => testSym(tree.symbol, r) + case Apply(Apply(op, l :: Nil), Literal(Constant(null)) :: Nil) => + testPredefSym(op.symbol, l) + case Apply(Apply(op, Literal(Constant(null)) :: Nil), r :: Nil) => + testPredefSym(op.symbol, r) case _ => None @@ -123,6 +127,13 @@ object Nullables: else if sym == defn.Any_!= || sym == defn.Object_ne then Some((operand, false)) else None + private def testPredefSym(opSym: Symbol, operand: Tree)(using Context) = + if opSym.owner == defn.ScalaPredefModuleClass then + if opSym.name == nme.eq then Some((operand, true)) + else if opSym.name == nme.ne then Some((operand, false)) + else None + else None + end CompareNull /** An extractor for null-trackable references */ diff --git a/tests/explicit-nulls/pos/flow-predef-eq.scala b/tests/explicit-nulls/pos/flow-predef-eq.scala new file mode 100644 index 000000000000..25bbf32fef15 --- /dev/null +++ b/tests/explicit-nulls/pos/flow-predef-eq.scala @@ -0,0 +1,7 @@ +def f(s: String|Null): String = { + if(s eq null) "foo" else s +} + +def f2(s: String|Null): String = { + if(s ne null) s else "foo" +}