Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace quoted toExpr with Expr.apply #7267

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/reference/changed-features/numeric-literals.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ implementation method `fromDigitsImpl`. Here is its definition:
case Const(ds) =>
try {
val BigFloat(m, e) = apply(ds)
'{BigFloat(${m.toExpr}, ${e.toExpr})}
'{BigFloat(${Expr(m)}, ${Expr(e)})}
}
catch {
case ex: FromDigits.FromDigitsException =>
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/reference/metaprogramming/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ import given scala.quoted._

def compile(e: Exp, env: Map[String, Expr[Int]]): Expr[Int] = e match {
case Num(n) =>
n.toExpr
Expr(n)
case Plus(e1, e2) =>
'{ ${ compile(e1, env) } + ${ compile(e2, env) } }
case Var(x) =>
Expand All @@ -241,7 +241,7 @@ Running `compile(letExp, Map())` would yield the following Scala code:
```scala
'{ val y = 3; (2 + y) + 4 }
```
The body of the first clause, `case Num(n) => n.toExpr`, looks suspicious. `n`
The body of the first clause, `case Num(n) => Expr(n)`, looks suspicious. `n`
is declared as an `Int`, yet it is converted to an `Expr[Int]` with `toExpr`.
Shouldn’t `n` be quoted? In fact this would not
work since replacing `n` by `'n` in the clause would not be phase
Expand Down Expand Up @@ -308,7 +308,7 @@ Using lifting, we can now give the missing definition of `showExpr` in the intro
```scala
def showExpr[T](expr: Expr[T]): Expr[String] = {
val code: String = expr.show
code.toExpr
Expr(code)
}
```
That is, the `showExpr` method converts its `Expr` argument to a string (`code`), and lifts
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/reference/metaprogramming/tasty-reflect.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ The method `qctx.tasty.Term.seal[T]` provides a way to go back to a
`quoted.Expr[Any]`. Note that the type is `Expr[Any]`. Consequently, the type
must be set explicitly with a checked `cast` call. If the type does not conform
to it an exception will be thrown. In the code above, we could have replaced
`n.toExpr` by `xTree.seal.cast[Int]`.
`Expr(n)` by `xTree.seal.cast[Int]`.

### Obtaining the underlying argument

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,6 @@ object StringContextMacro {
}

// macro expansion
'{(${parts.mkString.toExpr}).format(${argsExpr}: _*)}
'{(${Expr(parts.mkString)}).format(${argsExpr}: _*)}
}
}
80 changes: 40 additions & 40 deletions library/src-bootstrapped/scala/quoted/Liftable.scala

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion library/src-bootstrapped/scala/quoted/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package scala
package object quoted {

implicit object ExprOps {
def (x: T) toExpr[T: Liftable](given QuoteContext): Expr[T] = summon[Liftable[T]].toExpr(x)
@deprecated("Use scala.quoted.Expr.apply instead", "0.19.0")
def (x: T) toExpr[T: Liftable](given QuoteContext): Expr[T] = Expr(x)
}
}
3 changes: 3 additions & 0 deletions library/src/scala/quoted/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ package quoted {
Block(statements.map(_.unseal), expr.unseal).seal.asInstanceOf[Expr[T]]
}

/** Lift a value into an expression containing the construction of that value */
def apply[T: Liftable](x: T)(given QuoteContext): Expr[T] = summon[Liftable[T]].toExpr(x)

