@@ -16,8 +16,10 @@ import scala.language.`2.13`
1616import scala .language .implicitConversions
1717
1818import scala .collection .{mutable , immutable , ArrayOps , StringOps }, immutable .WrappedString
19- import scala .annotation .{elidable , implicitNotFound }, elidable .ASSERTION
19+ import scala .annotation .{elidable , experimental , implicitNotFound , publicInBinary , targetName }, elidable .ASSERTION
2020import scala .annotation .meta .{ companionClass , companionMethod }
21+ import scala .annotation .internal .{ RuntimeChecked }
22+ import scala .compiletime .summonFrom
2123
2224/** The `Predef` object provides definitions that are accessible in all Scala
2325 * compilation units without explicit qualification.
@@ -137,6 +139,23 @@ object Predef extends LowPriorityImplicits {
137139 */
138140 @ inline def valueOf [T ](implicit vt : ValueOf [T ]): T = vt.value
139141
142+ /**
143+ * Retrieve the single value of a type with a unique inhabitant.
144+ *
145+ * @example {{{
146+ * object Foo
147+ * val foo = valueOf[Foo.type]
148+ * // foo is Foo.type = Foo
149+ *
150+ * val bar = valueOf[23]
151+ * // bar is 23.type = 23
152+ * }}}
153+ * @group utilities
154+ */
155+ inline def valueOf [T ]: T = summonFrom {
156+ case ev : ValueOf [T ] => ev.value
157+ }
158+
140159 /** The `String` type in Scala has all the methods of the underlying
141160 * [[java.lang.String ]], of which it is just an alias.
142161 *
@@ -218,6 +237,13 @@ object Predef extends LowPriorityImplicits {
218237 */
219238 @ inline def implicitly [T ](implicit e : T ): T = e // TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero`
220239
240+ /** Summon a given value of type `T`. Usually, the argument is not passed explicitly.
241+ *
242+ * @tparam T the type of the value to be summoned
243+ * @return the given value typed: the provided type parameter
244+ */
245+ transparent inline def summon [T ](using x : T ): x.type = x
246+
221247 /** Used to mark code blocks as being expressions, instead of being taken as part of anonymous classes and the like.
222248 * This is just a different name for [[identity ]].
223249 *
@@ -249,7 +275,26 @@ object Predef extends LowPriorityImplicits {
249275 */
250276 @ inline def locally [T ](@ deprecatedName(" x" ) x : T ): T = x
251277
252- // assertions ---------------------------------------------------------
278+ // ==============================================================================================
279+ // ========================================= ASSERTIONS =========================================
280+ // ==============================================================================================
281+
282+ /* In Scala 3, `assert` are methods that are `transparent` and `inline`.
283+ In Scala 2, `assert` are methods that are elidable, inlinable by the optimizer
284+ For scala 2 code to be able to run with the scala 3 library in the classpath
285+ (following our own compatibility policies), we will need the `assert` methods
286+ to be available at runtime.
287+ To achieve this, we keep the Scala 3 signature publicly available.
288+ We rely on the fact that it is `inline` and will not be visible in the bytecode.
289+ To add the required Scala 2 ones, we define the `scala2Assert`, we use:
290+ - `@targetName` to swap the name in the generated code to `assert`
291+ - `@publicInBinary` to make it available during runtime.
292+ As such, we would successfully hijack the definitions of `assert` such as:
293+ - At compile time, we would have the definitions of `assert`
294+ - At runtime, the definitions of `scala2Assert` as `assert`
295+ NOTE: Tasty-Reader in Scala 2 will have to learn about this swapping if we are to
296+ allow loading the full Scala 3 library by it.
297+ */
253298
254299 /** Tests an expression, throwing an `AssertionError` if false.
255300 * Calls to this method will not be generated if `-Xelide-below`
@@ -259,8 +304,8 @@ object Predef extends LowPriorityImplicits {
259304 * @param assertion the expression to test
260305 * @group assertions
261306 */
262- @ elidable(ASSERTION )
263- def assert (assertion : Boolean ): Unit = {
307+ @ elidable(ASSERTION ) @ publicInBinary
308+ @ targetName( " assert " ) private [scala] def scala2Assert (assertion : Boolean ): Unit = {
264309 if (! assertion)
265310 throw new java.lang.AssertionError (" assertion failed" )
266311 }
@@ -274,12 +319,22 @@ object Predef extends LowPriorityImplicits {
274319 * @param message a String to include in the failure message
275320 * @group assertions
276321 */
277- @ elidable(ASSERTION ) @ inline
278- final def assert (assertion : Boolean , message : => Any ): Unit = {
322+ @ elidable(ASSERTION ) @ inline @ publicInBinary
323+ @ targetName( " assert " ) private [scala] final def scala2Assert (assertion : Boolean , message : => Any ): Unit = {
279324 if (! assertion)
280325 throw new java.lang.AssertionError (" assertion failed: " + message)
281326 }
282327
328+ transparent inline def assert (inline assertion : Boolean , inline message : => Any ): Unit =
329+ if ! assertion then scala.runtime.Scala3RunTime .assertFailed(message)
330+
331+ transparent inline def assert (inline assertion : Boolean ): Unit =
332+ if ! assertion then scala.runtime.Scala3RunTime .assertFailed()
333+
334+ // ==============================================================================================
335+ // ======================================== ASSUMPTIONS =========================================
336+ // ==============================================================================================
337+
283338 /** Tests an expression, throwing an `AssertionError` if false.
284339 * This method differs from assert only in the intent expressed:
285340 * assert contains a predicate which needs to be proven, while
@@ -509,6 +564,67 @@ object Predef extends LowPriorityImplicits {
509564 */
510565 // $ to avoid accidental shadowing (e.g. scala/bug#7788)
511566 implicit def $conforms [A ]: A => A = <:< .refl
567+
568+ // Extension methods for working with explicit nulls
569+
570+ /** Strips away the nullability from a value. Note that `.nn` performs a checked cast,
571+ * so if invoked on a `null` value it will throw an `NullPointerException`.
572+ * @example {{{
573+ * val s1: String | Null = "hello"
574+ * val s2: String = s1.nn
575+ *
576+ * val s3: String | Null = null
577+ * val s4: String = s3.nn // throw NullPointerException
578+ * }}}
579+ */
580+ extension [T ](x : T | Null ) inline def nn : x.type & T =
581+ if x.asInstanceOf [Any ] == null then scala.runtime.Scala3RunTime .nnFail()
582+ x.asInstanceOf [x.type & T ]
583+
584+ extension (inline x : AnyRef | Null )
585+ /** Enables an expression of type `T|Null`, where `T` is a subtype of `AnyRef`, to be checked for `null`
586+ * using `eq` rather than only `==`. This is needed because `Null` no longer has
587+ * `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */
588+ inline infix def eq (inline y : AnyRef | Null ): Boolean =
589+ x.asInstanceOf [AnyRef ] eq y.asInstanceOf [AnyRef ]
590+ /** Enables an expression of type `T|Null`, where `T` is a subtype of `AnyRef`, to be checked for `null`
591+ * using `ne` rather than only `!=`. This is needed because `Null` no longer has
592+ * `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */
593+ inline infix def ne (inline y : AnyRef | Null ): Boolean =
594+ ! (x eq y)
595+
596+ extension (opt : Option .type )
597+ @ experimental
598+ inline def fromNullable [T ](t : T | Null ): Option [T ] = Option (t).asInstanceOf [Option [T ]]
599+
600+ /** A type supporting Self-based type classes.
601+ *
602+ * A is TC
603+ *
604+ * expands to
605+ *
606+ * TC { type Self = A }
607+ *
608+ * which is what is needed for a context bound `[A: TC]`.
609+ */
610+ @ experimental
611+ infix type is [A <: AnyKind , B <: Any {type Self <: AnyKind }] = B { type Self = A }
612+
613+ extension [T ](x : T )
614+ /** Asserts that a term should be exempt from static checks that can be reliably checked at runtime.
615+ * @example {{{
616+ * val xs: Option[Int] = Option(1)
617+ * xs.runtimeChecked match
618+ * case Some(x) => x // `Some(_)` can be checked at runtime, so no warning
619+ * }}}
620+ * @example {{{
621+ * val xs: List[Int] = List(1,2,3)
622+ * val y :: ys = xs.runtimeChecked // `_ :: _` can be checked at runtime, so no warning
623+ * }}}
624+ */
625+ @ experimental
626+ inline def runtimeChecked : x.type @ RuntimeChecked = x : @ RuntimeChecked
627+
512628}
513629
514630/** The `LowPriorityImplicits` class provides implicit values that
0 commit comments