From fc43000ac3bb51ac420460c6931805aa26c6df25 Mon Sep 17 00:00:00 2001 From: noti0na1 <8036790+noti0na1@users.noreply.github.com> Date: Thu, 25 Apr 2024 14:42:30 +0000 Subject: [PATCH 1/6] Make experimental final --- library/src-bootstrapped/scala/annotation/experimental.scala | 3 +-- .../src-non-bootstrapped/scala/annotation/experimental.scala | 3 +-- project/MiMaFilters.scala | 1 + tests/neg/experimentalExperimental.scala | 1 + tests/pos/experimentalExperimental.scala | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) create mode 100644 tests/neg/experimentalExperimental.scala delete mode 100644 tests/pos/experimentalExperimental.scala diff --git a/library/src-bootstrapped/scala/annotation/experimental.scala b/library/src-bootstrapped/scala/annotation/experimental.scala index 185db51c07c1..634cfe12db7f 100644 --- a/library/src-bootstrapped/scala/annotation/experimental.scala +++ b/library/src-bootstrapped/scala/annotation/experimental.scala @@ -5,6 +5,5 @@ package scala.annotation * @see [[https://dotty.epfl.ch/docs/reference/other-new-features/experimental-defs]] * @syntax markdown */ -@deprecatedInheritance("Scheduled for being final in the future", "3.4.0") -class experimental(message: String) extends StaticAnnotation: +final class experimental(message: String) extends StaticAnnotation: def this() = this("") diff --git a/library/src-non-bootstrapped/scala/annotation/experimental.scala b/library/src-non-bootstrapped/scala/annotation/experimental.scala index dbc3296aa1ab..e879b47e12ff 100644 --- a/library/src-non-bootstrapped/scala/annotation/experimental.scala +++ b/library/src-non-bootstrapped/scala/annotation/experimental.scala @@ -1,4 +1,3 @@ package scala.annotation -@deprecatedInheritance("Scheduled for being final in the future", "3.4.0") -class experimental extends StaticAnnotation +final class experimental extends StaticAnnotation diff --git a/project/MiMaFilters.scala b/project/MiMaFilters.scala index 904367d15ecd..3dec32a4c369 100644 --- a/project/MiMaFilters.scala +++ b/project/MiMaFilters.scala @@ -56,6 +56,7 @@ object MiMaFilters { ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeModule.apply"), ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeMethods.methodTypeKind"), ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeMethods.isContextual"), + ProblemFilters.exclude[FinalClassProblem]("scala.annotation.experimental"), ), // Breaking changes since last LTS diff --git a/tests/neg/experimentalExperimental.scala b/tests/neg/experimentalExperimental.scala new file mode 100644 index 000000000000..9011a3e49225 --- /dev/null +++ b/tests/neg/experimentalExperimental.scala @@ -0,0 +1 @@ +class MyExperimentalAnnot extends scala.annotation.experimental // error diff --git a/tests/pos/experimentalExperimental.scala b/tests/pos/experimentalExperimental.scala deleted file mode 100644 index 4b57e5b94346..000000000000 --- a/tests/pos/experimentalExperimental.scala +++ /dev/null @@ -1 +0,0 @@ -class MyExperimentalAnnot extends scala.annotation.experimental From 38b87f977d77c45c49d3e0bae64d8ed12f715555 Mon Sep 17 00:00:00 2001 From: noti0na1 <8036790+noti0na1@users.noreply.github.com> Date: Thu, 25 Apr 2024 14:48:27 +0000 Subject: [PATCH 2/6] Add a comment for experimental in MiMaFilters --- project/MiMaFilters.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/project/MiMaFilters.scala b/project/MiMaFilters.scala index 3dec32a4c369..cc0da889620f 100644 --- a/project/MiMaFilters.scala +++ b/project/MiMaFilters.scala @@ -56,6 +56,7 @@ object MiMaFilters { ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeModule.apply"), ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeMethods.methodTypeKind"), ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeMethods.isContextual"), + // Change `experimental` annotation to a final class ProblemFilters.exclude[FinalClassProblem]("scala.annotation.experimental"), ), From e55a36dd4385bbdb53b75be923d87854ed9e3d15 Mon Sep 17 00:00:00 2001 From: noti0na1 <8036790+noti0na1@users.noreply.github.com> Date: Fri, 26 Apr 2024 11:22:45 +0000 Subject: [PATCH 3/6] Add fromNullable --- library/src/scala/runtime/stdLibPatches/Predef.scala | 4 ++++ project/MiMaFilters.scala | 1 + tests/explicit-nulls/neg/from-nullable.scala | 6 ++++++ .../run-tasty-inspector/stdlibExperimentalDefinitions.scala | 3 +++ 4 files changed, 14 insertions(+) create mode 100644 tests/explicit-nulls/neg/from-nullable.scala diff --git a/library/src/scala/runtime/stdLibPatches/Predef.scala b/library/src/scala/runtime/stdLibPatches/Predef.scala index 2146254a9467..ca9978ea347f 100644 --- a/library/src/scala/runtime/stdLibPatches/Predef.scala +++ b/library/src/scala/runtime/stdLibPatches/Predef.scala @@ -62,4 +62,8 @@ object Predef: * `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */ inline def ne(inline y: AnyRef | Null): Boolean = !(x eq y) + + extension (inline opt: Option.type) + @experimental + inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf end Predef diff --git a/project/MiMaFilters.scala b/project/MiMaFilters.scala index cc0da889620f..5ccb70ad6fdf 100644 --- a/project/MiMaFilters.scala +++ b/project/MiMaFilters.scala @@ -9,6 +9,7 @@ object MiMaFilters { // Additions that require a new minor version of the library Build.mimaPreviousDottyVersion -> Seq( ProblemFilters.exclude[DirectMissingMethodProblem]("scala.annotation.experimental.this"), + ProblemFilters.exclude[FinalClassProblem]("scala.annotation.experimental"), ), // Additions since last LTS diff --git a/tests/explicit-nulls/neg/from-nullable.scala b/tests/explicit-nulls/neg/from-nullable.scala new file mode 100644 index 000000000000..ab4ab7f63e8e --- /dev/null +++ b/tests/explicit-nulls/neg/from-nullable.scala @@ -0,0 +1,6 @@ +import scala.annotation.experimental + +@experimental def testFromNullable = + val s: String | Null = "abc" + val sopt1: Option[String] = Option(s) // error + val sopt2: Option[String] = Option.fromNullable(s) // ok \ No newline at end of file diff --git a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala index 5e6e5700b719..76c08fa24213 100644 --- a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala +++ b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala @@ -76,6 +76,9 @@ val experimentalDefinitionInLibrary = Set( "scala.Tuple$.Reverse", // can be stabilized in 3.5 "scala.Tuple$.ReverseOnto", // can be stabilized in 3.5 "scala.runtime.Tuples$.reverse", // can be stabilized in 3.5 + + // New feature: fromNullable for explicit nulls + "scala.Predef$.fromNullable", ) From c1291d3ef844b7c7e4ed88797bf1d7f818fffd88 Mon Sep 17 00:00:00 2001 From: noti0na1 Date: Tue, 30 Apr 2024 13:36:25 +0200 Subject: [PATCH 4/6] Update library/src/scala/runtime/stdLibPatches/Predef.scala Co-authored-by: Nicolas Stucki --- library/src/scala/runtime/stdLibPatches/Predef.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/scala/runtime/stdLibPatches/Predef.scala b/library/src/scala/runtime/stdLibPatches/Predef.scala index ca9978ea347f..7684ca2700f4 100644 --- a/library/src/scala/runtime/stdLibPatches/Predef.scala +++ b/library/src/scala/runtime/stdLibPatches/Predef.scala @@ -65,5 +65,5 @@ object Predef: extension (inline opt: Option.type) @experimental - inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf + inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf[Option[T]] end Predef From 4d07f58c8540a76feb25bb706ddf063dfde3c8a6 Mon Sep 17 00:00:00 2001 From: noti0na1 <8036790+noti0na1@users.noreply.github.com> Date: Wed, 1 May 2024 16:39:19 +0000 Subject: [PATCH 5/6] Add a run test --- tests/explicit-nulls/run/from-nullable.check | 2 ++ tests/explicit-nulls/run/from-nullable.scala | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/explicit-nulls/run/from-nullable.check create mode 100644 tests/explicit-nulls/run/from-nullable.scala diff --git a/tests/explicit-nulls/run/from-nullable.check b/tests/explicit-nulls/run/from-nullable.check new file mode 100644 index 000000000000..43d418e64a03 --- /dev/null +++ b/tests/explicit-nulls/run/from-nullable.check @@ -0,0 +1,2 @@ +hello +None diff --git a/tests/explicit-nulls/run/from-nullable.scala b/tests/explicit-nulls/run/from-nullable.scala new file mode 100644 index 000000000000..6f01e402e790 --- /dev/null +++ b/tests/explicit-nulls/run/from-nullable.scala @@ -0,0 +1,17 @@ +object Test: + import scala.annotation.experimental + + @experimental def main(args: Array[String]): Unit = + val s1: String | Null = "hello" + val s2: String | Null = null + + val opts1: Option[String] = Option.fromNullable(s1) + val opts2: Option[String] = Option.fromNullable(s2) + + opts1 match + case Some(s) => println(s) + case None => println("None") + + opts2 match + case Some(s) => println(s) + case None => println("None") From 850f77ed8da368af47763c1e6e8767f4334ae688 Mon Sep 17 00:00:00 2001 From: noti0na1 <8036790+noti0na1@users.noreply.github.com> Date: Wed, 1 May 2024 17:59:30 +0000 Subject: [PATCH 6/6] Make opt non-inlined --- library/src/scala/runtime/stdLibPatches/Predef.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/scala/runtime/stdLibPatches/Predef.scala b/library/src/scala/runtime/stdLibPatches/Predef.scala index 7684ca2700f4..7abd92e408f8 100644 --- a/library/src/scala/runtime/stdLibPatches/Predef.scala +++ b/library/src/scala/runtime/stdLibPatches/Predef.scala @@ -63,7 +63,7 @@ object Predef: inline def ne(inline y: AnyRef | Null): Boolean = !(x eq y) - extension (inline opt: Option.type) + extension (opt: Option.type) @experimental inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf[Option[T]] end Predef