diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index 9cc37d3716bd..bb2de5f3d5e6 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -236,7 +236,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { case tree: DefTree => val sym = tree.symbol if ((sym.isClass || !sym.maybeOwner.isType) && !levelOf.contains(sym)) { - levelOf(sym) = level + val symLevel = if (isStage0Value(sym)) 0 else level + levelOf(sym) = symLevel enteredSyms = sym :: enteredSyms } case _ => @@ -249,8 +250,7 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { */ def levelOK(sym: Symbol)(implicit ctx: Context): Boolean = levelOf.get(sym) match { case Some(l) => - l == level || - l == 1 && level == 0 && isStage0Value(sym) + l == level case None => !sym.is(Param) || levelOK(sym.owner) } @@ -384,15 +384,9 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { } else body match { case body: RefTree if isCaptured(body.symbol, level + 1) => - if (isStage0Value(body.symbol)) { - // Optimization: avoid the full conversion when capturing inlined `x` - // in '{ x } to '{ x$1.toExpr.unary_~ } and go directly to `x$1.toExpr` - liftValue(capturers(body.symbol)(body)) - } else { - // Optimization: avoid the full conversion when capturing `x` - // in '{ x } to '{ x$1.unary_~ } and go directly to `x$1` - capturers(body.symbol)(body) - } + // Optimization: avoid the full conversion when capturing `x` + // in '{ x } to '{ x$1.unary_~ } and go directly to `x$1` + capturers(body.symbol)(body) case _=> val (body1, splices) = nested(isQuote = true).split(body) pickledQuote(body1, splices, body.tpe, isType).withPos(quote.pos) @@ -575,9 +569,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { val capturer = capturers(tree.symbol) def captureAndSplice(t: Tree) = splice(t.select(if (tree.isTerm) nme.UNARY_~ else tpnme.UNARY_~)) - if (!isStage0Value(tree.symbol)) captureAndSplice(capturer(tree)) - else if (level == 0) capturer(tree) - else captureAndSplice(liftValue(capturer(tree))) + if (level == 0 && isStage0Value(tree.symbol)) capturer(tree) + else captureAndSplice(capturer(tree)) case Block(stats, _) => val last = enteredSyms stats.foreach(markDef) @@ -632,23 +625,8 @@ class ReifyQuotes extends MacroTransformWithImplicits with InfoTransformer { } } - private def liftValue(tree: Tree)(implicit ctx: Context): Tree = { - val reqType = defn.QuotedLiftableType.appliedTo(tree.tpe.widen) - val liftable = ctx.typer.inferImplicitArg(reqType, tree.pos) - liftable.tpe match { - case fail: SearchFailureType => - ctx.error(i""" - | - | The access would be accepted with the right Liftable, but - | ${ctx.typer.missingArgMsg(liftable, reqType, "")}""") - EmptyTree - case _ => - liftable.select("toExpr".toTermName).appliedTo(tree) - } - } - private def isStage0Value(sym: Symbol)(implicit ctx: Context): Boolean = - (sym.is(Inline) && sym.owner.is(Macro) && !defn.isFunctionType(sym.info)) || + (sym.is(Inline) && sym.is(Param) && sym.owner.is(Macro) && !defn.isFunctionType(sym.info)) || sym == defn.TastyTopLevelSplice_compilationTopLevelSplice // intrinsic value at stage 0 private def liftList(list: List[Tree], tpe: Type)(implicit ctx: Context): Tree = { diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index cd55764631a6..abcea511d994 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -124,7 +124,7 @@ object Inliner { if needsAccessor(tree.symbol) && tree.isTerm && !tree.symbol.isConstructor => val (refPart, targs, argss) = decomposeCall(tree) val qual = qualifier(refPart) - println(i"adding receiver passing inline accessor for $tree/$refPart -> (${qual.tpe}, $refPart: ${refPart.getClass}, [$targs%, %], ($argss%, %))") + inlining.println(i"adding receiver passing inline accessor for $tree/$refPart -> (${qual.tpe}, $refPart: ${refPart.getClass}, [$targs%, %], ($argss%, %))") // Need to dealias in order to cagtch all possible references to abstracted over types in // substitutions diff --git a/docs/docs/reference/principled-meta-programming.md b/docs/docs/reference/principled-meta-programming.md index a3b972618e97..6952fa679ace 100644 --- a/docs/docs/reference/principled-meta-programming.md +++ b/docs/docs/reference/principled-meta-programming.md @@ -400,7 +400,7 @@ as follows: function) of type Boolean, Byte, Short, Int, Long, Float, Double, Char or String, it can be accessed in all contexts where the number of splices minus the number of quotes between use and definition - is either 0 or 1. + is 1. ### Relationship with Staging diff --git a/tests/neg/quote-macro-inline-args.scala b/tests/neg/quote-macro-inline-args.scala new file mode 100644 index 000000000000..bfae11dfbf96 --- /dev/null +++ b/tests/neg/quote-macro-inline-args.scala @@ -0,0 +1,9 @@ +object Test { + + inline def foo(inline x: Int): Int = ~{ + if (x == 1) '(3) + else '(x) // error + } + +} + diff --git a/tests/run/i4455/Macro_1.scala b/tests/run/i4455/Macro_1.scala index 9ac3070ed986..c98ea68cd983 100644 --- a/tests/run/i4455/Macro_1.scala +++ b/tests/run/i4455/Macro_1.scala @@ -1,8 +1,8 @@ import scala.quoted._ object Macros { - inline def foo(inline i: Int): Int = ~bar('(i)) + inline def foo(inline i: Int): Int = ~bar(i.toExpr) - inline def foo2(inline i: Int): Int = ~bar('(i + 1)) + inline def foo2(inline i: Int): Int = ~bar((i + 1).toExpr) def bar(x: Expr[Int]): Expr[Int] = x }