@@ -5,7 +5,7 @@ import core._
5
5
import Decorators ._ , Flags ._ , Types ._ , Contexts ._ , Symbols ._ , Constants ._
6
6
import Flags ._
7
7
import ast .Trees ._
8
- import ast .{TreeTypeMap , untpd }
8
+ import ast .{TreeTypeMap , tpd , untpd }
9
9
import util .Positions ._
10
10
import tasty .TreePickler .Hole
11
11
import SymUtils ._
@@ -16,6 +16,7 @@ import typer.Implicits.SearchFailureType
16
16
import scala .collection .mutable
17
17
import dotty .tools .dotc .core .StdNames ._
18
18
import dotty .tools .dotc .core .quoted ._
19
+ import dotty .tools .dotc .util .SourcePosition
19
20
20
21
21
22
/** Translates quoted terms and types to `unpickle` method calls.
@@ -230,10 +231,6 @@ class ReifyQuotes extends MacroTransformWithImplicits {
230
231
! sym.is(Param ) || levelOK(sym.owner)
231
232
}
232
233
233
- /** Issue a "splice outside quote" error unless we are in the body of a transparent method */
234
- def spliceOutsideQuotes (pos : Position )(implicit ctx : Context ): Unit =
235
- ctx.error(i " splice outside quotes " , pos)
236
-
237
234
/** Try to heal phase-inconsistent reference to type `T` using a local type definition.
238
235
* @return None if successful
239
236
* @return Some(msg) if unsuccessful where `msg` is a potentially empty error message
@@ -292,7 +289,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
292
289
outer.checkType(pos).foldOver(acc, tp)
293
290
}
294
291
else {
295
- if (tp.isTerm) spliceOutsideQuotes( pos)
292
+ if (tp.isTerm) ctx.error( i " splice outside quotes " , pos)
296
293
tp
297
294
}
298
295
case tp : NamedType =>
@@ -418,14 +415,28 @@ class ReifyQuotes extends MacroTransformWithImplicits {
418
415
val body1 = nested(isQuote = false ).transform(splice.qualifier)
419
416
body1.select(splice.name)
420
417
}
421
- else if (! inQuote && level == 0 && ! ctx.owner.is(Transparent )) {
422
- spliceOutsideQuotes(splice.pos)
423
- splice
424
- }
425
- else {
418
+ else if (level == 1 ) {
426
419
val (body1, quotes) = nested(isQuote = false ).split(splice.qualifier)
427
420
makeHole(body1, quotes, splice.tpe).withPos(splice.pos)
428
421
}
422
+ else if (enclosingInlineds.nonEmpty) { // level 0 in an inline call
423
+ val spliceCtx = ctx.outer // drop the last `inlineContext`
424
+ val pos : SourcePosition = Decorators .sourcePos(enclosingInlineds.head.pos)(spliceCtx)
425
+ val evaluatedSplice = Splicer .splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPos(splice.pos)
426
+ if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice)
427
+ }
428
+ else if (! ctx.owner.ownersIterator.exists(_.is(Transparent ))) { // level 0 outside a transparent definition
429
+ ctx.error(i " splice outside quotes or transparent method " , splice.pos)
430
+ splice
431
+ }
432
+ else if (Splicer .canBeSpliced(splice.qualifier)) { // level 0 inside a transparent definition
433
+ nested(isQuote = false ).split(splice.qualifier) // Just check PCP
434
+ splice
435
+ }
436
+ else { // level 0 inside a transparent definition
437
+ ctx.error(" Malformed macro call. The contents of the ~ must call a static method and arguments must be quoted or transparent." .stripMargin, splice.pos)
438
+ splice
439
+ }
429
440
}
430
441
431
442
/** Transforms the contents of a nested splice
@@ -550,39 +561,10 @@ class ReifyQuotes extends MacroTransformWithImplicits {
550
561
val last = enteredSyms
551
562
stats.foreach(markDef)
552
563
mapOverTree(last)
553
- case Inlined (call, bindings, InlineSplice (spliced)) if ! call.isEmpty =>
554
- val tree2 =
555
- if (level == 0 ) {
556
- val evaluatedSplice = Splicer .splice(spliced, tree.pos, macroClassLoader).withPos(tree.pos)
557
- if (ctx.reporter.hasErrors) EmptyTree
558
- else transform(cpy.Inlined (tree)(call, bindings, evaluatedSplice))
559
- }
560
- else super .transform(tree)
561
-
562
- // due to value-discarding which converts an { e } into { e; () })
563
- if (tree.tpe =:= defn.UnitType ) Block (tree2 :: Nil , Literal (Constant (())))
564
- else tree2
565
564
case _ : Import =>
566
565
tree
567
- case tree : DefDef if tree.symbol.is(Macro ) && level == 0 =>
568
- if (enclosingInlineds.nonEmpty)
569
- return EmptyTree // Already checked at definition site and already inlined
570
- markDef(tree)
571
- tree.rhs match {
572
- case InlineSplice (_) =>
573
- mapOverTree(enteredSyms) // Ignore output, only check PCP
574
- cpy.DefDef (tree)(rhs = defaultValue(tree.rhs.tpe))
575
- case _ =>
576
- ctx.error(
577
- """ Malformed transparent macro.
578
- |
579
- |Expected the ~ to be at the top of the RHS:
580
- | transparent def foo(x: X, ..., y: Y): Int = ~impl(x, ... '(y))
581
- |
582
- |The contents of the splice must call a static method. Arguments must be quoted or inlined.
583
- """ .stripMargin, tree.rhs.pos)
584
- EmptyTree
585
- }
566
+ case tree : DefDef if tree.symbol.is(Macro ) && level == 0 && enclosingInlineds.nonEmpty =>
567
+ EmptyTree // Already checked at definition site and already inlined
586
568
case _ =>
587
569
markDef(tree)
588
570
checkLevel(mapOverTree(enteredSyms))
@@ -616,18 +598,6 @@ class ReifyQuotes extends MacroTransformWithImplicits {
616
598
acc.select(" ::" .toTermName).appliedToType(tpe).appliedTo(x)
617
599
}
618
600
}
619
-
620
- /** InlineSplice is used to detect cases where the expansion
621
- * consists of a (possibly multiple & nested) block or a sole expression.
622
- */
623
- object InlineSplice {
624
- def unapply (tree : Tree )(implicit ctx : Context ): Option [Tree ] = tree match {
625
- case Select (qual, _) if tree.symbol.isSplice && Splicer .canBeSpliced(qual) => Some (qual)
626
- case Block (List (stat), Literal (Constant (()))) => unapply(stat)
627
- case Block (Nil , expr) => unapply(expr)
628
- case _ => None
629
- }
630
- }
631
601
}
632
602
}
633
603
0 commit comments