@@ -16,8 +16,10 @@ import scala.language.`2.13`
16
16
import scala .language .implicitConversions
17
17
18
18
import 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
20
20
import scala .annotation .meta .{ companionClass , companionMethod }
21
+ import scala .annotation .internal .{ RuntimeChecked }
22
+ import scala .compiletime .summonFrom
21
23
22
24
/** The `Predef` object provides definitions that are accessible in all Scala
23
25
* compilation units without explicit qualification.
@@ -137,6 +139,23 @@ object Predef extends LowPriorityImplicits {
137
139
*/
138
140
@ inline def valueOf [T ](implicit vt : ValueOf [T ]): T = vt.value
139
141
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
+
140
159
/** The `String` type in Scala has all the methods of the underlying
141
160
* [[java.lang.String ]], of which it is just an alias.
142
161
*
@@ -218,6 +237,13 @@ object Predef extends LowPriorityImplicits {
218
237
*/
219
238
@ 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`
220
239
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
+
221
247
/** Used to mark code blocks as being expressions, instead of being taken as part of anonymous classes and the like.
222
248
* This is just a different name for [[identity ]].
223
249
*
@@ -249,7 +275,26 @@ object Predef extends LowPriorityImplicits {
249
275
*/
250
276
@ inline def locally [T ](@ deprecatedName(" x" ) x : T ): T = x
251
277
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
+ */
253
298
254
299
/** Tests an expression, throwing an `AssertionError` if false.
255
300
* Calls to this method will not be generated if `-Xelide-below`
@@ -259,8 +304,8 @@ object Predef extends LowPriorityImplicits {
259
304
* @param assertion the expression to test
260
305
* @group assertions
261
306
*/
262
- @ elidable(ASSERTION )
263
- def assert (assertion : Boolean ): Unit = {
307
+ @ elidable(ASSERTION ) @ publicInBinary
308
+ @ targetName( " assert " ) private [scala] def scala2Assert (assertion : Boolean ): Unit = {
264
309
if (! assertion)
265
310
throw new java.lang.AssertionError (" assertion failed" )
266
311
}
@@ -274,12 +319,22 @@ object Predef extends LowPriorityImplicits {
274
319
* @param message a String to include in the failure message
275
320
* @group assertions
276
321
*/
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 = {
279
324
if (! assertion)
280
325
throw new java.lang.AssertionError (" assertion failed: " + message)
281
326
}
282
327
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
+
283
338
/** Tests an expression, throwing an `AssertionError` if false.
284
339
* This method differs from assert only in the intent expressed:
285
340
* assert contains a predicate which needs to be proven, while
@@ -509,6 +564,67 @@ object Predef extends LowPriorityImplicits {
509
564
*/
510
565
// $ to avoid accidental shadowing (e.g. scala/bug#7788)
511
566
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
+
512
628
}
513
629
514
630
/** The `LowPriorityImplicits` class provides implicit values that
0 commit comments