From 69ba4be50e832645f894669e863687538939aec1 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 2 Jul 2019 17:21:42 +0200 Subject: [PATCH 1/2] Perform full check that a the contents of a macro are valid in PrepareInlineable Avoid check duplication --- .../dotc/transform/PCPCheckAndHeal.scala | 19 ++++--------------- .../tools/dotc/typer/PrepareInlineable.scala | 9 +++++++-- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index c9c96635d7c1..4eba2e96e79e 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -54,7 +54,10 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( * - If inside of a macro definition, check the validity of the macro. */ protected def transformSplice(body: Tree, splice: Tree)(implicit ctx: Context): Tree = { - if (level >= 1) { + if (level < 0) { + ctx.error(s"Splice at level $level is not allowed", splice.sourcePos) + splice + } else { val body1 = transform(body)(spliceContext) splice match { case Apply(fun: TypeApply, _) if splice.isTerm => @@ -65,20 +68,6 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( case splice: Select => cpy.Select(splice)(body1, splice.name) } } - else { - assert(enclosingInlineds.isEmpty, "unexpanded macro") - assert(ctx.owner.isInlineMethod) - if (Splicer.canBeSpliced(body)) { // level 0 inside an inline definition - transform(body)(spliceContext) // Just check PCP - splice - } - else { // level 0 inside an inline definition - ctx.error( - "Malformed macro call. The contents of the splice ${...} must call a static method and arguments must be quoted or inline.", - splice.sourcePos) - splice - } - } } /** If `tree` refers to a locally defined symbol (either directly, or in a pickled type), diff --git a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala index 97ebf77b5fca..e74a2c3b3442 100644 --- a/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala +++ b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala @@ -251,9 +251,14 @@ object PrepareInlineable { */ object InlineSplice { def unapply(tree: Tree)(implicit ctx: Context): Option[Tree] = tree match { - case Spliced(code) if Splicer.canBeSpliced(code) => - if (code.symbol.flags.is(Inline)) + case Spliced(code) => + if (!Splicer.canBeSpliced(code)) { + ctx.error( + "Malformed macro call. The contents of the splice ${...} must call a static method and arguments must be quoted or inline.", + tree.sourcePos) + } else if (code.symbol.flags.is(Inline)) { ctx.error("Macro cannot be implemented with an `inline` method", code.sourcePos) + } Some(code) case Block(List(stat), Literal(Constants.Constant(()))) => unapply(stat) case Block(Nil, expr) => unapply(expr) From e54c112585cf6aa9ee0bdd3402062e266872d6cb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 2 Jul 2019 17:28:29 +0200 Subject: [PATCH 2/2] Remove unnecessary warining All splices at level -1 or lower are now caught by typer --- .../dotc/transform/PCPCheckAndHeal.scala | 21 +++++++------------ .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index 4eba2e96e79e..d321c12b6b8d 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -54,19 +54,14 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages( * - If inside of a macro definition, check the validity of the macro. */ protected def transformSplice(body: Tree, splice: Tree)(implicit ctx: Context): Tree = { - if (level < 0) { - ctx.error(s"Splice at level $level is not allowed", splice.sourcePos) - splice - } else { - val body1 = transform(body)(spliceContext) - splice match { - case Apply(fun: TypeApply, _) if splice.isTerm => - // Type of the splice itsel must also be healed - // internal.Quoted.expr[F[T]](... T ...) --> internal.Quoted.expr[F[$t]](... T ...) - val tp = checkType(splice.sourcePos).apply(splice.tpe.widenTermRefExpr) - cpy.Apply(splice)(cpy.TypeApply(fun)(fun.fun, tpd.TypeTree(tp) :: Nil), body1 :: Nil) - case splice: Select => cpy.Select(splice)(body1, splice.name) - } + val body1 = transform(body)(spliceContext) + splice match { + case Apply(fun: TypeApply, _) if splice.isTerm => + // Type of the splice itsel must also be healed + // internal.Quoted.expr[F[T]](... T ...) --> internal.Quoted.expr[F[$t]](... T ...) + val tp = checkType(splice.sourcePos).apply(splice.tpe.widenTermRefExpr) + cpy.Apply(splice)(cpy.TypeApply(fun)(fun.fun, tpd.TypeTree(tp) :: Nil), body1 :: Nil) + case splice: Select => cpy.Select(splice)(body1, splice.name) } } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 807cda83bde1..4cdd973788ae 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2263,7 +2263,7 @@ class Typer extends Namer ctx.error("Splice ${...} outside quotes '{...} or inline method", tree.sourcePos) else if (level < 0) ctx.error( - """Splice ${...} at level -1. + s"""Splice $${...} at level $level. | |Inline method may contain a splice at level 0 but the contents of this splice cannot have a splice. |""".stripMargin, tree.sourcePos