Skip to content

Commit f8e337d

Browse files
committed
Do not allow running Expr that came as macro arguments
It is too hard to ensure that the contents of the tree can be pickled. It would be posible but the current ad-hoc solution is too brittle and has no good usecases.
1 parent 6876240 commit f8e337d

File tree

12 files changed

+13
-68
lines changed

12 files changed

+13
-68
lines changed

compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,6 @@ object PickledQuotes {
2323

2424
/** Pickle the tree of the quoted.Expr */
2525
def pickleExpr(tree: Tree)(implicit ctx: Context): scala.quoted.Expr[Any] = {
26-
// Check that there are no free variables
27-
new TreeTraverser {
28-
private val definedHere = scala.collection.mutable.Set.empty[Symbol]
29-
def traverse(tree: tpd.Tree)(implicit ctx: Context): Unit = tree match {
30-
case tree: Ident if tree.symbol.exists && !definedHere(tree.symbol) =>
31-
throw new scala.quoted.FreeVariableError(tree.name.toString)
32-
case tree: DefTree =>
33-
definedHere += tree.symbol
34-
traverseChildren(tree)
35-
case _ =>
36-
traverseChildren(tree)
37-
}
38-
}.traverse(tree)
3926
val pickled = pickleQuote(tree)
4027
scala.runtime.quoted.Unpickler.unpickleExpr(pickled, Nil)
4128
}
@@ -64,7 +51,7 @@ object PickledQuotes {
6451
case value: Class[_] => ref(defn.Predef_classOf).appliedToType(classToType(value))
6552
case value => Literal(Constant(value))
6653
}
67-
case expr: TreeExpr[Tree] @unchecked => expr.tree
54+
case expr: TastyTreeExpr[Tree] @unchecked => expr.tree
6855
case expr: FunctionAppliedTo[_, _] =>
6956
functionAppliedTo(quotedExprToTree(expr.f), quotedExprToTree(expr.x))
7057
}

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import config.Config
2222
import core.quoted.PickledQuotes
2323
import scala.quoted
2424
import scala.quoted.Types.TreeType
25-
import scala.quoted.Exprs.TreeExpr
25+
import scala.quoted.Exprs.TastyTreeExpr
2626

2727
/** Unpickler for typed trees
2828
* @param reader the reader from which to unpickle
@@ -1150,7 +1150,7 @@ class TreeUnpickler(reader: TastyReader,
11501150
val args = until(end)(readTerm())
11511151
val splice = splices(idx)
11521152
def wrap(arg: Tree) =
1153-
if (arg.isTerm) new TreeExpr(arg, PickledQuotes.pickleExpr(arg))
1153+
if (arg.isTerm) new TastyTreeExpr(arg)
11541154
else new TreeType(arg)
11551155
val reifiedArgs = args.map(wrap)
11561156
if (isType) {

compiler/src/dotty/tools/dotc/quoted/Toolbox.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import dotty.tools.dotc.printing.RefinedPrinter
66

77
import scala.quoted.Expr
88
import scala.runtime.BoxedUnit
9-
import scala.quoted.Exprs.{LiftedExpr, TreeExpr}
9+
import scala.quoted.Exprs.{LiftedExpr, TastyTreeExpr}
1010
import scala.runtime.quoted._
1111

1212
/** Default runners for quoted expressions */
@@ -24,8 +24,8 @@ object Toolbox {
2424
def run(expr: Expr[T]): T = expr match {
2525
case expr: LiftedExpr[T] =>
2626
expr.value
27-
case expr: TreeExpr[Tree] @unchecked =>
28-
new QuoteDriver().run(expr.pickled, runSettings)
27+
case expr: TastyTreeExpr[Tree] @unchecked =>
28+
throw new scala.quoted.QuoteError("Can't run and scala.quoted.Expr coming from a macro argument")
2929
case _ =>
3030
new QuoteDriver().run(expr, runSettings)
3131
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ object Splicer {
6767
assert(!tp.hasAnnotation(defn.InlineParamAnnot))
6868
// Replace argument by its binding
6969
val arg1 = bindMap.getOrElse(arg, arg)
70-
new scala.quoted.Exprs.TreeExpr(arg1, PickledQuotes.pickleExpr(arg1))
70+
new scala.quoted.Exprs.TastyTreeExpr(arg1)
7171
}
7272
args1 ::: liftArgs(tp.resType, args.tail)
7373
case tp: PolyType =>

library/src/scala/quoted/Expr.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ object Expr {
3333
object Exprs {
3434
/** An Expr backed by a pickled TASTY tree */
3535
final class TastyExpr[T](val tasty: Pickled, val args: Seq[Any]) extends Expr[T] {
36-
override def toString: String = s"Expr(<pickled>)"
36+
override def toString: String = s"Expr(<pickled tasty>)"
3737
}
3838

3939
/** An Expr backed by a lifted value.
@@ -50,9 +50,8 @@ object Exprs {
5050
*
5151
* May contain references to code defined outside this Expr instance.
5252
*/
53-
final class TreeExpr[Tree](val tree: Tree, pickle: => Expr[_]) extends quoted.Expr[Any] {
54-
def pickled[T]: Expr[T] = pickle.asInstanceOf[Expr[T]]
55-
override def toString: String = s"Expr(<raw>)"
53+
final class TastyTreeExpr[Tree](val tree: Tree) extends quoted.Expr[Any] {
54+
override def toString: String = s"Expr(<tasty tree>)"
5655
}
5756

5857
/** An Expr representing `'{(~f).apply(~x)}` but it is beta-reduced when the closure is known */

library/src/scala/quoted/FreeVariableError.scala

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/run/quote-run-in-macro-1/quoted_2.scala renamed to tests/neg/quote-run-in-macro-2/quoted_2.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import Macros._
22
object Test {
33
def main(args: Array[String]): Unit = {
4-
println(foo(1))
5-
println(foo(1 + 3))
4+
println(foo(1)) // error
5+
println(foo(1 + 3)) // error
66
val x = 3
7-
println(foo {
7+
println(foo { // error
88
val x = 5
99
x
1010
})

tests/run/quote-run-in-macro-1.check

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/run/quote-run-in-macro-2.check

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/run/quote-run-in-macro-2/quoted_1.scala

Lines changed: 0 additions & 18 deletions
This file was deleted.

tests/run/quote-run-in-macro-2/quoted_2.scala

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)