From 6ee3f0269b2fe2120d396a4a19e4f31978ddc93a Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 7 Mar 2022 15:50:04 +0100 Subject: [PATCH 01/12] add eq/ne extension for AnyRef|Null to Scala3RunTime --- library/src/scala/runtime/Scala3RunTime.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/src/scala/runtime/Scala3RunTime.scala b/library/src/scala/runtime/Scala3RunTime.scala index b1645f5242aa..32f3687e88c6 100644 --- a/library/src/scala/runtime/Scala3RunTime.scala +++ b/library/src/scala/runtime/Scala3RunTime.scala @@ -19,4 +19,10 @@ object Scala3RunTime: if (isNull) throw new NullPointerException("tried to cast away nullability, but value is null") else x.asInstanceOf[x.type & T] + extension (inline x: AnyRef | Null) + inline def eq(inline y: AnyRef | Null): Boolean = + x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] + inline def ne(inline y: AnyRef | Null): Boolean = + !(x eq y) + end Scala3RunTime From 33a4c8aef1e5959b9e9bc5859f31a6c17c6dbaa4 Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 7 Mar 2022 16:45:53 +0100 Subject: [PATCH 02/12] add @since("3.2") --- library/src/scala/runtime/Scala3RunTime.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/src/scala/runtime/Scala3RunTime.scala b/library/src/scala/runtime/Scala3RunTime.scala index 32f3687e88c6..2eed853114cc 100644 --- a/library/src/scala/runtime/Scala3RunTime.scala +++ b/library/src/scala/runtime/Scala3RunTime.scala @@ -1,5 +1,7 @@ package scala.runtime +import scala.annotation.since + object Scala3RunTime: // Called by inline def assert's. Extracted to minimize the bytecode size at call site. @@ -20,8 +22,10 @@ object Scala3RunTime: else x.asInstanceOf[x.type & T] extension (inline x: AnyRef | Null) + @since("3.2") inline def eq(inline y: AnyRef | Null): Boolean = x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] + @since("3.2") inline def ne(inline y: AnyRef | Null): Boolean = !(x eq y) From 4acac5276b6374afdfe4fbdcbbb2da7d990688b9 Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 14 Mar 2022 11:52:28 +0100 Subject: [PATCH 03/12] move extension methods to Predef instead of Scala3RunTime --- library/src/scala/runtime/Scala3RunTime.scala | 10 ---------- library/src/scala/runtime/stdLibPatches/Predef.scala | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/library/src/scala/runtime/Scala3RunTime.scala b/library/src/scala/runtime/Scala3RunTime.scala index 2eed853114cc..b1645f5242aa 100644 --- a/library/src/scala/runtime/Scala3RunTime.scala +++ b/library/src/scala/runtime/Scala3RunTime.scala @@ -1,7 +1,5 @@ package scala.runtime -import scala.annotation.since - object Scala3RunTime: // Called by inline def assert's. Extracted to minimize the bytecode size at call site. @@ -21,12 +19,4 @@ object Scala3RunTime: if (isNull) throw new NullPointerException("tried to cast away nullability, but value is null") else x.asInstanceOf[x.type & T] - extension (inline x: AnyRef | Null) - @since("3.2") - inline def eq(inline y: AnyRef | Null): Boolean = - x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] - @since("3.2") - inline def ne(inline y: AnyRef | Null): Boolean = - !(x eq y) - end Scala3RunTime diff --git a/library/src/scala/runtime/stdLibPatches/Predef.scala b/library/src/scala/runtime/stdLibPatches/Predef.scala index 13dfc77ac60b..f26544dfea50 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.since + object Predef: import compiletime.summonFrom @@ -47,4 +49,13 @@ object Predef: */ extension [T](x: T | Null) inline def nn: x.type & T = scala.runtime.Scala3RunTime.nn(x) + + extension (inline x: AnyRef | Null) + @since("3.2") + inline def eq(inline y: AnyRef | Null): Boolean = + x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] + @since("3.2") + inline def ne(inline y: AnyRef | Null): Boolean = + !(x eq y) + end Predef From adf8b779af392e683ef6bc835635385d38924793 Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 14 Mar 2022 11:57:45 +0100 Subject: [PATCH 04/12] reclassify unsafe-eq test as pos/eq-ne --- tests/explicit-nulls/pos/eq-ne.scala | 16 ++++++++++++++++ .../explicit-nulls/unsafe-common/unsafe-eq.scala | 16 ---------------- 2 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 tests/explicit-nulls/pos/eq-ne.scala delete mode 100644 tests/explicit-nulls/unsafe-common/unsafe-eq.scala 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 From bb3696b4dc678086e6e93efe0b0b8f03e1eec062 Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 7 Mar 2022 15:50:04 +0100 Subject: [PATCH 05/12] add eq/ne extension for AnyRef|Null to Scala3RunTime --- library/src/scala/runtime/Scala3RunTime.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/src/scala/runtime/Scala3RunTime.scala b/library/src/scala/runtime/Scala3RunTime.scala index b1645f5242aa..32f3687e88c6 100644 --- a/library/src/scala/runtime/Scala3RunTime.scala +++ b/library/src/scala/runtime/Scala3RunTime.scala @@ -19,4 +19,10 @@ object Scala3RunTime: if (isNull) throw new NullPointerException("tried to cast away nullability, but value is null") else x.asInstanceOf[x.type & T] + extension (inline x: AnyRef | Null) + inline def eq(inline y: AnyRef | Null): Boolean = + x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] + inline def ne(inline y: AnyRef | Null): Boolean = + !(x eq y) + end Scala3RunTime From e279a7b3509242805af04a08a5de9d7801eb6fab Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 7 Mar 2022 16:45:53 +0100 Subject: [PATCH 06/12] add @since("3.2") --- library/src/scala/runtime/Scala3RunTime.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/src/scala/runtime/Scala3RunTime.scala b/library/src/scala/runtime/Scala3RunTime.scala index 32f3687e88c6..2eed853114cc 100644 --- a/library/src/scala/runtime/Scala3RunTime.scala +++ b/library/src/scala/runtime/Scala3RunTime.scala @@ -1,5 +1,7 @@ package scala.runtime +import scala.annotation.since + object Scala3RunTime: // Called by inline def assert's. Extracted to minimize the bytecode size at call site. @@ -20,8 +22,10 @@ object Scala3RunTime: else x.asInstanceOf[x.type & T] extension (inline x: AnyRef | Null) + @since("3.2") inline def eq(inline y: AnyRef | Null): Boolean = x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] + @since("3.2") inline def ne(inline y: AnyRef | Null): Boolean = !(x eq y) From 755c6755009bdc9e98547a8bf73bd419ee3c3cab Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 14 Mar 2022 11:52:28 +0100 Subject: [PATCH 07/12] move extension methods to Predef instead of Scala3RunTime --- library/src/scala/runtime/Scala3RunTime.scala | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/library/src/scala/runtime/Scala3RunTime.scala b/library/src/scala/runtime/Scala3RunTime.scala index 2eed853114cc..b1645f5242aa 100644 --- a/library/src/scala/runtime/Scala3RunTime.scala +++ b/library/src/scala/runtime/Scala3RunTime.scala @@ -1,7 +1,5 @@ package scala.runtime -import scala.annotation.since - object Scala3RunTime: // Called by inline def assert's. Extracted to minimize the bytecode size at call site. @@ -21,12 +19,4 @@ object Scala3RunTime: if (isNull) throw new NullPointerException("tried to cast away nullability, but value is null") else x.asInstanceOf[x.type & T] - extension (inline x: AnyRef | Null) - @since("3.2") - inline def eq(inline y: AnyRef | Null): Boolean = - x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] - @since("3.2") - inline def ne(inline y: AnyRef | Null): Boolean = - !(x eq y) - end Scala3RunTime From cc87f351765d3805427ac1ad5b8869c3bceb4232 Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Thu, 5 May 2022 19:07:46 +0200 Subject: [PATCH 08/12] use @experimental instead of @since("3.2") (as suggested in today's LAMP meeting) --- library/src/scala/runtime/stdLibPatches/Predef.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/src/scala/runtime/stdLibPatches/Predef.scala b/library/src/scala/runtime/stdLibPatches/Predef.scala index f26544dfea50..64e76d3b8fd9 100644 --- a/library/src/scala/runtime/stdLibPatches/Predef.scala +++ b/library/src/scala/runtime/stdLibPatches/Predef.scala @@ -1,6 +1,6 @@ package scala.runtime.stdLibPatches -import scala.annotation.since +import scala.annotation.experimental object Predef: import compiletime.summonFrom @@ -51,10 +51,10 @@ object Predef: scala.runtime.Scala3RunTime.nn(x) extension (inline x: AnyRef | Null) - @since("3.2") + @experimental inline def eq(inline y: AnyRef | Null): Boolean = x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef] - @since("3.2") + @experimental inline def ne(inline y: AnyRef | Null): Boolean = !(x eq y) From 5aef5a2990b1155628461e722fb02340b76d379c Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 9 May 2022 11:20:24 +0200 Subject: [PATCH 09/12] add eq and ne extension methods to stdlibExperimentalDefinitions.scala --- .../tasty-inspector/stdlibExperimentalDefinitions.scala | 5 +++++ 1 file changed, 5 insertions(+) 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", ) From bb3dbf7564e917b0e19e09028aab405e1ee151b3 Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 9 May 2022 14:36:00 +0200 Subject: [PATCH 10/12] update coverage test checkfile --- tests/coverage/pos/Inlined.scoverage.check | 54 +++++++++++----------- 1 file changed, 27 insertions(+), 27 deletions(-) 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 From 03b391cedc6370ec4f08fd40a100e0271393ebb5 Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 9 May 2022 22:31:08 +0200 Subject: [PATCH 11/12] add comment --- library/src/scala/runtime/stdLibPatches/Predef.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/src/scala/runtime/stdLibPatches/Predef.scala b/library/src/scala/runtime/stdLibPatches/Predef.scala index 64e76d3b8fd9..8c9d6fae392d 100644 --- a/library/src/scala/runtime/stdLibPatches/Predef.scala +++ b/library/src/scala/runtime/stdLibPatches/Predef.scala @@ -50,6 +50,9 @@ object Predef: extension [T](x: T | Null) inline def nn: x.type & T = scala.runtime.Scala3RunTime.nn(x) + /** Enables an expression of type `T|Null`, where `T` is a subtype of `AnyRef`, to be checked for `null` + * using `eq` and `ne`, rather than only `==` and `!=`. This is needed because `Null` no longer has + * `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */ extension (inline x: AnyRef | Null) @experimental inline def eq(inline y: AnyRef | Null): Boolean = From 7c6b5596ab74aa0071fddde7906824cb26182db6 Mon Sep 17 00:00:00 2001 From: Ondrej Lhotak Date: Mon, 9 May 2022 23:00:22 +0200 Subject: [PATCH 12/12] split comment for each method, not whole extension block --- library/src/scala/runtime/stdLibPatches/Predef.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/src/scala/runtime/stdLibPatches/Predef.scala b/library/src/scala/runtime/stdLibPatches/Predef.scala index 8c9d6fae392d..080a3957f79f 100644 --- a/library/src/scala/runtime/stdLibPatches/Predef.scala +++ b/library/src/scala/runtime/stdLibPatches/Predef.scala @@ -50,13 +50,16 @@ object Predef: extension [T](x: T | Null) inline def nn: x.type & T = scala.runtime.Scala3RunTime.nn(x) - /** Enables an expression of type `T|Null`, where `T` is a subtype of `AnyRef`, to be checked for `null` - * using `eq` and `ne`, rather than only `==` and `!=`. This is needed because `Null` no longer has - * `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */ 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)