Skip to content

Commit 08e50eb

Browse files
committed
chore: add Predef.assert from stdlib patches
1 parent 292dc42 commit 08e50eb

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

library/src/scala/Predef.scala

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ 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, experimental, implicitNotFound}, elidable.ASSERTION
19+
import scala.annotation.{elidable, experimental, implicitNotFound, publicInBinary, targetName }, elidable.ASSERTION
2020
import scala.annotation.meta.{ companionClass, companionMethod }
2121
import scala.annotation.internal.{ RuntimeChecked }
2222
import scala.compiletime.summonFrom
@@ -275,7 +275,26 @@ object Predef extends LowPriorityImplicits {
275275
*/
276276
@inline def locally[T](@deprecatedName("x") x: T): T = x
277277

278-
// 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+
*/
279298

280299
/** Tests an expression, throwing an `AssertionError` if false.
281300
* Calls to this method will not be generated if `-Xelide-below`
@@ -285,8 +304,8 @@ object Predef extends LowPriorityImplicits {
285304
* @param assertion the expression to test
286305
* @group assertions
287306
*/
288-
@elidable(ASSERTION)
289-
def assert(assertion: Boolean): Unit = {
307+
@elidable(ASSERTION) @publicInBinary
308+
@targetName("assert") private[scala] def scala2Assert(assertion: Boolean): Unit = {
290309
if (!assertion)
291310
throw new java.lang.AssertionError("assertion failed")
292311
}
@@ -300,12 +319,22 @@ object Predef extends LowPriorityImplicits {
300319
* @param message a String to include in the failure message
301320
* @group assertions
302321
*/
303-
@elidable(ASSERTION) @inline
304-
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 = {
305324
if (!assertion)
306325
throw new java.lang.AssertionError("assertion failed: "+ message)
307326
}
308327

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+
309338
/** Tests an expression, throwing an `AssertionError` if false.
310339
* This method differs from assert only in the intent expressed:
311340
* assert contains a predicate which needs to be proven, while

0 commit comments

Comments
 (0)