Skip to content

Commit 4e75aa2

Browse files
committed
chore: add stdlib patches to the actual definitions but Predef.assert
1 parent a19c2b0 commit 4e75aa2

File tree

3 files changed

+431
-2
lines changed

3 files changed

+431
-2
lines changed

library/src/scala/Predef.scala

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ import scala.language.`2.13`
1616
import scala.language.implicitConversions
1717

1818
import scala.collection.{mutable, immutable, ArrayOps, StringOps}, immutable.WrappedString
19-
import scala.annotation.{elidable, implicitNotFound}, elidable.ASSERTION
19+
import scala.annotation.{elidable, experimental, implicitNotFound}, elidable.ASSERTION
2020
import 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
*
@@ -509,6 +535,67 @@ object Predef extends LowPriorityImplicits {
509535
*/
510536
// $ to avoid accidental shadowing (e.g. scala/bug#7788)
511537
implicit def $conforms[A]: A => A = <:<.refl
538+
539+
// Extension methods for working with explicit nulls
540+
541+
/** Strips away the nullability from a value. Note that `.nn` performs a checked cast,
542+
* so if invoked on a `null` value it will throw an `NullPointerException`.
543+
* @example {{{
544+
* val s1: String | Null = "hello"
545+
* val s2: String = s1.nn
546+
*
547+
* val s3: String | Null = null
548+
* val s4: String = s3.nn // throw NullPointerException
549+
* }}}
550+
*/
551+
extension [T](x: T | Null) inline def nn: x.type & T =
552+
if x.asInstanceOf[Any] == null then scala.runtime.Scala3RunTime.nnFail()
553+
x.asInstanceOf[x.type & T]
554+
555+
extension (inline x: AnyRef | Null)
556+
/** Enables an expression of type `T|Null`, where `T` is a subtype of `AnyRef`, to be checked for `null`
557+
* using `eq` rather than only `==`. This is needed because `Null` no longer has
558+
* `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */
559+
inline infix def eq(inline y: AnyRef | Null): Boolean =
560+
x.asInstanceOf[AnyRef] eq y.asInstanceOf[AnyRef]
561+
/** Enables an expression of type `T|Null`, where `T` is a subtype of `AnyRef`, to be checked for `null`
562+
* using `ne` rather than only `!=`. This is needed because `Null` no longer has
563+
* `eq` or `ne` methods, only `==` and `!=` inherited from `Any`. */
564+
inline infix def ne(inline y: AnyRef | Null): Boolean =
565+
!(x eq y)
566+
567+
extension (opt: Option.type)
568+
@experimental
569+
inline def fromNullable[T](t: T | Null): Option[T] = Option(t).asInstanceOf[Option[T]]
570+
571+
/** A type supporting Self-based type classes.
572+
*
573+
* A is TC
574+
*
575+
* expands to
576+
*
577+
* TC { type Self = A }
578+
*
579+
* which is what is needed for a context bound `[A: TC]`.
580+
*/
581+
@experimental
582+
infix type is[A <: AnyKind, B <: Any{type Self <: AnyKind}] = B { type Self = A }
583+
584+
extension [T](x: T)
585+
/**Asserts that a term should be exempt from static checks that can be reliably checked at runtime.
586+
* @example {{{
587+
* val xs: Option[Int] = Option(1)
588+
* xs.runtimeChecked match
589+
* case Some(x) => x // `Some(_)` can be checked at runtime, so no warning
590+
* }}}
591+
* @example {{{
592+
* val xs: List[Int] = List(1,2,3)
593+
* val y :: ys = xs.runtimeChecked // `_ :: _` can be checked at runtime, so no warning
594+
* }}}
595+
*/
596+
@experimental
597+
inline def runtimeChecked: x.type @RuntimeChecked = x: @RuntimeChecked
598+
512599
}
513600

514601
/** The `LowPriorityImplicits` class provides implicit values that

0 commit comments

Comments
 (0)