@@ -7,6 +7,7 @@ import Trees._
77import core ._
88import Flags ._
99import Symbols ._
10+ import Flags ._
1011import Types ._
1112import Decorators ._
1213import NameKinds ._
@@ -246,24 +247,32 @@ object PrepareInlineable {
246247 def checkInlineMacro (sym : Symbol , rhs : Tree , pos : SourcePosition )(implicit ctx : Context ) = {
247248 if (! ctx.isAfterTyper) {
248249
249- /** InlineSplice is used to detect cases where the expansion
250- * consists of a (possibly multiple & nested) block or a sole expression.
251- */
250+
252251 object InlineSplice {
253- def unapply (tree : Tree )(implicit ctx : Context ): Option [ Tree ] = tree match {
252+ def unapply (tree : Tree )(implicit ctx : Context ): Boolean = tree match {
254253 case Spliced (code) =>
255- if (! Splicer .canBeSpliced(code)) {
256- ctx.error(
257- " Malformed macro call. The contents of the splice ${...} must call a static method and arguments must be quoted or inline." ,
258- tree.sourcePos)
259- } else if (code.symbol.flags.is(Inline )) {
254+ if (code.symbol.flags.is(Inline ))
260255 ctx.error(" Macro cannot be implemented with an `inline` method" , code.sourcePos)
261- }
262- Some (code)
256+ Splicer .checkValidMacroBody(code)
257+ true
263258 case Block (List (stat), Literal (Constants .Constant (()))) => unapply(stat)
264259 case Block (Nil , expr) => unapply(expr)
265260 case Typed (expr, _) => unapply(expr)
266- case _ => None
261+ case Block (DefDef (nme.ANON_FUN , _, _, _, _) :: Nil , Closure (_, fn, _)) if fn.symbol.info.isImplicitMethod =>
262+ // TODO Suppot this pattern
263+ ctx.error(" Macros using `given X => Y` return types are not yet supported" .stripMargin, tree.sourcePos)
264+ false
265+ case _ =>
266+ ctx.error(
267+ """ Malformed macro.
268+ |
269+ |Expected the splice ${...} to be at the top of the RHS:
270+ | inline def foo(inline x: X, ..., y: Y): Int = ${impl(x, ... '{y}})
271+ |
272+ | * The contents of the splice must call a static method
273+ | * All arguments must be quoted or inline
274+ """ .stripMargin, pos)
275+ false
267276 }
268277 }
269278
@@ -279,10 +288,24 @@ object PrepareInlineable {
279288
280289 if (isMacro) {
281290 sym.setFlag(Macro )
282- if (level == 0 )
283- rhs match {
284- case InlineSplice (_) =>
291+ if (level == 0 ) {
292+ def isValidMacro (tree : Tree )(implicit ctx : Context ): Unit = tree match {
293+ case Spliced (code) =>
294+ if (code.symbol.flags.is(Inline ))
295+ ctx.error(" Macro cannot be implemented with an `inline` method" , code.sourcePos)
296+ Splicer .checkValidMacroBody(code)
285297 new PCPCheckAndHeal (freshStagingContext).transform(rhs) // Ignore output, only check PCP
298+
299+ case Block (List (stat), Literal (Constants .Constant (()))) => isValidMacro(stat)
300+ case Block (Nil , expr) => isValidMacro(expr)
301+ case Typed (expr, _) => isValidMacro(expr)
302+ case Block (DefDef (nme.ANON_FUN , _, _, _, _) :: Nil , Closure (_, fn, _)) if fn.symbol.info.isImplicitMethod =>
303+ // TODO Suppot this pattern
304+ ctx.error(
305+ """ Macros using a return type of the form `foo(): given X => Y` are not yet supported.
306+ |
307+ |Place the implicit as an argument (`foo() given X: Y`) to overcome this limitation.
308+ |""" .stripMargin, tree.sourcePos)
286309 case _ =>
287310 ctx.error(
288311 """ Malformed macro.
@@ -294,6 +317,8 @@ object PrepareInlineable {
294317 | * All arguments must be quoted or inline
295318 """ .stripMargin, pos)
296319 }
320+ isValidMacro(rhs)
321+ }
297322 }
298323 }
299324 }
0 commit comments