Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 570e840

Browse files
Add missing definitions in the stdlib (from stdLibPatches) (#23562)
Add all the definitions that we used to patch in the compiler to their actual source file. No more patching. Since this will be merged during the `3.7.3` cycle, we cannot undo yet the logic, hence, we rely on the facts that: - None of the changes in this PR are visible during 3.7.3 - Patching is disabled via `-Yno-stdlib-patches` Even with all the definitions in the trees, we can still not enable back `-Ycheck:all` because the trees for `Tuple1` and `Tuple2` do not contain the definitions of the specialized functions. Based on #23510
2 parents b6c232d + 08e50eb commit 570e840

File tree

3 files changed

+465
-7
lines changed

3 files changed

+465
-7
lines changed

‎library/src/scala/Predef.scala‎

Lines changed: 122 additions & 6 deletions
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, publicInBinary, targetName}, 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
*
@@ -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

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /