Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fromNullable to Predef for explicit nulls #20222

Merged
merged 6 commits into from
May 1, 2024

Conversation

noti0na1
Copy link
Member

@noti0na1 noti0na1 commented Apr 18, 2024

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.

extension (inline opt: Option.type)
  @experimental
  inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf

val s: String | Null = "abc"
val sopt: Option[String] = Option.fromNullable(s)
The experimental issue (wait for #20260)

This PR is currently blocked by the experimental annotation: using the annotation in Predef would cause cyclic references when compiling the library.

[error] -- [E046] Cyclic Error: /dotty/library/src-non-bootstrapped/scala/annotation/experimental.scala:3:1 
[error] 3 |@deprecatedInheritance("Scheduled for being final in the future", "3.4.0")
[error]   | ^
[error]   | Cyclic reference involving class experimental
[error]   |
[error]   |  Run with -explain-cyclic for more details.
[error]   |
[error]   | longer explanation available when compiling with `-explain`
[error] -- [E008] Not Found Error: /dotty/library/src/scala/quoted/Expr.scala:70:17 
[error] 70 |    scala.Predef.summon[ToExpr[T]].apply(x)
[error]    |    ^^^^^^^^^^^^^^^^^^^
[error]    |    value summon is not a member of object Predef
[error] -- [E008] Not Found Error: /dotty/library/src/scala/quoted/Expr.scala:85:17 
[error] 85 |    scala.Predef.summon[FromExpr[T]].unapply(x)
[error]    |    ^^^^^^^^^^^^^^^^^^^
[error]    |    value summon is not a member of object Predef
[error] -- [E006] Not Found Error: /dotty/library/src/scala/quoted/Quotes.scala:68:6 
[error] 68 |      summon[FromExpr[T]].unapply(self)
[error]    |      ^^^^^^
[error]    |      Not found: summon
[error]    |
[error]    | longer explanation available when compiling with `-explain`
[error] -- [E006] Not Found Error: /dotty/library/src/scala/quoted/Quotes.scala:77:21 
[error] 77 |      val fromExpr = summon[FromExpr[T]]
[error]    |                     ^^^^^^
[error]    |                     Not found: summon
[error]    |
[error]    | longer explanation available when compiling with `-explain`
[error] -- [E006] Not Found Error: /dotty/library/src/scala/quoted/ToExpr.scala:100:46 
[error] 100 |      '{ Array[T](${Expr(arr.toSeq)}*)(${Expr(summon[ClassTag[T]])}) }
[error]     |                                              ^^^^^^
[error]     |                                              Not found: summon
[error]     |
[error]     | longer explanation available when compiling with `-explain`
[error] -- [E006] Not Found Error: /dotty/library/src/scala/quoted/ToExpr.scala:168:24 
[error] 168 |      Expr.ofSeq(xs.map(summon[ToExpr[T]].apply))
[error]     |                        ^^^^^^
[error]     |                        Not found: summon
[error]     |
[error]     | longer explanation available when compiling with `-explain`
[error] -- [E006] Not Found Error: /dotty/library/src/scala/quoted/ToExpr.scala:174:25 
[error] 174 |      Expr.ofList(xs.map(summon[ToExpr[T]].apply))
[error]     |                         ^^^^^^
[error]     |                         Not found: summon
[error]     |
[error]     | longer explanation available when compiling with `-explain`
[error] -- [E008] Not Found Error: /dotty/library/src/scala/reflect/Selectable.scala:24:60 
[error] 24 |      val fld = rcls.getField(NameTransformer.encode(name)).nn
[error]    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |value nn is not a member of java.lang.reflect.Field | Null, but could be made available as an extension method.
[error]    |
[error]    |The following import might fix the problem:
[error]    |
[error]    |  import scala.runtime.stdLibPatches.Predef.nn
[error]    |
[error] -- [E008] Not Found Error: /dotty/library/src/scala/reflect/Selectable.scala:38:72 
[error] 38 |    val mth = rcls.getMethod(NameTransformer.encode(name), paramTypes*).nn
[error]    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |value nn is not a member of java.lang.reflect.Method | Null, but could be made available as an extension method.
[error]    |
[error]    |The following import might fix the problem:
[error]    |
[error]    |  import scala.runtime.stdLibPatches.Predef.nn
[error]    |
[error] -- [E008] Not Found Error: /dotty/library/src/scala/runtime/LazyVals.scala:18:79 
[error] 18 |      val unsafeField = classOf[sun.misc.Unsafe].getDeclaredField("theUnsafe").nn
[error]    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |value nn is not a member of java.lang.reflect.Field | Null, but could be made available as an extension method.
[error]    |
[error]    |The following import might fix the problem:
[error]    |
[error]    |  import scala.runtime.stdLibPatches.Predef.nn
[error]    |
[error] -- [E008] Not Found Error: /dotty/library/src/scala/runtime/LazyVals.scala:29:50 
[error] 29 |    val processors = java.lang.Runtime.getRuntime.nn.availableProcessors()
[error]    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |value nn is not a member of Runtime | Null, but could be made available as an extension method.
[error]    |
[error]    |The following import might fix the problem:
[error]    |
[error]    |  import scala.runtime.stdLibPatches.Predef.nn
[error]    |
[error] -- [E008] Not Found Error: /dotty/library/src/scala/runtime/coverage/Invoker.scala:54:66 
[error] 54 |    MeasurementsPrefix + runtimeUUID + "." + Thread.currentThread.nn.getId
[error]    |                                             ^^^^^^^^^^^^^^^^^^^^^^^
[error]    |value nn is not a member of Thread | Null, but could be made available as an extension method.
[error]    |
[error]    |The following import might fix the problem:
[error]    |
[error]    |  import scala.runtime.stdLibPatches.Predef.nn
[error]    |
[error] -- [E046] Cyclic Error: /dotty/library/src/scala/runtime/stdLibPatches/Predef.scala:68:15 
[error] 68 |    inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf
[error]    |               ^
[error]    |               Cyclic reference involving method fromNullable
[error]    |
[error]    |                Run with -explain-cyclic for more details.
[error]    |
[error]    | longer explanation available when compiling with `-explain`
[warn] -- Warning: /dotty/library/src/scala/runtime/stdLibPatches/Predef.scala:64:10 
[warn] 64 |      !(x eq y)
[warn]    |          ^^
[warn]    |Alphanumeric method eq is not declared infix; it should not be used as infix operator.
[warn]    |Instead, use method syntax .eq(...) or backticked identifier `eq`.
[warn]    |The latter can be rewritten automatically under -rewrite -source 3.4-migration.
[error] -- [E008] Not Found Error: /dotty/library/src/scala/util/FromDigits.scala:138:56 
[error] 138 |    if (x == 0.0f && !zeroFloat.pattern.matcher(digits).nn.matches) throw NumberTooSmall()
[error]     |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]     |value nn is not a member of java.util.regex.Matcher | Null, but could be made available as an extension method.
[error]     |
[error]     |The following import might fix the problem:
[error]     |
[error]     |  import scala.runtime.stdLibPatches.Predef.nn
[error]     |
[error] -- [E008] Not Found Error: /dotty/library/src/scala/util/FromDigits.scala:156:56 
[error] 156 |    if (x == 0.0d && !zeroFloat.pattern.matcher(digits).nn.matches) throw NumberTooSmall()
[error]     |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]     |value nn is not a member of java.util.regex.Matcher | Null, but could be made available as an extension method.
[error]     |
[error]     |The following import might fix the problem:
[error]     |
[error]     |  import scala.runtime.stdLibPatches.Predef.nn
[error]     |
[error] No warnings can be incurred under -Werror (or -Xfatal-warnings)
[warn] one warning found
[error] 17 errors found
[error] (scala3-library / Compile / compileIncremental) Compilation failed
[error] Total time: 6 s, completed 18 Apr 2024, 14:59:41

cc @olhotak

@noti0na1 noti0na1 added area:nullability needs-minor-release This PR cannot be merged until the next minor release labels Apr 18, 2024
@noti0na1 noti0na1 added the area:library Standard library label Apr 24, 2024
@noti0na1 noti0na1 marked this pull request as ready for review April 24, 2024 16:27
Copy link
Contributor

@nicolasstucki nicolasstucki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise LGTM

library/src/scala/runtime/stdLibPatches/Predef.scala Outdated Show resolved Hide resolved
@sjrd
Copy link
Member

sjrd commented May 1, 2024

The core meeting decided to take this PR in on 3.5.0.

@nicolasstucki nicolasstucki assigned sjrd and unassigned nicolasstucki May 1, 2024
@sjrd sjrd merged commit e6bc130 into scala:main May 1, 2024
19 checks passed
@sjrd sjrd deleted the add-from-nullable branch May 1, 2024 20:59
@Kordyjan Kordyjan added this to the 3.5.0 milestone May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:library Standard library area:nullability needs-minor-release This PR cannot be merged until the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants