Skip to content

Commit 031110b

Browse files
committed
Move tasty.Reflection in QuoteContext
1 parent 8212f60 commit 031110b

File tree

119 files changed

+368
-347
lines changed

Some content is hidden

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

119 files changed

+368
-347
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,12 @@ class Definitions {
762762
@threadUnsafe lazy val QuotedExprType: TypeRef = ctx.requiredClassRef("scala.quoted.Expr")
763763
def QuotedExprClass(implicit ctx: Context): ClassSymbol = QuotedExprType.symbol.asClass
764764

765+
@threadUnsafe lazy val QuoteContextType: TypeRef = ctx.requiredClassRef("scala.quoted.QuoteContext")
766+
def QuoteContextClass(implicit ctx: Context): ClassSymbol = QuoteContextType.symbol.asClass
767+
768+
@threadUnsafe lazy val QuoteContextModule: TermSymbol = ctx.requiredModule("scala.quoted.QuoteContext")
769+
@threadUnsafe lazy val QuoteContext_macroContext: TermSymbol = QuoteContextModule.requiredMethod("macroContext")
770+
765771
@threadUnsafe lazy val InternalQuotedModuleRef: TermRef = ctx.requiredModuleRef("scala.internal.Quoted")
766772
def InternalQuotedModule: Symbol = InternalQuotedModuleRef.symbol
767773
@threadUnsafe lazy val InternalQuoted_exprQuoteR: TermRef = InternalQuotedModule.requiredMethodRef("exprQuote")

compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
166166
l == level ||
167167
level == -1 && (
168168
sym == defn.TastyReflection_macroContext ||
169+
sym == defn.QuoteContext_macroContext ||
169170
// here we assume that Splicer.canBeSpliced was true before going to level -1,
170171
// this implies that all non-inline arguments are quoted and that the following two cases are checked
171172
// on inline parameters or type parameters.

compiler/src/dotty/tools/dotc/transform/Splicer.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ object Splicer {
114114
args.toSeq
115115

116116
protected def interpretTastyContext()(implicit env: Env): Object = ReflectionImpl(ctx, pos)
117+
protected def interpretQuoteContext()(implicit env: Env): Object =
118+
new scala.quoted.QuoteContext(ReflectionImpl(ctx, pos))
117119

118120
protected def interpretStaticMethodCall(moduleClass: Symbol, fn: Symbol, args: => List[Object])(implicit env: Env): Object = {
119121
val (inst, clazz) =
@@ -308,6 +310,7 @@ object Splicer {
308310
protected def interpretLiteral(value: Any)(implicit env: Env): Result
309311
protected def interpretVarargs(args: List[Result])(implicit env: Env): Result
310312
protected def interpretTastyContext()(implicit env: Env): Result
313+
protected def interpretQuoteContext()(implicit env: Env): Result
311314
protected def interpretStaticMethodCall(module: Symbol, fn: Symbol, args: => List[Result])(implicit env: Env): Result
312315
protected def interpretModuleAccess(fn: Symbol)(implicit env: Env): Result
313316
protected def interpretNew(fn: Symbol, args: => List[Result])(implicit env: Env): Result
@@ -333,6 +336,9 @@ object Splicer {
333336
case _ if tree.symbol == defn.TastyReflection_macroContext =>
334337
interpretTastyContext()
335338

339+
case _ if tree.symbol == defn.QuoteContext_macroContext =>
340+
interpretQuoteContext()
341+
336342
case Call(fn, args) =>
337343
if (fn.symbol.isConstructor && fn.symbol.owner.owner.is(Package)) {
338344
interpretNew(fn.symbol, args.map(interpretTree))

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,11 @@ trait Implicits { self: Typer =>
707707
if (ctx.inInlineMethod || enclosingInlineds.nonEmpty) ref(defn.TastyReflection_macroContext)
708708
else EmptyTree
709709

710+
lazy val synthesizedQuoteContext: SpecialHandler =
711+
(formal, span) => implicit ctx =>
712+
if (ctx.inInlineMethod || enclosingInlineds.nonEmpty) ref(defn.QuoteContext_macroContext)
713+
else EmptyTree
714+
710715
lazy val synthesizedTupleFunction: SpecialHandler =
711716
(formal, span) => implicit ctx => formal match {
712717
case AppliedType(_, funArgs @ fun :: tupled :: Nil) =>
@@ -1033,9 +1038,10 @@ trait Implicits { self: Typer =>
10331038
mySpecialHandlers = List(
10341039
defn.ClassTagClass -> synthesizedClassTag,
10351040
defn.QuotedTypeClass -> synthesizedTypeTag,
1041+
defn.QuoteContextClass -> synthesizedQuoteContext,
10361042
defn.TastyReflectionClass -> synthesizedTastyContext,
10371043
defn.EqlClass -> synthesizedEq,
1038-
defn.TupledFunctionClass -> synthesizedTupleFunction,
1044+
defn.TupledFunctionClass -> synthesizedTupleFunction,
10391045
defn.ValueOfClass -> synthesizedValueOf,
10401046
defn.Mirror_ProductClass -> synthesizedProductMirror,
10411047
defn.Mirror_SumClass -> synthesizedSumMirror,

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1978,7 +1978,7 @@ class Typer extends Namer
19781978
fun = ref(defn.InternalQuotedMatcher_unapplyR).appliedToType(patType),
19791979
implicits =
19801980
ref(defn.InternalQuoted_exprQuoteR).appliedToType(shape.tpe).appliedTo(shape) ::
1981-
implicitArgTree(defn.TastyReflectionType, tree.span) :: Nil,
1981+
implicitArgTree(defn.QuoteContextType, tree.span) :: Nil,
19821982
patterns = splicePat :: Nil,
19831983
proto = pt)
19841984
}

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ guarantees and may fail at macro expansion time, hence additional explicit
2020
checks must be done.
2121

2222
To provide reflection capabilities in macros we need to add an implicit
23-
parameter of type `scala.tasty.Reflection` and import it in the scope where it
23+
parameter of type `scala.quoted.QuoteContext` and import `tasty._` from it in the scope where it
2424
is used.
2525

2626
```scala
@@ -29,23 +29,23 @@ import scala.tasty._
2929

3030
inline def natConst(x: => Int): Int = ${natConstImpl('{x})}
3131

32-
def natConstImpl(x: Expr[Int])(implicit reflection: Reflection): Expr[Int] = {
33-
import reflection._
32+
def natConstImpl(x: Expr[Int]) given (qctx: QuoteContext): Expr[Int] = {
33+
import qctx.tasty._
3434
...
3535
}
3636
```
3737

3838
### Sealing and Unsealing
3939

40-
`import reflection._` will provide an `unseal` extension method on `quoted.Expr`
41-
and `quoted.Type` which returns a `reflection.Term` that represents the tree of
42-
the expression and `reflection.TypeTree` that represents the tree of the type
40+
`import qctx.tasty._` will provide an `unseal` extension method on `quoted.Expr`
41+
and `quoted.Type` which returns a `qctx.tasty.Term` that represents the tree of
42+
the expression and `qctx.tasty.TypeTree` that represents the tree of the type
4343
respectively. It will also import all extractors and methods on TASTy Reflect
4444
trees. For example the `Literal(_)` extractor used below.
4545

4646
```scala
47-
def natConstImpl(x: Expr[Int])(implicit reflection: Reflection): Expr[Int] = {
48-
import reflection._
47+
def natConstImpl(x: Expr[Int]) given (qctx: QuoteContext): Expr[Int] = {
48+
import qctx.tasty._
4949
val xTree: Term = x.unseal
5050
xTree match {
5151
case Term.Literal(Constant.Int(n)) =>
@@ -58,10 +58,10 @@ def natConstImpl(x: Expr[Int])(implicit reflection: Reflection): Expr[Int] = {
5858
}
5959
```
6060

61-
To easily know which extractors are needed, the `reflection.Term.show` method
61+
To easily know which extractors are needed, the `qctx.tasty.Term.show` method
6262
returns the string representation of the extractors.
6363

64-
The method `reflection.Term.seal[T]` provides a way to go back to a
64+
The method `qctx.tasty.Term.seal[T]` provides a way to go back to a
6565
`quoted.Expr[Any]`. Note that the type is `Expr[Any]`. Consequently, the type
6666
must be set explicitly with a checked `cast` call. If the type does not conform
6767
to it an exception will be thrown. In the code above, we could have replaced
@@ -77,8 +77,8 @@ operation expression passed while calling the `macro` below.
7777
```scala
7878
inline def macro(param: => Boolean): Unit = ${ macroImpl('param) }
7979

80-
def macroImpl(param: Expr[Boolean])(implicit refl: Reflection): Expr[Unit] = {
81-
import refl._
80+
def macroImpl(param: Expr[Boolean]) given (qctx: QuoteContext): Expr[Unit] = {
81+
import qctx.tasty._
8282
import util._
8383

8484
param.unseal.underlyingArgument match {
@@ -99,8 +99,8 @@ such as the start line, the end line or even the source code at the expansion
9999
point.
100100

101101
```scala
102-
def macroImpl()(reflect: Reflection): Expr[Unit] = {
103-
import reflect.{Position => _, _}
102+
def macroImpl()(qctx: QuoteContext): Expr[Unit] = {
103+
import qctx.tasty._
104104
val pos = rootPosition
105105

106106
val path = pos.sourceFile.jpath.toString

library/src-3.x/scala/internal/quoted/Matcher.scala

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import scala.annotation.internal.sharable
44

55
import scala.quoted._
66
import scala.quoted.matching.Bind
7-
import scala.tasty._
87

98
object Matcher {
109

@@ -27,12 +26,11 @@ object Matcher {
2726
*
2827
* @param scrutineeExpr `Expr[_]` on which we are pattern matching
2928
* @param patternExpr `Expr[_]` containing the pattern tree
30-
* @param reflection instance of the reflection API (implicitly provided by the macro)
29+
* @param qctx the current QuoteContext
3130
* @return None if it did not match, `Some(tup)` if it matched where `tup` contains `Expr[Ti]``
3231
*/
33-
def unapply[Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], reflection: Reflection): Option[Tup] = {
34-
// TODO improve performance
35-
import reflection.{Bind => BindPattern, _}
32+
def unapply[Tup <: Tuple](scrutineeExpr: Expr[_])(implicit patternExpr: Expr[_], qctx: QuoteContext): Option[Tup] = {
33+
import qctx.tasty.{Bind => BindPattern, _}
3634
import Matching._
3735

3836
type Env = Set[(Symbol, Symbol)]

library/src-3.x/scala/quoted/Expr.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ package quoted {
4848
* Given list of statements `s1 :: s2 :: ... :: Nil` and an expression `e` the resulting expression
4949
* will be equivalent to `'{ $s1; $s2; ...; $e }`.
5050
*/
51-
def block[T](statements: List[Expr[_]], expr: Expr[T])(implicit refl: tasty.Reflection): Expr[T] = {
52-
import refl._
51+
def block[T](statements: List[Expr[_]], expr: Expr[T])(implicit qctx: QuoteContext): Expr[T] = {
52+
import qctx.tasty._
5353
Block(statements.map(_.unseal), expr.unseal).seal.asInstanceOf[Expr[T]]
5454
}
5555

library/src-3.x/scala/quoted/matching/Bind.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package scala.quoted
22
package matching
33

4-
import scala.tasty.Reflection // TODO do not depend on reflection directly
5-
64
/** Bind of an Expr[T] used to know if some Expr[T] is a reference to the binding
75
*
86
* @param name string name of this binding
@@ -21,8 +19,8 @@ class Bind[T <: AnyKind] private[scala](val name: String, private[Bind] val id:
2119

2220
object Bind {
2321

24-
def unapply[T](expr: Expr[T])(implicit reflect: Reflection): Option[Bind[T]] = {
25-
import reflect.{Bind => BindPattern, _}
22+
def unapply[T](expr: Expr[T]) given (qctx: QuoteContext): Option[Bind[T]] = {
23+
import qctx.tasty.{Bind => BindPattern, _}
2624
expr.unseal match {
2725
case IsIdent(ref) =>
2826
val sym = ref.symbol

library/src-3.x/scala/quoted/matching/Const.scala

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
package scala.quoted.matching
2-
3-
import scala.quoted.Expr
4-
5-
import scala.tasty.Reflection // TODO do not depend on reflection directly
1+
package scala.quoted
2+
package matching
63

74
/** Matches expressions containing literal constant values and extracts the value.
85
* It may match expressions of type Boolean, Byte, Short, Int, Long,
@@ -17,8 +14,8 @@ import scala.tasty.Reflection // TODO do not depend on reflection directly
1714
*/
1815
object Const {
1916

20-
def unapply[T](expr: Expr[T])(implicit reflect: Reflection): Option[T] = {
21-
import reflect._
17+
def unapply[T](expr: Expr[T]) given (qctx: QuoteContext): Option[T] = {
18+
import qctx.tasty._
2219
def rec(tree: Term): Option[T] = tree match {
2320
case Literal(c) => Some(c.value.asInstanceOf[T])
2421
case Block(Nil, e) => rec(e)

library/src-3.x/scala/quoted/matching/ConstSeq.scala

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
package scala.quoted.matching
2-
3-
import scala.quoted.Expr
4-
5-
import scala.tasty.Reflection // TODO do not depend on reflection directly
1+
package scala.quoted
2+
package matching
63

74
/** Literal sequence of literal constant value expressions */
85
object ConstSeq {
96

107
/** Matches literal sequence of literal constant value expressions */
11-
def unapply[T](expr: Expr[Seq[T]]) given Reflection: Option[Seq[T]] = expr match {
8+
def unapply[T](expr: Expr[Seq[T]]) given (qctx: QuoteContext): Option[Seq[T]] = expr match {
129
case ExprSeq(elems) =>
1310
elems.foldRight(Option(List.empty[T])) { (elem, acc) =>
1411
(elem, acc) match {

library/src-3.x/scala/quoted/matching/ExprSeq.scala

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
package scala.quoted.matching
2-
3-
import scala.quoted.Expr
4-
5-
import scala.tasty.Reflection // TODO do not depend on reflection directly
1+
package scala.quoted
2+
package matching
63

74
/** Literal sequence of expressions */
85
object ExprSeq {
96

107
/** Matches a literal sequence of expressions */
11-
def unapply[T](expr: Expr[Seq[T]])(implicit reflect: Reflection): Option[Seq[Expr[T]]] = {
12-
import reflect._
8+
def unapply[T](expr: Expr[Seq[T]]) given (qctx: QuoteContext): Option[Seq[Expr[T]]] = {
9+
import qctx.tasty._
1310
def rec(tree: Term): Option[Seq[Expr[T]]] = tree match {
1411
case Typed(Repeated(elems, _), _) => Some(elems.map(x => x.seal.asInstanceOf[Expr[T]]))
1512
case Block(Nil, e) => rec(e)

library/src-3.x/dotty/internal/StringContextMacro.scala renamed to library/src-bootstrapped/dotty/internal/StringContextMacro.scala

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
// ALWAYS KEEP THIS FILE IN src-bootstrapped, DO NOT MOVE TO src
2+
13
package dotty.internal
24

35
import scala.quoted._
46
import scala.quoted.matching._
5-
import scala.tasty.Reflection
67
import reflect._
78

89
object StringContextMacro {
@@ -58,7 +59,7 @@ object StringContextMacro {
5859
* @return the String contained in the given Expr
5960
* quotes an error if the given Expr does not contain a String
6061
*/
61-
private def literalToString(expression : Expr[String])(implicit reflect: Reflection) : String = expression match {
62+
private def literalToString(expression : Expr[String]) given (ctx: QuoteContext) : String = expression match {
6263
case Const(string : String) => string
6364
case _ => QuoteError("Expected statically known literal", expression)
6465
}
@@ -69,8 +70,7 @@ object StringContextMacro {
6970
* @return a list of Expr containing Strings, each corresponding to one parts of the given StringContext
7071
* quotes an error if the given Expr does not correspond to a StringContext
7172
*/
72-
def getPartsExprs(strCtxExpr : Expr[scala.StringContext])(implicit reflect : Reflection): List[Expr[String]] = {
73-
import reflect._
73+
def getPartsExprs(strCtxExpr : Expr[scala.StringContext]) given QuoteContext: List[Expr[String]] = {
7474
strCtxExpr match {
7575
case '{ StringContext(${ExprSeq(parts)}: _*) } => parts.toList
7676
case '{ new StringContext(${ExprSeq(parts)}: _*) } => parts.toList
@@ -84,8 +84,8 @@ object StringContextMacro {
8484
* @return a list of Expr containing arguments
8585
* quotes an error if the given Expr does not contain a list of arguments
8686
*/
87-
def getArgsExprs(argsExpr: Expr[Seq[Any]])(implicit reflect: Reflection): List[Expr[Any]] = {
88-
import reflect._
87+
def getArgsExprs(argsExpr: Expr[Seq[Any]]) given (qctx: QuoteContext): List[Expr[Any]] = {
88+
import qctx.tasty._
8989
argsExpr.unseal.underlyingArgument match {
9090
case Typed(Repeated(args, _), _) => args.map(_.seal)
9191
case tree => QuoteError("Expected statically known argument list", argsExpr)
@@ -98,8 +98,8 @@ object StringContextMacro {
9898
* @param args the Expr that holds the sequence of arguments to interpolate to the String in the correct format
9999
* @return the Expr containing the formatted and interpolated String or an error/warning if the parameters are not correct
100100
*/
101-
private def interpolate(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]])(implicit reflect: Reflection): Expr[String] = {
102-
import reflect._
101+
private def interpolate(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]]) given (qctx: QuoteContext): Expr[String] = {
102+
import qctx.tasty._
103103
val sourceFile = strCtxExpr.unseal.pos.sourceFile
104104

105105
val partsExpr = getPartsExprs(strCtxExpr)
@@ -111,27 +111,27 @@ object StringContextMacro {
111111
def partError(message : String, index : Int, offset : Int) : Unit = {
112112
reported = true
113113
val positionStart = partsExpr(index).unseal.pos.start + offset
114-
reflect.error(message, sourceFile, positionStart, positionStart)
114+
error(message, sourceFile, positionStart, positionStart)
115115
}
116116
def partWarning(message : String, index : Int, offset : Int) : Unit = {
117117
reported = true
118118
val positionStart = partsExpr(index).unseal.pos.start + offset
119-
reflect.warning(message, sourceFile, positionStart, positionStart)
119+
warning(message, sourceFile, positionStart, positionStart)
120120
}
121121

122122
def argError(message : String, index : Int) : Unit = {
123123
reported = true
124-
reflect.error(message, args(index).unseal.pos)
124+
error(message, args(index).unseal.pos)
125125
}
126126

127127
def strCtxError(message : String) : Unit = {
128128
reported = true
129129
val positionStart = strCtxExpr.unseal.pos.start
130-
reflect.error(message, sourceFile, positionStart, positionStart)
130+
error(message, sourceFile, positionStart, positionStart)
131131
}
132132
def argsError(message : String) : Unit = {
133133
reported = true
134-
reflect.error(message, argsExpr.unseal.pos)
134+
error(message, argsExpr.unseal.pos)
135135
}
136136

137137
def hasReported() : Boolean = {
@@ -158,8 +158,8 @@ object StringContextMacro {
158158
* @param reporter the reporter to return any error/warning when a problem is encountered
159159
* @return the Expr containing the formatted and interpolated String or an error/warning report if the parameters are not correct
160160
*/
161-
def interpolate(partsExpr : List[Expr[String]], args : List[Expr[Any]], argsExpr: Expr[Seq[Any]], reporter : Reporter)(implicit reflect: Reflection) : Expr[String] = {
162-
import reflect._
161+
def interpolate(partsExpr : List[Expr[String]], args : List[Expr[Any]], argsExpr: Expr[Seq[Any]], reporter : Reporter) given (qctx: QuoteContext) : Expr[String] = {
162+
import qctx.tasty._
163163

164164
/** Checks if the number of arguments are the same as the number of formatting strings
165165
*
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package scala.testing
22

33
import scala.quoted._
4-
import scala.tasty.Reflection
54

65
inline def typeChecks(inline code: String): Boolean = ${ typeChecksImpl(code) }
76

8-
private def typeChecksImpl(code: String)(implicit reflect: Reflection): Expr[Boolean] = {
9-
import reflect._
7+
private def typeChecksImpl(code: String) given (qctx: QuoteContext): Expr[Boolean] = {
8+
import qctx.tasty._
109
typing.typeChecks(code).toExpr
1110
}
12-
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// ALWAYS KEEP THIS FILE IN src-non-bootstrapped
2+
3+
package dotty.internal
4+
5+
import scala.quoted._
6+
import scala.quoted.matching._
7+
import scala.tasty.Reflection
8+
import reflect._
9+
10+
object StringContextMacro {
11+
12+
/** Implementation of scala.StringContext.f used in Dotty */
13+
inline def f(sc: => StringContext)(args: Any*): String =
14+
scala.compiletime.error("Cannot expand f interpolator while bootstrapping the compiler")
15+
16+
}

0 commit comments

Comments
 (0)