Skip to content

Commit 4bd610b

Browse files
committed
Move Expr.underlyingArgument to UnsafeExpr.underlyingArgument
Make it explicit that this operation may change the call semantics.
1 parent 5a86c1f commit 4bd610b

File tree

4 files changed

+32
-22
lines changed

4 files changed

+32
-22
lines changed

library/src/scala/quoted/Expr.scala

-20
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,6 @@ class Expr[+T] private[scala] {
2929
final def matches(that: Expr[Any])(given qctx: QuoteContext): Boolean =
3030
!scala.internal.quoted.Expr.unapply[Unit, Unit](this)(given that, false, qctx).isEmpty
3131

32-
/** Returns the undelying argument that was in the call before inlining.
33-
*
34-
* ```
35-
* inline foo(x: Int): Int = baz(x, x)
36-
* foo(bar())
37-
* ```
38-
* is inlined as
39-
* ```
40-
* val x = bar()
41-
* baz(x, x)
42-
* ```
43-
* in this case the undelying argument of `x` will be `bar()`.
44-
*
45-
* Warning: Using the undelying argument directly in the expansion of a macro may change the parameter
46-
* semantics from by-value to by-name.
47-
*/
48-
def underlyingArgument(given qctx: QuoteContext): Expr[T] = {
49-
import qctx.tasty.{given, _}
50-
this.unseal.underlyingArgument.seal.asInstanceOf[Expr[T]]
51-
}
5232
}
5333

5434
object Expr {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package scala.quoted
2+
package unsafe
3+
4+
object UnsafeExpr {
5+
6+
/** Returns the undelying argument that was in the call before inlining.
7+
*
8+
* ```
9+
* inline foo(x: Int): Int = baz(x, x)
10+
* foo(bar())
11+
* ```
12+
* is inlined as
13+
* ```
14+
* val x = bar()
15+
* baz(x, x)
16+
* ```
17+
* in this case the undelying argument of `x` will be `bar()`.
18+
*
19+
* Warning: Using the undelying argument directly in the expansion of a macro may
20+
* change the parameter semantics as by-value parameter could be re-evaluated.
21+
*/
22+
def underlyingArgument[T](expr: Expr[T])(given qctx: QuoteContext): Expr[T] = {
23+
import qctx.tasty.{given, _}
24+
expr.unseal.underlyingArgument.seal.asInstanceOf[Expr[T]]
25+
}
26+
27+
28+
}

tests/run-macros/i7898/Macro_1.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import quoted._
2+
import quoted.unsafe._
23
object Main {
34

45
def myMacroImpl(body: Expr[_])(given qctx: QuoteContext): Expr[_] = {
56
import qctx.tasty.{_, given}
6-
val bodyTerm = body.underlyingArgument.unseal
7+
val bodyTerm = UnsafeExpr.underlyingArgument(body).unseal
78
val showed = bodyTerm.show
89
'{
910
println(${Expr(showed)})

tests/run-macros/quoted-matching-docs/Macro_1.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import scala.quoted._
22
import scala.quoted.matching._
3+
import scala.quoted.unsafe._
34

45
inline def sum(args: Int*): Int = ${ sumExpr('args) }
56

@@ -10,7 +11,7 @@ private def sumExprShow(argsExpr: Expr[Seq[Int]])(given QuoteContext): Expr[Stri
1011

1112
private def sumExpr(argsExpr: Expr[Seq[Int]])(given qctx: QuoteContext): Expr[Int] = {
1213
import qctx.tasty.{given, _}
13-
argsExpr.underlyingArgument match {
14+
UnsafeExpr.underlyingArgument(argsExpr) match {
1415
case ConstSeq(args) => // args is of type Seq[Int]
1516
Expr(args.sum) // precompute result of sum
1617
case ExprSeq(argExprs) => // argExprs is of type Seq[Expr[Int]]

0 commit comments

Comments
 (0)