Skip to content

Commit 222516a

Browse files
Merge pull request #4101 from dotty-staging/quote-error-reporting
Add error reporter for inlined quotes
2 parents 14c5af6 + 345a808 commit 222516a

File tree

7 files changed

+61
-2
lines changed

7 files changed

+61
-2
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
336336
}
337337

338338
val tree1 =
339-
if (level == 0) cpy.Inlined(tree)(call, stagedBindings, Splicer.splice(seq(splicedBindings, body)))
339+
if (level == 0) cpy.Inlined(tree)(call, stagedBindings, Splicer.splice(seq(splicedBindings, body).withPos(tree.pos)))
340340
else seq(stagedBindings, cpy.Select(expansion)(cpy.Inlined(tree)(call, splicedBindings, body), name))
341341
val tree2 = transform(tree1)
342342

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@ package transform
33

44
import dotty.tools.dotc.ast.tpd
55
import dotty.tools.dotc.core.Contexts._
6+
import dotty.tools.dotc.core.Decorators._
67
import dotty.tools.dotc.core.quoted._
78
import dotty.tools.dotc.interpreter._
89

10+
import scala.util.control.NonFatal
11+
12+
import java.lang.reflect.InvocationTargetException
13+
914
/** Utility class to splice quoted expressions */
1015
object Splicer {
1116
import tpd._
@@ -22,7 +27,22 @@ object Splicer {
2227
/** Splice the Tree for a Quoted expression which is constructed via a reflective call to the given method */
2328
private def reflectiveSplice(tree: Tree)(implicit ctx: Context): Tree = {
2429
val interpreter = new Interpreter
25-
interpreter.interpretTree[scala.quoted.Expr[_]](tree).map(PickledQuotes.quotedExprToTree).getOrElse(tree)
30+
val interpreted =
31+
try interpreter.interpretTree[scala.quoted.Expr[_]](tree)
32+
catch { case ex: InvocationTargetException => handleTargetException(tree, ex); None }
33+
interpreted.fold(tree)(PickledQuotes.quotedExprToTree)
34+
}
35+
36+
private def handleTargetException(tree: Tree, ex: InvocationTargetException)(implicit ctx: Context): Unit = ex.getCause match {
37+
case ex: scala.quoted.QuoteError => ctx.error(ex.getMessage, tree.pos)
38+
case NonFatal(ex) =>
39+
val msg =
40+
s"""Failed to evaluate inlined quote.
41+
| Caused by: ${ex.getMessage}
42+
| ${ex.getStackTrace.takeWhile(_.getClassName != "sun.reflect.NativeMethodAccessorImpl").mkString("\n ")}
43+
""".stripMargin
44+
ctx.error(msg, tree.pos)
45+
case _ => throw ex
2646
}
2747

2848
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package scala.quoted
2+
3+
/** Throwing this error in the implementation of an inline macro
4+
* will result in a compilation error with the given message.
5+
*/
6+
class QuoteError(message: String) extends Throwable(message)
7+
8+
object QuoteError {
9+
/** Throws a QuoteError with the given message */
10+
def apply(message: => String): Nothing = throw new QuoteError(message)
11+
}

tests/neg/quote-error/Macro_1.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
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+
if (b) '(println("foo(true)"))
7+
else QuoteError("foo cannot be called with false")
8+
}

tests/neg/quote-error/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+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
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+
if (b) '(println("foo(true)"))
7+
else ???
8+
}
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: Failed to evaluate inlined quote. Caused by: an implementation is missing
6+
}

0 commit comments

Comments
 (0)