Skip to content

Commit 3e90f1e

Browse files
committed
Add Tree.of and Term.of to transform Expr into Tree
This is replacement for `Expr.asReflectTree` (which replaced `unseal`). This version of the API aligns with `Type.of`, `TypeRepr.of` and `TypeTree.of`. By requiring the `Tree` or `Term` modules to do the transformation we can ensure that all uses of the reflection API have the `qctx.reflect` import or explicit path. This delimits in a clearer way where the reflect API is used.
1 parent 88541a3 commit 3e90f1e

File tree

92 files changed

+207
-179
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+207
-179
lines changed

compiler/src/scala/quoted/internal/impl/QuoteContextImpl.scala

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,20 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
4747

4848
extension [T](self: scala.quoted.Expr[T]):
4949
def show: String =
50-
reflect.TreeMethodsImpl.show(self.asReflectTree)
50+
reflect.TreeMethodsImpl.show(reflect.Term.of(self))
5151

5252
def showAnsiColored: String =
53-
reflect.TreeMethodsImpl.showAnsiColored(self.asReflectTree)
53+
reflect.TreeMethodsImpl.showAnsiColored(reflect.Term.of(self))
5454

5555
def matches(that: scala.quoted.Expr[Any]): Boolean =
56-
treeMatch(self.asReflectTree, that.asReflectTree).nonEmpty
57-
58-
def asReflectTree: reflect.Term =
59-
val expr = self.asInstanceOf[ExprImpl]
60-
expr.checkScopeId(QuoteContextImpl.this.hashCode)
61-
expr.tree
56+
treeMatch(reflect.Term.of(self), reflect.Term.of(that)).nonEmpty
6257

6358
end extension
6459

6560
extension [X](self: scala.quoted.Expr[Any]):
6661
/** Checks is the `quoted.Expr[?]` is valid expression of type `X` */
6762
def isExprOf(using scala.quoted.Type[X]): Boolean =
68-
reflect.TypeReprMethodsImpl.<:<(self.asReflectTree.tpe)(reflect.TypeRepr.of[X])
63+
reflect.TypeReprMethodsImpl.<:<(reflect.Term.of(self).tpe)(reflect.TypeRepr.of[X])
6964

