Skip to content

Commit 4c2cddf

Browse files
Merge pull request #11000 from dotty-staging/fix-#10910
Fix #10910: Add missing position
2 parents 90b56b5 + 29d1cd5 commit 4c2cddf

File tree

3 files changed

+118
-1
lines changed

3 files changed

+118
-1
lines changed

compiler/src-bootstrapped/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
744744
object Lambda extends LambdaModule:
745745
def apply(owner: Symbol, tpe: MethodType, rhsFn: (Symbol, List[Tree]) => Tree): Block =
746746
val meth = dotc.core.Symbols.newSymbol(owner, nme.ANON_FUN, Synthetic | Method, tpe)
747-
tpd.Closure(meth, tss => yCheckedOwners(rhsFn(meth, tss.head), meth))
747+
tpd.Closure(meth, tss => yCheckedOwners(rhsFn(meth, tss.head.map(withDefaultPos)), meth))
748748

749749
def unapply(tree: Block): Option[(List[ValDef], Term)] = tree match {
750750
case Block((ddef @ DefDef(_, _, params :: Nil, _, Some(body))) :: Nil, Closure(meth, _))

tests/pos-macros/i10910/Macro_1.scala

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package x
2+
3+
import scala.quoted._
4+
5+
trait CB[T]:
6+
def map[S](f: T=>S): CB[S] = ???
7+
8+
def await[T](x:CB[T]):T = ???
9+
10+
object CBM:
11+
def pure[T](t:T):CB[T] = ???
12+
13+
object X:
14+
15+
inline def process[T](inline f:T) = ${
16+
processImpl[T]('f)
17+
}
18+
19+
def processImpl[T:Type](f:Expr[T])(using qctx: Quotes):Expr[CB[T]] =
20+
import quotes.reflect._
21+
22+
def transform(term:Term): Either[Term, Term] =
23+
term match
24+
case ap@Apply(Select(obj,"foreach"),args) =>
25+
// println("handle-foreach")
26+
val nArgs = args.map(x => shiftLambda(x).right.get)
27+
val nSelect = Select.unique(obj, "foreach_async")
28+
Right(Apply(nSelect,nArgs))
29+
case ap@Apply(sel@Select(obj,"awrite"),args) =>
30+
// println("handle-awrite")
31+
transform(args.head) match
32+
case Left(unchanded) => Left(ap)
33+
case Right(changed) =>
34+
val r = '{ ${changed.asExprOf[CB[?]]}.map(x => ${Apply(sel,List('x.asTerm)).asExpr}) }
35+
Right(r.asTerm)
36+
case Apply(tap@TypeApply(Ident("await"),targs),args) =>
37+
// println("handle-await")
38+
transform(args.head) match
39+
case Left(unchanged) => Right(unchanged)
40+
case Right(changed) =>
41+
val r = Apply(tap,List(changed))
42+
Right(r)
43+
case Lambda(v, body) => ???
44+
case Block(stats, last) => transform(last) match
45+
case Left(unchanged) => Left(Block(stats, last))
46+
case Right(changed) => Right(Block(stats, changed))
47+
case Inlined(x,List(),body) => transform(body)
48+
case Inlined(x,bindings,body) => transform(body) match
49+
case Left(unchanged) => Left(term)
50+
case Right(changed) => Right(Inlined(x,bindings,changed))
51+
case Typed(arg,tp) => transform(arg)
52+
case Ident(x) => Left(term)
53+
case l@Literal(x) => Left(l)
54+
case other =>
55+
throw RuntimeException(s"Not supported $other")
56+
57+
def shiftLambda(term:Term): Either[Term,Term] =
58+
term match
59+
case lt@Lambda(params, body) =>
60+
transform(body) match
61+
case Left(unchanged) => Left(term)
62+
case Right(nBody) =>
63+
val paramTypes = params.map(_.tpt.tpe)
64+
val paramNames = params.map(_.name+"Changed")
65+
val mt = MethodType(paramNames)(_ => paramTypes, _ => TypeRepr.of[CB].appliedTo(body.tpe.widen) )
66+
val r = Lambda(Symbol.spliceOwner, mt, (owner,args) => changeArgs(params,args,nBody).changeOwner(owner) )
67+
Right(r)
68+
case _ =>
69+
throw RuntimeException("lambda expected")
70+
def changeArgs(oldArgs:List[Tree], newArgs:List[Tree], body:Term):Term =
71+
// println(s"changeArgs: oldArgs=${oldArgs.map(_.symbol.hashCode)}, newArgs=${newArgs.map(_.symbol.hashCode)} ")
72+
val association: Map[Symbol, Term] = (oldArgs zip newArgs).foldLeft(Map.empty){
73+
case (m, (oldParam, newParam: Term)) => m.updated(oldParam.symbol, newParam)
74+
case (m, (oldParam, newParam: Tree)) => throw RuntimeException("Term expected")
75+
}
76+
val changes = new TreeMap() {
77+
override def transformTerm(tree:Term)(owner: Symbol): Term =
78+
tree match
79+
case ident@Ident(name) => association.getOrElse(ident.symbol, super.transformTerm(tree)(owner))
80+
case _ => super.transformTerm(tree)(owner)
81+
}
82+
changes.transformTerm(body)(Symbol.spliceOwner)
83+
84+
transform(f.asTerm) match
85+
case Left(unchanged) => '{ CBM.pure($f) }
86+
case Right(changed) => changed.asExprOf[CB[T]]

tests/pos-macros/i10910/Test_2.scala

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import x._
2+
3+
class Writer[A] {
4+
5+
def awrite(a:A): CB[Unit] = ???
6+
7+
inline def write(a:A):Unit =
8+
await(awrite(a))
9+
10+
}
11+
12+
class Reader[A] {
13+
14+
def foreach_async(f: A=> CB[Unit]): CB[Unit] = ???
15+
16+
def foreach(f: A=>Unit): Unit =
17+
foreach_async(v => CBM.pure(f(v)))
18+
19+
}
20+
21+
object Test {
22+
23+
def main(args:Array[String]):Unit =
24+
val writer = new Writer[Int]()
25+
val reader = new Reader[Int]()
26+
val r = X.process{
27+
reader.foreach( v => writer.write(v) )
28+
}
29+
println("r")
30+
31+
}

0 commit comments

Comments
 (0)