/** Lifts this sequence of expressions into an expression of a sequence
*
* Transforms a sequence of expression
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/quoted/autolift.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package scala.quoted
/** Enable implicit conversion from a term of type `T` to an expression of type `Expr[T]` */
object autolift {
/** Implicit conversion from a term of type `T` to an expression of type `Expr[T]` */
given autoToExpr[T](given Liftable[T], QuoteContext): Conversion[T, Expr[T]] = _.toExpr
given autoToExpr[T](given Liftable[T], QuoteContext): Conversion[T, Expr[T]] = Expr(_)
}
2 changes: 1 addition & 1 deletion tests/disabled/pos/quote-whitebox/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ object Macro {

inline def charOrString(inline str: String) <: Char | String = ${ impl(str) }

def impl(str: String) = if (str.length == 1) str.charAt(0).toExpr else str.toExpr
def impl(str: String) = if (str.length == 1) Expr(str.charAt(0)) else Expr(str)

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object Even {
ctx.error(ex.getMessage)
Even(0)
}
'{Even(${ev.n.toExpr})}
'{Even(${Expr(ev.n)})}
case _ =>
'{evenFromDigits($digits)}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-macros/inline-case-objects/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import scala.quoted._

object Macros {
def impl(foo: Any)(given QuoteContext): Expr[String] = foo.getClass.getCanonicalName.toExpr
def impl(foo: Any)(given QuoteContext): Expr[String] = Expr(foo.getClass.getCanonicalName)
}

class Bar {
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-macros/inline-option/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import scala.quoted._

object Macro {
def impl(opt: Option[Int])(given QuoteContext): Expr[Int] = opt match {
case Some(i) => i.toExpr
case Some(i) => Expr(i)
case None => '{-1}
}
}
2 changes: 1 addition & 1 deletion tests/neg-macros/quote-macro-complex-arg-0.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import scala.quoted._

object Macros {
inline def foo(inline i: Int, dummy: Int, j: Int): Int = ${ bar(i + 1, 'j) } // error: i + 1 is not a parameter or field reference
def bar(x: Int, y: Expr[Int])(given QuoteContext): Expr[Int] = '{ ${x.toExpr} + $y }
def bar(x: Int, y: Expr[Int])(given QuoteContext): Expr[Int] = '{ ${Expr(x)} + $y }
}
2 changes: 1 addition & 1 deletion tests/neg-with-compiler/GenericNumLits/Even_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object Even {
ctx.error(ex.getMessage)
Even(0)
}
'{Even(${ev.n.toExpr})}
'{Even(${Expr(ev.n)})}
case _ =>
'{evenFromDigits($digits)}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/neg/BigFloat/BigFloat_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object BigFloat extends App {
case Const(ds) =>
try {
val BigFloat(m, e) = apply(ds)
'{BigFloat(${m.toExpr}, ${e.toExpr})}
'{BigFloat(${Expr(m)}, ${Expr(e)})}
}
catch {
case ex: FromDigits.FromDigitsException =>
Expand All @@ -60,7 +60,7 @@ object BigFloat extends App {

given Liftable[BigInt] {
def toExpr(x: BigInt) =
'{BigInt(${x.toString.toExpr})}
'{BigInt(${Expr(x.toString)})}
}
}

5 changes: 2 additions & 3 deletions tests/pending/pos/i4987.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ object Foo {

implicit def NilIsLiftable: Liftable[Nil.type] = ???

Nil.toExpr(NilIsLiftable)
(Nil.toExpr: Expr[Nil.type])
Nil.toExpr
Expr(Nil)(given NilIsLiftable)
Expr(Nil)
}
2 changes: 1 addition & 1 deletion tests/pos-macros/quote-whitebox-2/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ object Macro {

inline def charOrString(inline str: String) <: Any = ${ impl(str) }

def impl(str: String)(given QuoteContext) = if (str.length == 1) str.charAt(0).toExpr else str.toExpr
def impl(str: String)(given QuoteContext) = if (str.length == 1) Expr(str.charAt(0)) else Expr(str)

}
2 changes: 1 addition & 1 deletion tests/pos/i5547.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ object scalatest {
${assertImpl('condition, '{""})}

inline def assert2(condition: => Boolean): Unit =
${ assertImpl('condition, "".toExpr) }
${ assertImpl('condition, Expr("")) }

def assertImpl(condition: Expr[Boolean], clue: Expr[Any])(given QuoteContext): Expr[Unit] =
'{}
Expand Down
2 changes: 1 addition & 1 deletion tests/pos/i6214.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import scala.quoted._
object Test {
def res(x: quoted.Expr[Int])(given QuoteContext): quoted.Expr[Int] = x match {
case '{ val a: Int = $y; 1} => y // owner of `y` is `res`
case _ => '{ val b: Int = ${val c = 2; c.toExpr}; 1} // owner of `c` is `b`, but that seems to be OK
case _ => '{ val b: Int = ${val c = 2; Expr(c)}; 1} // owner of `c` is `b`, but that seems to be OK
}
}
2 changes: 1 addition & 1 deletion tests/pos/quote-lift.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object Test {

'{ ${summon[Liftable[Int]].toExpr(1)} }

'{ ${1.toExpr} }
'{ ${Expr(1)} }

}

Expand Down
22 changes: 11 additions & 11 deletions tests/pos/quote-liftable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ def test(given QuoteContext) = {

implicit def ListIsLiftable[T: Liftable: Type]: Liftable[List[T]] = new {
def toExpr(xs: List[T]) = xs match {
case x :: xs1 => '{ ${ implicitly[Liftable[T]].toExpr(x) } :: ${ toExpr(xs1) } }
case x :: xs1 => '{ ${ Expr(x) } :: ${ toExpr(xs1) } }
case Nil => '{Nil: List[T]}
}
}

true.toExpr
1.toExpr
'a'.toExpr
1.toExpr
1.toExpr
1L.toExpr
1.0f.toExpr
1.0.toExpr
"abc".toExpr
Expr(true)
Expr(1)
Expr('a')
Expr(1)
Expr(1)
Expr(1L)
Expr(1.0f)
Expr(1.0)
Expr("abc")

val xs: Expr[List[Int]] = (1 :: 2 :: 3 :: Nil).toExpr
val xs: Expr[List[Int]] = Expr(1 :: 2 :: 3 :: Nil)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ object Foo {
import qctx.tasty._

def definitionString(tree: Tree): Expr[String] = tree.symbol match {
case IsClassDefSymbol(sym) => sym.tree.showExtractors.toExpr
case IsDefDefSymbol(sym) => sym.tree.showExtractors.toExpr
case IsValDefSymbol(sym) => sym.tree.showExtractors.toExpr
case IsClassDefSymbol(sym) => Expr(sym.tree.showExtractors)
case IsDefDefSymbol(sym) => Expr(sym.tree.showExtractors)
case IsValDefSymbol(sym) => Expr(sym.tree.showExtractors)
case _ => '{"NO DEFINTION"}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ object Foo {
import qctx.tasty._

def definitionString(tree: Tree): Expr[String] = tree.symbol match {
case IsClassDefSymbol(sym) => sym.tree.showExtractors.toExpr
case IsDefDefSymbol(sym) => sym.tree.showExtractors.toExpr
case IsValDefSymbol(sym) => sym.tree.showExtractors.toExpr
case IsClassDefSymbol(sym) => Expr(sym.tree.showExtractors)
case IsDefDefSymbol(sym) => Expr(sym.tree.showExtractors)
case IsValDefSymbol(sym) => Expr(sym.tree.showExtractors)
case _ => '{"NO DEFINTION"}
}

Expand Down
28 changes: 14 additions & 14 deletions tests/run-macros/gestalt-type-toolbox-reflect/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ object TypeToolbox {
private def tpEqImpl[A, B](a: Type[A], b: Type[B])(given qctx: QuoteContext): Expr[Boolean] = {
import qctx.tasty._
val res = a.unseal.tpe =:= b.unseal.tpe
res.toExpr
Expr(res)
}

/** is `tp1` a subtype of `tp2` */
inline def <:<[A, B]: Boolean = ${tpLEqImpl('[A], '[B])}
private def tpLEqImpl[A, B](a: Type[A], b: Type[B])(given qctx: QuoteContext): Expr[Boolean] = {
import qctx.tasty._
val res = a.unseal.tpe <:< b.unseal.tpe
res.toExpr
Expr(res)
}

/** type associated with the tree */
inline def typeOf[T, Expected](a: T): Boolean = ${typeOfImpl('a, '[Expected])}
private def typeOfImpl(a: Expr[_], expected: Type[_])(given qctx: QuoteContext): Expr[Boolean] = {
import qctx.tasty._
val res = a.unseal.tpe =:= expected.unseal.tpe
res.toExpr
Expr(res)
}

/** does the type refer to a case class? */
Expand All @@ -36,67 +36,67 @@ object TypeToolbox {
case IsClassDefSymbol(sym) => sym.flags.is(Flags.Case)
case _ => false
}
res.toExpr
Expr(res)
}

/** val fields of a case class Type -- only the ones declared in primary constructor */
inline def caseFields[T]: List[String] = ${caseFieldsImpl('[T])}
private def caseFieldsImpl(tp: Type[_])(given qctx: QuoteContext): Expr[List[String]] = {
import qctx.tasty._
val fields = tp.unseal.symbol.asClassDef.caseFields.map(_.name)
fields.toExpr
Expr(fields)
}

inline def fieldIn[T](inline mem: String): String = ${fieldInImpl('[T], mem)}
private def fieldInImpl(t: Type[_], mem: String)(given qctx: QuoteContext): Expr[String] = {
import qctx.tasty._
val field = t.unseal.symbol.asClassDef.field(mem)
field.map(_.name).getOrElse("").toExpr
Expr(field.map(_.name).getOrElse(""))
}

inline def fieldsIn[T]: Seq[String] = ${fieldsInImpl('[T])}
private def fieldsInImpl(t: Type[_])(given qctx: QuoteContext): Expr[Seq[String]] = {
import qctx.tasty._
val fields = t.unseal.symbol.asClassDef.fields
fields.map(_.name).toList.toExpr
Expr(fields.map(_.name).toList)
}

inline def methodIn[T](inline mem: String): Seq[String] = ${methodInImpl('[T], mem)}
private def methodInImpl(t: Type[_], mem: String)(given qctx: QuoteContext): Expr[Seq[String]] = {
import qctx.tasty._
t.unseal.symbol.asClassDef.classMethod(mem).map(_.name).toExpr
Expr(t.unseal.symbol.asClassDef.classMethod(mem).map(_.name))
}

inline def methodsIn[T]: Seq[String] = ${methodsInImpl('[T])}
private def methodsInImpl(t: Type[_])(given qctx: QuoteContext): Expr[Seq[String]] = {
import qctx.tasty._
t.unseal.symbol.asClassDef.classMethods.map(_.name).toExpr
Expr(t.unseal.symbol.asClassDef.classMethods.map(_.name))
}

inline def method[T](inline mem: String): Seq[String] = ${methodImpl('[T], mem)}
private def methodImpl(t: Type[_], mem: String)(given qctx: QuoteContext): Expr[Seq[String]] = {
import qctx.tasty._
t.unseal.symbol.asClassDef.method(mem).map(_.name).toExpr
Expr(t.unseal.symbol.asClassDef.method(mem).map(_.name))
}

inline def methods[T]: Seq[String] = ${methodsImpl('[T])}
private def methodsImpl(t: Type[_])(given qctx: QuoteContext): Expr[Seq[String]] = {
import qctx.tasty._
t.unseal.symbol.asClassDef.methods.map(_.name).toExpr
Expr(t.unseal.symbol.asClassDef.methods.map(_.name))
}

inline def typeTag[T](x: T): String = ${typeTagImpl('[T])}
private def typeTagImpl(tp: Type[_])(given qctx: QuoteContext): Expr[String] = {
import qctx.tasty._
val res = tp.unseal.tpe.show
res.toExpr
Expr(res)
}

inline def companion[T1, T2]: Boolean = ${companionImpl('[T1], '[T2])}
private def companionImpl(t1: Type[_], t2: Type[_])(given qctx: QuoteContext): Expr[Boolean] = {
import qctx.tasty._
val res = t1.unseal.symbol.asClassDef.companionModule.contains(t2.unseal.symbol)
res.toExpr
Expr(res)
}

inline def companionName[T1]: String = ${companionNameImpl('[T1])}
Expand All @@ -107,7 +107,7 @@ object TypeToolbox {
case IsValDefSymbol(sym) => sym.companionClass
case _ => None
}
companionClassOpt.map(_.fullName).getOrElse("").toExpr
Expr(companionClassOpt.map(_.fullName).getOrElse(""))
}

}
2 changes: 1 addition & 1 deletion tests/run-macros/i5629/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ object Macros {

def thisLineNumberImpl(given qctx: QuoteContext): Expr[Int] = {
import qctx.tasty._
rootPosition.startLine.toExpr
Expr(rootPosition.startLine)
}
}
2 changes: 1 addition & 1 deletion tests/run-macros/i6765-b/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ inline def foo = ${fooImpl}

def fooImpl(given qctx: QuoteContext) = {
val res = Expr.ofList(List('{"One"}))
res.show.toExpr
Expr(res.show)
}
Loading