7065
/** Convert this to an `quoted.Expr[X]` if this expression is a valid expression of type `X` or throws */
7166
def asExprOf(using scala.quoted.Type[X]): scala.quoted.Expr[X] = {
@@ -74,7 +69,7 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
7469
else
7570
throw Exception(
7671
s"""Expr cast exception: ${self.show}
77-
|of type: ${reflect.TypeReprMethodsImpl.show(self.asReflectTree.tpe)}
72+
|of type: ${reflect.TypeReprMethodsImpl.show(reflect.Term.of(self).tpe)}
7873
|did not conform to type: ${reflect.TypeReprMethodsImpl.show(reflect.TypeRepr.of[X])}
7974
|""".stripMargin
8075
)
@@ -89,7 +84,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
8984

9085
type Tree = tpd.Tree
9186

92-
object Tree extends TreeModule
87+
object Tree extends TreeModule:
88+
def of(expr: Expr[Any]): Tree = Term.of(expr)
89+
end Tree
9390

9491
object TreeMethodsImpl extends TreeMethods:
9592
extension (self: Tree):
@@ -328,6 +325,11 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
328325
end TermTypeTest
329326

330327
object Term extends TermModule:
328+
def of(expr: Expr[Any]): Term =
329+
val exprImpl = expr.asInstanceOf[ExprImpl]
330+
exprImpl.checkScopeId(QuoteContextImpl.this.hashCode)
331+
exprImpl.tree
332+
331333
def betaReduce(tree: Term): Option[Term] =
332334
tree match
333335
case app @ tpd.Apply(tpd.Select(fn, nme.apply), args) if dotc.core.Symbols.defn.isFunctionType(fn.tpe) =>
@@ -2551,8 +2553,8 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
25512553

25522554
object ExprMatch extends ExprMatchModule:
25532555
def unapply[TypeBindings <: Tuple, Tup <: Tuple](scrutinee: scala.quoted.Expr[Any])(using pattern: scala.quoted.Expr[Any]): Option[Tup] =
2554-
val scrutineeTree = QuoteContextImpl.this.asReflectTree(scrutinee)
2555-
val patternTree = QuoteContextImpl.this.asReflectTree(pattern)
2556+
val scrutineeTree = reflect.Term.of(scrutinee)
2557+
val patternTree = reflect.Term.of(pattern)
25562558
treeMatch(scrutineeTree, patternTree).asInstanceOf[Option[Tup]]
25572559
end ExprMatch
25582560

docs/docs/reference/metaprogramming/tasty-reflect.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ trees. For example the `Literal(_)` extractor used below.
4242
```scala
4343
def natConstImpl(x: Expr[Int])(using qctx: QuoteContext): Expr[Int] = {
4444
import qctx.reflect._
45-
val xTree: Term = x.unseal
45+
val xTree: Term = Term.of(x)
4646
xTree match {
4747
case Inlined(_, _, Literal(Constant(n: Int))) =>
4848
if (n <= 0) {

library/src-bootstrapped/scala/quoted/Expr.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ object Expr {
1414
* Some bindings may be elided as an early optimization.
1515
*/
1616
def betaReduce[T](expr: Expr[T])(using qctx: QuoteContext): Expr[T] =
17-
qctx.reflect.Term.betaReduce(expr.unseal) match
17+
import qctx.reflect._
18+
Term.betaReduce(Term.of(expr)) match
1819
case Some(expr1) => expr1.asExpr.asInstanceOf[Expr[T]]
1920
case _ => expr
2021

@@ -24,7 +25,7 @@ object Expr {
2425
*/
2526
def block[T](statements: List[Expr[Any]], expr: Expr[T])(using qctx: QuoteContext): Expr[T] = {
2627
import qctx.reflect._
27-
Block(statements.map(_.unseal), expr.unseal).asExpr.asInstanceOf[Expr[T]]
28+
Block(statements.map(Term.of), Term.of(expr)).asExpr.asInstanceOf[Expr[T]]
2829
}
2930

3031
/** Lift a value into an expression containing the construction of that value */

library/src-bootstrapped/scala/quoted/ExprMap.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ trait ExprMap:
104104
type X
105105
val expr = tree.asExpr.asInstanceOf[Expr[X]]
106106
val t = tpe.asType.asInstanceOf[Type[X]]
107-
transform(expr)(using qctx, t).unseal
107+
val transformedExpr = transform(expr)(using qctx, t)
108+
Term.of(transformedExpr)
108109
case _ =>
109110
transformTermChildren(tree, tpe)
110111

@@ -144,7 +145,7 @@ trait ExprMap:
144145
trees mapConserve (transformTypeCaseDef(_))
145146

146147
}
147-
new MapChildren().transformTermChildren(e.unseal, TypeRepr.of[T]).asExprOf[T]
148+
new MapChildren().transformTermChildren(Term.of(e), TypeRepr.of[T]).asExprOf[T]
148149
}
149150

150151
end ExprMap

library/src/scala/quoted/Const.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ object Const {
2323
case Inlined(_, Nil, e) => rec(e)
2424
case _ => None
2525
}
26-
rec(expr.unseal)
26+
rec(Term.of(expr))
2727
}
2828

2929
}

library/src/scala/quoted/QuoteContext.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,13 @@ trait QuoteContext { self: internal.QuoteUnpickler & internal.QuoteMatching =>
4848
unlift.fromExpr(self)(using QuoteContext.this).getOrElse(reportError)
4949

5050
/** View this expression `quoted.Expr[T]` as a `Term` */
51+
@deprecated("Use reflect.Term.of", "")
5152
def unseal: reflect.Term = self.asReflectTree // TODO remove
5253

5354
/** View this expression `quoted.Expr[T]` as a `Term` */
54-
def asReflectTree: reflect.Term
55+
@deprecated("Use reflect.Term.of", "")
56+
def asReflectTree: reflect.Term = // TODO remove
57+
reflect.Term.of(self)
5558
end extension
5659

5760
// Extension methods for `Expr[Any]` that take another explicit type parameter

library/src/scala/quoted/Reflection.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,10 @@ trait Reflection { reflection =>
129129

130130
val Tree: TreeModule
131131

132-
trait TreeModule { this: Tree.type => }
132+
trait TreeModule { this: Tree.type =>
133+
/** Returns the Term representation this expression */
134+
def of(expr: Expr[Any]): Tree
135+
}
133136

134137
given TreeMethods as TreeMethods = TreeMethodsImpl
135138
protected val TreeMethodsImpl: TreeMethods
@@ -372,6 +375,9 @@ trait Reflection { reflection =>
372375

373376
trait TermModule { this: Term.type =>
374377

378+
/** Returns the Term representation this expression */
379+
def of(expr: Expr[Any]): Term
380+
375381
/** Returns a term that is functionally equivalent to `t`,
376382
* however if `t` is of the form `((y1, ..., yn) => e2)(e1, ..., en)`
377383
* then it optimizes this the top most call by returning the `Some`

library/src/scala/quoted/Varargs.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ object Varargs {
1717
*/
1818
def apply[T](xs: Seq[Expr[T]])(using tp: Type[T], qctx: QuoteContext): Expr[Seq[T]] = {
1919
import qctx.reflect._
20-
Repeated(xs.map[Term](_.unseal).toList, TypeTree.of[T]).asExpr.asInstanceOf[Expr[Seq[T]]]
20+
Repeated(xs.map(Term.of).toList, TypeTree.of[T]).asExpr.asInstanceOf[Expr[Seq[T]]]
2121
}
2222

2323
/** Matches a literal sequence of expressions and return a sequence of expressions.
@@ -40,7 +40,7 @@ object Varargs {
4040
case Inlined(_, Nil, e) => rec(e)
4141
case _ => None
4242
}
43-
rec(expr.unseal)
43+
rec(Term.of(expr))
4444
}
4545

4646
}

library/src/scala/quoted/report.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ object report:
44

55
/** Report an error at the position of the macro expansion */
66
def error(msg: => String)(using qctx: QuoteContext): Unit =
7-
qctx.reflect.Reporting.error(msg, qctx.reflect.Position.ofMacroExpansion)
7+
import qctx.reflect._
8+
Reporting.error(msg, Position.ofMacroExpansion)
89

910
/** Report an error at the on the position of `expr` */
1011
def error(msg: => String, expr: Expr[Any])(using qctx: QuoteContext): Unit =
11-
qctx.reflect.Reporting.error(msg, expr.unseal.pos)
12+
import qctx.reflect._
13+
Reporting.error(msg, Term.of(expr).pos)
1214

1315
/** Report an error at the position of the macro expansion and throws a StopQuotedContext */
1416
def throwError(msg: => String)(using qctx: QuoteContext): Nothing = {
@@ -23,11 +25,13 @@ object report:
2325

2426
/** Report a warning */
2527
def warning(msg: => String)(using qctx: QuoteContext): Unit =
26-
qctx.reflect.Reporting.warning(msg, qctx.reflect.Position.ofMacroExpansion)
28+
import qctx.reflect._
29+
Reporting.warning(msg, Position.ofMacroExpansion)
2730

2831
/** Report a warning at the on the position of `expr` */
29-
def warning(msg: => String, expr: Expr[_])(using qctx: QuoteContext): Unit =
30-
qctx.reflect.Reporting.warning(msg, expr.unseal.pos)
32+
def warning(msg: => String, expr: Expr[Any])(using qctx: QuoteContext): Unit =
33+
import qctx.reflect._
34+
Reporting.warning(msg, Term.of(expr).pos)
3135

3236
/** Throwable used to stop the expansion of a macro after an error was reported */
3337
class StopQuotedContext extends Throwable

tests/neg-macros/i6432/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ object Macro {
1010
sc match {
1111
case '{ StringContext(${Varargs(parts)}: _*) } =>
1212
for (part @ Const(s) <- parts)
13-
Reporting.error(s, part.unseal.pos)
13+
Reporting.error(s, Term.of(part).pos)
1414
}
1515
'{}
1616
}

0 commit comments

Comments
 (0)