From 29ef6208125f4f3b9eaac6e6f5209df612a45ef4 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 12 Oct 2021 14:30:51 +0200 Subject: [PATCH] Add missing position to closure tree Fixes #13557 --- .../quoted/runtime/impl/QuotesImpl.scala | 2 +- tests/pos-macros/i13557/Macro_1.scala | 41 +++++++++++++++++++ tests/pos-macros/i13557/Test_2.scala | 9 ++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/pos-macros/i13557/Macro_1.scala create mode 100644 tests/pos-macros/i13557/Test_2.scala diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 80c6dc757aaa..d64ecb1d33e5 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -794,7 +794,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler object Lambda extends LambdaModule: def apply(owner: Symbol, tpe: MethodType, rhsFn: (Symbol, List[Tree]) => Tree): Block = val meth = dotc.core.Symbols.newSymbol(owner, nme.ANON_FUN, Synthetic | Method, tpe) - tpd.Closure(meth, tss => xCheckMacroedOwners(xCheckMacroValidExpr(rhsFn(meth, tss.head.map(withDefaultPos))), meth)) + withDefaultPos(tpd.Closure(meth, tss => xCheckMacroedOwners(xCheckMacroValidExpr(rhsFn(meth, tss.head.map(withDefaultPos))), meth))) def unapply(tree: Block): Option[(List[ValDef], Term)] = tree match { case Block((ddef @ DefDef(_, tpd.ValDefs(params) :: Nil, _, Some(body))) :: Nil, Closure(meth, _)) diff --git a/tests/pos-macros/i13557/Macro_1.scala b/tests/pos-macros/i13557/Macro_1.scala new file mode 100644 index 000000000000..73d2328b7e3a --- /dev/null +++ b/tests/pos-macros/i13557/Macro_1.scala @@ -0,0 +1,41 @@ +package x + +import scala.quoted.* + +def fun(x:Int): Int = ??? + +transparent inline def in1[T](inline expr: Int => Int): Int => Int = + ${ + M.transformLambdaImpl('expr) + } + +object M: + + def transformLambdaImpl(cexpr: Expr[Int => Int])(using Quotes): Expr[Int => Int] = + import quotes.reflect.* + + def extractLambda(f:Term): (ValDef, Term, Term => Term ) = + f match + case Inlined(call, bindings, body) => + val inner = extractLambda(body) + (inner._1, inner._2, t => Inlined(call, bindings, t) ) + case Lambda(params,body) => + params match + case List(vd) => (vd, body, identity) + case _ => report.throwError(s"lambda with one argument expected, we have ${params}",cexpr) + case Block(Nil,nested@Lambda(params,body)) => extractLambda(nested) + case _ => + report.throwError(s"lambda expected, have: ${f}", cexpr) + + val (oldValDef, body, inlineBack) = extractLambda(cexpr.asTerm) + val mt = MethodType(List(oldValDef.name))( _ => List(oldValDef.tpt.tpe), _ => TypeRepr.of[Int]) + val nLambda = Lambda(Symbol.spliceOwner, mt, (owner, params) => { + val argTransformer = new TreeMap() { + override def transformTerm(tree: Term)(owner: Symbol): Term = + tree match + case Ident(name) if (tree.symbol == oldValDef.symbol) => Ref(params.head.symbol) + case _ => super.transformTerm(tree)(owner) + } + argTransformer.transformTerm('{ fun(${body.asExprOf[Int]}) }.asTerm )(owner) + }) + inlineBack(nLambda).asExprOf[Int => Int] diff --git a/tests/pos-macros/i13557/Test_2.scala b/tests/pos-macros/i13557/Test_2.scala new file mode 100644 index 000000000000..c9468a538abe --- /dev/null +++ b/tests/pos-macros/i13557/Test_2.scala @@ -0,0 +1,9 @@ +package x + +object Main: + + def testSimpleContext(): Unit = + var x = 0 + val c = in1{ scope => + 1 + }