Skip to content

fix #11401 (proxy parameter should be owned by proxy) #11552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Inliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions tests/pos-macros/i11401/Main_2.scala
Original file line number Diff line number Diff line change
@@ -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)

}
89 changes: 89 additions & 0 deletions tests/pos-macros/i11401/X_1.scala
Original file line number Diff line number Diff line change
@@ -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