diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index d89ba6128274..b179a8b89015 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -461,8 +461,9 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { else (inlineFlags, argtpe.widen) val boundSym = newSym(InlineBinderName.fresh(name.asTermName), bindingFlags, bindingType).asTerm val binding = { - if (isByName) DefDef(boundSym, arg.changeOwner(ctx.owner, boundSym)) - else ValDef(boundSym, arg) + val newArg = arg.changeOwner(ctx.owner, boundSym) + if (isByName) DefDef(boundSym, newArg) + else ValDef(boundSym, newArg) }.withSpan(boundSym.span) bindingsBuf += binding.setDefTree binding diff --git a/tests/pos-macros/i11401/Main_2.scala b/tests/pos-macros/i11401/Main_2.scala new file mode 100644 index 000000000000..85e2e39efff2 --- /dev/null +++ b/tests/pos-macros/i11401/Main_2.scala @@ -0,0 +1,16 @@ +package i11401 + +object Main { + + def main(args:Array[String]):Unit = + val in = new CIFReader[Boolean](true) + val select = new SLSelect[Unit]() + + val generator = X.process { + select.fold(in){ (ch,s) => + s.apply1(ch, v=>ch) + } + } + assert(true) + +} diff --git a/tests/pos-macros/i11401/X_1.scala b/tests/pos-macros/i11401/X_1.scala new file mode 100644 index 000000000000..92f868d996a4 --- /dev/null +++ b/tests/pos-macros/i11401/X_1.scala @@ -0,0 +1,89 @@ +package i11401 + +import scala.quoted._ + +import scala.concurrent.Future + +def await[T](x:Future[T]):T = ??? + +class CIFReader[A](a:A) + + +class SLSelect[S]: + + def onRead[A](ch: CIFReader[A])(f: A=> S): this.type = + ??? + + def fold[S](s0:S)(step: (S,SLSelect[S])=> S): S = { + ??? + } + + def fold_async[S](s0:S)(step: (S,SLSelect[S])=> Future[S]): Future[S] = { + ??? + } + + inline def apply1[A](inline ch: CIFReader[A], f: A=>S): S = + val s0 = new SLSelect[S] + await(s0.onRead(ch)(f).runAsync()) + + def runAsync(): Future[S] = ??? + + + +object X: + + inline def process[T](inline f:T) = ${ + processImpl[T]('f) + } + + def processImpl[T:Type](t:Expr[T])(using Quotes):Expr[Future[T]] = + import quotes.reflect._ + val r = processTree[T](t.asTerm) + r.asExprOf[Future[T]] + + + def processTree[T:Type](using Quotes)(t: quotes.reflect.Term):quotes.reflect.Term = + import quotes.reflect._ + val r: Term = t match + case Inlined(_,List(),body) => processTree(body) + case Inlined(d,bindings,body) => + Inlined(d,bindings,processTree[T](body)) + case Block(stats,expr) => Block(stats,processTree(expr)) + case Apply(Apply(TypeApply(Select(x,"fold"),targs),List(state)),List(fun)) => + val nFun = processLambda[T](fun) + Apply(Apply(TypeApply(Select.unique(x,"fold_async"),targs),List(state)),List(nFun)) + case Apply(TypeApply(Ident("await"),targs),List(body)) => body + case Typed(x,tp) => Typed(processTree(x), Inferred(TypeRepr.of[Future].appliedTo(tp.tpe)) ) + case _ => throw new RuntimeException(s"tree not recoginized: $t") + val checker = new TreeMap() {} + checker.transformTerm(r)(Symbol.spliceOwner) + r + + def processLambda[T:Type](using Quotes)(fun: quotes.reflect.Term):quotes.reflect.Term = + import quotes.reflect._ + + def changeArgs(oldArgs:List[Tree], newArgs:List[Tree], body:Term, owner: Symbol):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)(owner: Symbol): Term = + tree match + case ident@Ident(name) => association.getOrElse(ident.symbol, super.transformTerm(tree)(owner)) + case _ => super.transformTerm(tree)(owner) + } + changes.transformTerm(body)(owner) + + val r = fun match + case Lambda(params, body) => + val nBody = processTree[T](body) + val paramTypes = params.map(_.tpt.tpe) + val paramNames = params.map(_.name) + val mt = MethodType(paramNames)(_ => paramTypes, _ => TypeRepr.of[Future].appliedTo(body.tpe.widen) ) + val r = Lambda(Symbol.spliceOwner, mt, (owner,args) => changeArgs(params,args,nBody,owner).changeOwner(owner) ) + r + case Block(List(),expr) => processLambda(expr) + case _ => + throw new RuntimeException(s"Lambda expected") + r