Skip to content

Commit def8b69

Browse files
Merge pull request #4479 from dotty-staging/fix-QuoteError-in-splices
Handle QuotedError when evaluating holes in quotes
2 parents 96a8708 + 3c18715 commit def8b69

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ object Splicer {
3636
val liftedArgs = getLiftedArgs(call, bindings)
3737
val interpreter = new Interpreter(pos, classLoader)
3838
val interpreted = interpreter.interpretCallToSymbol[Seq[Any] => Object](call.symbol)
39-
interpreted.flatMap(lambda => evaluateLambda(lambda, liftedArgs, pos)).fold(tree)(PickledQuotes.quotedExprToTree)
39+
evaluateMacro(pos) {
40+
// Some parts of the macro are evaluated during the unpickling performed in quotedExprToTree
41+
val evaluated = interpreted.map(lambda => lambda(liftedArgs).asInstanceOf[scala.quoted.Expr[Nothing]])
42+
evaluated.fold(tree)(PickledQuotes.quotedExprToTree)
43+
}
4044
}
4145

4246
/** Given the inline code and bindings, compute the lifted arguments that will be used to execute the macro
@@ -73,20 +77,21 @@ object Splicer {
7377
liftArgs(call.symbol.info, allArgs(call, Nil))
7478
}
7579

76-
private def evaluateLambda(lambda: Seq[Any] => Object, args: Seq[Any], pos: Position)(implicit ctx: Context): Option[scala.quoted.Expr[Nothing]] = {
77-
try Some(lambda(args).asInstanceOf[scala.quoted.Expr[Nothing]])
80+
/* Evaluate the code in the macro and handle exceptions durring evaluation */
81+
private def evaluateMacro(pos: Position)(code: => Tree)(implicit ctx: Context): Tree = {
82+
try code
7883
catch {
7984
case ex: scala.quoted.QuoteError =>
8085
ctx.error(ex.getMessage, pos)
81-
None
86+
EmptyTree
8287
case NonFatal(ex) =>
8388
val msg =
8489
s"""Failed to evaluate inlined quote.
85-
| Caused by: ${ex.getMessage}
86-
| ${ex.getStackTrace.takeWhile(_.getClassName != "dotty.tools.dotc.transform.Splicer$").init.mkString("\n ")}
90+
| Caused by ${ex.getClass}: ${if (ex.getMessage == null) "" else ex.getMessage}
91+
| ${ex.getStackTrace.takeWhile(_.getClassName != "dotty.tools.dotc.transform.Splicer$").init.mkString("\n ")}
8792
""".stripMargin
8893
ctx.error(msg, pos)
89-
None
94+
EmptyTree
9095
}
9196
}
9297

tests/neg/quote-error-2/Macro_1.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import quoted._
2+
3+
object Macro_1 {
4+
inline def foo(inline b: Boolean): Unit = ~fooImpl(b)
5+
def fooImpl(b: Boolean): Expr[Unit] =
6+
'(println(~msg(b)))
7+
8+
def msg(b: Boolean): Expr[String] =
9+
if (b) '("foo(true)")
10+
else QuoteError("foo cannot be called with false")
11+
12+
}

tests/neg/quote-error-2/Test_2.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import Macro_1._
2+
3+
object Test_2 {
4+
foo(true)
5+
foo(false) // error: foo cannot be called with false
6+
}

0 commit comments

Comments
 (0)