Skip to content

Commit e6bc130

Browse files
authored
Add fromNullable to Predef for explicit nulls (#20222)
The attempt to enable explicit nulls for community projects has shown the usefulness of `fromNullable`, so we decide to include it in the std library. It is a helper function which can turn a nullable value into an option.
2 parents 492f881 + 850f77e commit e6bc130

File tree

10 files changed

+38
-5
lines changed

10 files changed

+38
-5
lines changed

library/src-bootstrapped/scala/annotation/experimental.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@ package scala.annotation
55
* @see [[https://dotty.epfl.ch/docs/reference/other-new-features/experimental-defs]]
66
* @syntax markdown
77
*/
8-
@deprecatedInheritance("Scheduled for being final in the future", "3.4.0")
9-
class experimental(message: String) extends StaticAnnotation:
8+
final class experimental(message: String) extends StaticAnnotation:
109
def this() = this("")
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
package scala.annotation
22

3-
@deprecatedInheritance("Scheduled for being final in the future", "3.4.0")
4-
class experimental extends StaticAnnotation
3+
final class experimental extends StaticAnnotation

library/src/scala/runtime/stdLibPatches/Predef.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,8 @@ object Predef:
6262
* `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */
6363
inline def ne(inline y: AnyRef | Null): Boolean =
6464
!(x eq y)
65+
66+
extension (opt: Option.type)
67+
@experimental
68+
inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf[Option[T]]
6569
end Predef

project/MiMaFilters.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ object MiMaFilters {
99
// Additions that require a new minor version of the library
1010
Build.mimaPreviousDottyVersion -> Seq(
1111
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.annotation.experimental.this"),
12+
ProblemFilters.exclude[FinalClassProblem]("scala.annotation.experimental"),
1213
),
1314

1415
// Additions since last LTS
@@ -56,6 +57,8 @@ object MiMaFilters {
5657
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeModule.apply"),
5758
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeMethods.methodTypeKind"),
5859
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#MethodTypeMethods.isContextual"),
60+
// Change `experimental` annotation to a final class
61+
ProblemFilters.exclude[FinalClassProblem]("scala.annotation.experimental"),
5962
),
6063

6164
// Breaking changes since last LTS
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.annotation.experimental
2+
3+
@experimental def testFromNullable =
4+
val s: String | Null = "abc"
5+
val sopt1: Option[String] = Option(s) // error
6+
val sopt2: Option[String] = Option.fromNullable(s) // ok
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
hello
2+
None
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
object Test:
2+
import scala.annotation.experimental
3+
4+
@experimental def main(args: Array[String]): Unit =
5+
val s1: String | Null = "hello"
6+
val s2: String | Null = null
7+
8+
val opts1: Option[String] = Option.fromNullable(s1)
9+
val opts2: Option[String] = Option.fromNullable(s2)
10+
11+
opts1 match
12+
case Some(s) => println(s)
13+
case None => println("None")
14+
15+
opts2 match
16+
case Some(s) => println(s)
17+
case None => println("None")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
class MyExperimentalAnnot extends scala.annotation.experimental // error

tests/pos/experimentalExperimental.scala

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ val experimentalDefinitionInLibrary = Set(
7676
"scala.Tuple$.Reverse", // can be stabilized in 3.5
7777
"scala.Tuple$.ReverseOnto", // can be stabilized in 3.5
7878
"scala.runtime.Tuples$.reverse", // can be stabilized in 3.5
79+
80+
// New feature: fromNullable for explicit nulls
81+
"scala.Predef$.fromNullable",
7982
)
8083

8184

0 commit comments

Comments
 (0)