diff --git a/library/src/scala/runtime/stdLibPatches/Predef.scala b/library/src/scala/runtime/stdLibPatches/Predef.scala index 13dfc77ac60b..080a3957f79f 100644 --- a/library/src/scala/runtime/stdLibPatches/Predef.scala +++ b/library/src/scala/runtime/stdLibPatches/Predef.scala @@ -1,5 +1,7 @@ package scala.runtime.stdLibPatches +import scala.annotation.experimental + object Predef: import compiletime.summonFrom @@ -47,4 +49,19 @@ object Predef: */ extension [T](x: T | Null) inline def nn: x.type & T = scala.runtime.Scala3RunTime.nn(x) + + extension (inline x: AnyRef | Null) + /** Enables an expression of type `T|Null`, where `T` is a subtype of `AnyRef`, to be checked for `null` + * using `eq` rather than only `==`. This is needed because `Null` no longer has + * `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */ + @experimental + inline def eq(inline y: AnyRef | Null): Boolean = + x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] + /** Enables an expression of type `T|Null`, where `T` is a subtype of `AnyRef`, to be checked for `null` + * using `ne` rather than only `!=`. This is needed because `Null` no longer has + * `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */ + @experimental + inline def ne(inline y: AnyRef | Null): Boolean = + !(x eq y) + end Predef diff --git a/tests/coverage/pos/Inlined.scoverage.check b/tests/coverage/pos/Inlined.scoverage.check index f3cb3b5d9026..7d0e717a7aac 100644 --- a/tests/coverage/pos/Inlined.scoverage.check +++ b/tests/coverage/pos/Inlined.scoverage.check @@ -42,9 +42,9 @@ Inlined$package$ Object covtest.Inlined$package$ testInlined -340 -367 -9 +378 +405 +11 Scala3RunTime Select false @@ -59,9 +59,9 @@ Inlined$package$ Object covtest.Inlined$package$ testInlined -340 -382 -9 +378 +420 +11 assertFailed Apply false @@ -76,9 +76,9 @@ Inlined$package$ Object covtest.Inlined$package$ testInlined -340 -382 -9 +378 +420 +11 Block true @@ -127,9 +127,9 @@ Inlined$package$ Object covtest.Inlined$package$ testInlined -340 -367 -9 +378 +405 +11 Scala3RunTime Select false @@ -144,9 +144,9 @@ Inlined$package$ Object covtest.Inlined$package$ testInlined -340 -382 -9 +378 +420 +11 assertFailed Apply false @@ -161,9 +161,9 @@ Inlined$package$ Object covtest.Inlined$package$ testInlined -340 -382 -9 +378 +420 +11 Block true @@ -212,9 +212,9 @@ Inlined$package$ Object covtest.Inlined$package$ testInlined -340 -367 -9 +378 +405 +11 Scala3RunTime Select false @@ -229,9 +229,9 @@ Inlined$package$ Object covtest.Inlined$package$ testInlined -340 -382 -9 +378 +420 +11 assertFailed Apply false @@ -246,9 +246,9 @@ Inlined$package$ Object covtest.Inlined$package$ testInlined -340 -382 -9 +378 +420 +11 Block true diff --git a/tests/explicit-nulls/pos/eq-ne.scala b/tests/explicit-nulls/pos/eq-ne.scala new file mode 100644 index 000000000000..ac2c9742ea64 --- /dev/null +++ b/tests/explicit-nulls/pos/eq-ne.scala @@ -0,0 +1,16 @@ +val s1: String = ??? +val s2: String | Null = ??? + +def f = { + s1 eq s2 + s2 eq s1 + + s1 ne s2 + s2 ne s1 + + s1 eq null + s2 eq null + + null eq s1 + null eq s2 +} diff --git a/tests/explicit-nulls/unsafe-common/unsafe-eq.scala b/tests/explicit-nulls/unsafe-common/unsafe-eq.scala deleted file mode 100644 index 48fcd07bef80..000000000000 --- a/tests/explicit-nulls/unsafe-common/unsafe-eq.scala +++ /dev/null @@ -1,16 +0,0 @@ -val s1: String = ??? -val s2: String | Null = ??? - -def f = { - s1 eq s2 // error - s2 eq s1 // error - - s1 ne s2 // error - s2 ne s1 // error - - s1 eq null // error - s2 eq null // error - - null eq s1 // error - null eq s2 // error -} \ No newline at end of file diff --git a/tests/run-custom-args/tasty-inspector/stdlibExperimentalDefinitions.scala b/tests/run-custom-args/tasty-inspector/stdlibExperimentalDefinitions.scala index 63b95c280b61..0d86b5c05caa 100644 --- a/tests/run-custom-args/tasty-inspector/stdlibExperimentalDefinitions.scala +++ b/tests/run-custom-args/tasty-inspector/stdlibExperimentalDefinitions.scala @@ -76,6 +76,11 @@ val experimentalDefinitionInLibrary = Set( // Need experimental annotation macros to check that design works. "scala.quoted.Quotes.reflectModule.ClassDefModule.apply", "scala.quoted.Quotes.reflectModule.SymbolModule.newClass", + + //// New extension methods: Explicit Nulls + // Should be stabilized in 3.2.0. + "scala.Predef$.eq", + "scala.Predef$.ne", )