From e1c66fb7a0d3b6c0b8615d579afd11d85fc22f2e Mon Sep 17 00:00:00 2001 From: Ruslan Shevchenko Date: Sat, 31 Oct 2020 23:48:41 +0200 Subject: [PATCH 1/3] cleanup ownity in lambda destructor, to allow body be reused in other exoressions with current context --- compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala b/compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala index c8543f822688..deae7e6aa082 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuoteContextImpl.scala @@ -2,6 +2,7 @@ package dotty.tools.dotc.quoted import dotty.tools.dotc import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.ast.tpd.TreeOps import dotty.tools.dotc.ast.untpd import dotty.tools.dotc.core.Annotations import dotty.tools.dotc.core.Contexts._ @@ -745,7 +746,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext: def unapply(tree: Block): Option[(List[ValDef], Term)] = tree match { case Block((ddef @ DefDef(_, _, params :: Nil, _, Some(body))) :: Nil, Closure(meth, _)) if ddef.symbol == meth.symbol => - Some((params, body)) + val cleanParams = params.map(_.changeOwner(meth.symbol,ctx.owner)) + val cleanBody = body.changeOwner(meth.symbol,ctx.owner) + Some((cleanParams, cleanBody)) case _ => None } end Lambda From 33340f0fac5873bb788487d607b984cf74ca37b4 Mon Sep 17 00:00:00 2001 From: Ruslan Shevchenko Date: Sun, 1 Nov 2020 00:56:55 +0200 Subject: [PATCH 2/3] aded regression tests for #9894 --- tests/pos-macros/i9894/Macro_1.scala | 68 ++++++++++++++++++++++++++++ tests/pos-macros/i9894/Test_2.scala | 18 ++++++++ 2 files changed, 86 insertions(+) create mode 100644 tests/pos-macros/i9894/Macro_1.scala create mode 100644 tests/pos-macros/i9894/Test_2.scala diff --git a/tests/pos-macros/i9894/Macro_1.scala b/tests/pos-macros/i9894/Macro_1.scala new file mode 100644 index 000000000000..86f19dbbc8da --- /dev/null +++ b/tests/pos-macros/i9894/Macro_1.scala @@ -0,0 +1,68 @@ +package x + +import scala.quoted._ + +trait CB[T]: + def map[S](f: T=>S): CB[S] = ??? + +class MyArr[A]: + def map1[B](f: A=>B):MyArr[B] = ??? + def map1Out[B](f: A=> CB[B]): CB[MyArr[B]] = ??? + +def await[T](x:CB[T]):T = ??? + +object CBM: + def pure[T](t:T):CB[T] = ??? + +object X: + + inline def process[T](inline f:T) = ${ + processImpl[T]('f) + } + + def processImpl[T:Type](f:Expr[T])(using qctx: QuoteContext):Expr[CB[T]] = + import qctx.reflect._ + + def transform(term:Term):Term = + term match + case ap@Apply(TypeApply(Select(obj,"map1"),targs),args) => + val nArgs = args.map(x => shiftLambda(x)) + val nSelect = Select.unique(obj, "map1Out") + Apply(TypeApply(nSelect,targs),nArgs) + //Apply.copy(ap)(TypeApply(nSelect,targs),nArgs) + case Apply(TypeApply(Ident("await"),targs),args) => args.head + case Apply(x,y) => + Apply(x, y.map(transform)) + case Block(stats, last) => Block(stats, transform(last)) + case Inlined(x,List(),body) => transform(body) + case l@Literal(x) => + '{ CBM.pure(${term.seal}) }.unseal + case other => + throw RuntimeException(s"Not supported $other") + + def shiftLambda(term:Term): Term = + term match + case lt@Lambda(params, body) => + val paramTypes = params.map(_.tpt.tpe) + val paramNames = params.map(_.name) + val mt = MethodType(paramNames)(_ => paramTypes, _ => Type[CB].unseal.tpe.appliedTo(body.tpe.widen) ) + val r = Lambda(mt, args => changeArgs(params,args,transform(body)) ) + r + case _ => + throw RuntimeException("lambda expected") + + def changeArgs(oldArgs:List[Tree], newArgs:List[Tree], body:Term):Term = + val association: Map[Symbol, Term] = (oldArgs zip newArgs).foldLeft(Map.empty){ + case (m, (oldParam, newParam: Term)) => m.updated(oldParam.symbol, newParam) + case (m, (oldParam, newParam: Tree)) => throw RuntimeException("Term expected") + } + val changes = new TreeMap() { + override def transformTerm(tree:Term)(using Context): Term = + tree match + case ident@Ident(name) => association.getOrElse(ident.symbol, super.transformTerm(tree)) + case _ => super.transformTerm(tree) + } + changes.transformTerm(body) + + transform(f.unseal).seal.cast[CB[T]] + diff --git a/tests/pos-macros/i9894/Test_2.scala b/tests/pos-macros/i9894/Test_2.scala new file mode 100644 index 000000000000..a432915b887f --- /dev/null +++ b/tests/pos-macros/i9894/Test_2.scala @@ -0,0 +1,18 @@ +package x + + +object Main { + + def main(args:Array[String]):Unit = + val arr = new MyArr[Int]() + val r = X.process{ + arr.map1( zDebug => + await(CBM.pure(1).map(a => zDebug + a)) + ) + } + println("r") + +} + + + From d663848665dadca7e9de7353ad01274cf68f7a28 Mon Sep 17 00:00:00 2001 From: Ruslan Shevchenko Date: Sun, 1 Nov 2020 01:07:15 +0200 Subject: [PATCH 3/3] removed empty lines ad the end of file. --- tests/pos-macros/i9894/Macro_1.scala | 1 - tests/pos-macros/i9894/Test_2.scala | 3 --- 2 files changed, 4 deletions(-) diff --git a/tests/pos-macros/i9894/Macro_1.scala b/tests/pos-macros/i9894/Macro_1.scala index 86f19dbbc8da..751a2d4b4b16 100644 --- a/tests/pos-macros/i9894/Macro_1.scala +++ b/tests/pos-macros/i9894/Macro_1.scala @@ -65,4 +65,3 @@ object X: changes.transformTerm(body) transform(f.unseal).seal.cast[CB[T]] - diff --git a/tests/pos-macros/i9894/Test_2.scala b/tests/pos-macros/i9894/Test_2.scala index a432915b887f..c9d3a17fcf49 100644 --- a/tests/pos-macros/i9894/Test_2.scala +++ b/tests/pos-macros/i9894/Test_2.scala @@ -13,6 +13,3 @@ object Main { println("r") } - - -