Skip to content

Commit 7bef33b

Browse files
Merge pull request #11552 from rssh/fix-11401
fix #11401 (proxy parameter should be owned by proxy)
2 parents 4d0d591 + 0241150 commit 7bef33b

File tree

3 files changed

+108
-2
lines changed

3 files changed

+108
-2
lines changed

compiler/src/dotty/tools/dotc/typer/Inliner.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,9 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
461461
else (inlineFlags, argtpe.widen)
462462
val boundSym = newSym(InlineBinderName.fresh(name.asTermName), bindingFlags, bindingType).asTerm
463463
val binding = {
464-
if (isByName) DefDef(boundSym, arg.changeOwner(ctx.owner, boundSym))
465-
else ValDef(boundSym, arg)
464+
val newArg = arg.changeOwner(ctx.owner, boundSym)
465+
if (isByName) DefDef(boundSym, newArg)
466+
else ValDef(boundSym, newArg)
466467
}.withSpan(boundSym.span)
467468
bindingsBuf += binding.setDefTree
468469
binding

tests/pos-macros/i11401/Main_2.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package i11401
2+
3+
object Main {
4+
5+
def main(args:Array[String]):Unit =
6+
val in = new CIFReader[Boolean](true)
7+
val select = new SLSelect[Unit]()
8+
9+
val generator = X.process {
10+
select.fold(in){ (ch,s) =>
11+
s.apply1(ch, v=>ch)
12+
}
13+
}
14+
assert(true)
15+
16+
}

tests/pos-macros/i11401/X_1.scala

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package i11401
2+
3+
import scala.quoted._
4+
5+
import scala.concurrent.Future
6+
7+
def await[T](x:Future[T]):T = ???
8+
9+
class CIFReader[A](a:A)
10+
11+
12+
class SLSelect[S]:
13+
14+
def onRead[A](ch: CIFReader[A])(f: A=> S): this.type =
15+
???
16+
17+
def fold[S](s0:S)(step: (S,SLSelect[S])=> S): S = {
18+
???
19+
}
20+
21+
def fold_async[S](s0:S)(step: (S,SLSelect[S])=> Future[S]): Future[S] = {
22+
???
23+
}
24+
25+
inline def apply1[A](inline ch: CIFReader[A], f: A=>S): S =
26+
val s0 = new SLSelect[S]
27+
await(s0.onRead(ch)(f).runAsync())
28+
29+
def runAsync(): Future[S] = ???
30+
31+
32+
33+
object X:
34+
35+
inline def process[T](inline f:T) = ${
36+
processImpl[T]('f)
37+
}
38+
39+
def processImpl[T:Type](t:Expr[T])(using Quotes):Expr[Future[T]] =
40+
import quotes.reflect._
41+
val r = processTree[T](t.asTerm)
42+
r.asExprOf[Future[T]]
43+
44+
45+
def processTree[T:Type](using Quotes)(t: quotes.reflect.Term):quotes.reflect.Term =
46+
import quotes.reflect._
47+
val r: Term = t match
48+
case Inlined(_,List(),body) => processTree(body)
49+
case Inlined(d,bindings,body) =>
50+
Inlined(d,bindings,processTree[T](body))
51+
case Block(stats,expr) => Block(stats,processTree(expr))
52+
case Apply(Apply(TypeApply(Select(x,"fold"),targs),List(state)),List(fun)) =>
53+
val nFun = processLambda[T](fun)
54+
Apply(Apply(TypeApply(Select.unique(x,"fold_async"),targs),List(state)),List(nFun))
55+
case Apply(TypeApply(Ident("await"),targs),List(body)) => body
56+
case Typed(x,tp) => Typed(processTree(x), Inferred(TypeRepr.of[Future].appliedTo(tp.tpe)) )
57+
case _ => throw new RuntimeException(s"tree not recoginized: $t")
58+
val checker = new TreeMap() {}
59+
checker.transformTerm(r)(Symbol.spliceOwner)
60+
r
61+
62+
def processLambda[T:Type](using Quotes)(fun: quotes.reflect.Term):quotes.reflect.Term =
63+
import quotes.reflect._
64+
65+
def changeArgs(oldArgs:List[Tree], newArgs:List[Tree], body:Term, owner: Symbol):Term =
66+
val association: Map[Symbol, Term] = (oldArgs zip newArgs).foldLeft(Map.empty){
67+
case (m, (oldParam, newParam: Term)) => m.updated(oldParam.symbol, newParam)
68+
case (m, (oldParam, newParam: Tree)) => throw RuntimeException("Term expected")
69+
}
70+
val changes = new TreeMap() {
71+
override def transformTerm(tree:Term)(owner: Symbol): Term =
72+
tree match
73+
case ident@Ident(name) => association.getOrElse(ident.symbol, super.transformTerm(tree)(owner))
74+
case _ => super.transformTerm(tree)(owner)
75+
}
76+
changes.transformTerm(body)(owner)
77+
78+
val r = fun match
79+
case Lambda(params, body) =>
80+
val nBody = processTree[T](body)
81+
val paramTypes = params.map(_.tpt.tpe)
82+
val paramNames = params.map(_.name)
83+
val mt = MethodType(paramNames)(_ => paramTypes, _ => TypeRepr.of[Future].appliedTo(body.tpe.widen) )
84+
val r = Lambda(Symbol.spliceOwner, mt, (owner,args) => changeArgs(params,args,nBody,owner).changeOwner(owner) )
85+
r
86+
case Block(List(),expr) => processLambda(expr)
87+
case _ =>
88+
throw new RuntimeException(s"Lambda expected")
89+
r

0 commit comments

Comments
 (0)