Skip to content

Commit 0744eab

Browse files
committed
Add regression test for scala#10151
1 parent 6a50483 commit 0744eab

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

tests/pos-macros/i10151/Macro_1.scala

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package x
2+
3+
import scala.quoted._
4+
5+
trait CB[T]:
6+
def map[S](f: T=>S): CB[S] = ???
7+
def flatMap[S](f: T=>CB[S]): CB[S] = ???
8+
9+
class MyArr[AK,AV]:
10+
def map1[BK,BV](f: ((AK,AV)) => (BK, BV)):MyArr[BK,BV] = ???
11+
def map1Out[BK, BV](f: ((AK,AV)) => CB[(BK,BV)]): CB[MyArr[BK,BV]] = ???
12+
13+
def await[T](x:CB[T]):T = ???
14+
15+
object CBM:
16+
def pure[T](t:T):CB[T] = ???
17+
18+
object X:
19+
20+
inline def process[T](inline f:T) = ${
21+
processImpl[T]('f)
22+
}
23+
24+
def processImpl[T:Type](f:Expr[T])(using qctx: QuoteContext):Expr[CB[T]] =
25+
import qctx.reflect._
26+
27+
def transform(term:Term):Term =
28+
term match
29+
case Apply(TypeApply(Select(obj,"map1"),targs),args) =>
30+
val nArgs = args.map(x => shiftLambda(x))
31+
val nSelect = Select.unique(obj, "map1Out")
32+
Apply(TypeApply(nSelect,targs),nArgs)
33+
case Apply(TypeApply(Ident("await"),targs),args) => args.head
34+
case a@Apply(x,List(y,z)) =>
35+
val mty=MethodType(List("y1"))( _ => List(y.tpe.widen), _ => Type[CB].unseal.tpe.appliedTo(a.tpe.widen))
36+
val mtz=MethodType(List("z1"))( _ => List(z.tpe.widen), _ => a.tpe.widen)
37+
Apply(
38+
TypeApply(Select.unique(transform(y),"flatMap"),
39+
List(Inferred(a.tpe.widen))
40+
),
41+
List(
42+
Lambda(mty, yArgs =>
43+
Apply(
44+
TypeApply(Select.unique(transform(z),"map"),
45+
List(Inferred(a.tpe.widen))
46+
),
47+
List(
48+
Lambda(mtz, zArgs => {
49+
val termYArgs = yArgs.asInstanceOf[List[Term]]
50+
val termZArgs = zArgs.asInstanceOf[List[Term]]
51+
Apply(x,List(termYArgs.head,termZArgs.head))
52+
})
53+
)
54+
)
55+
)
56+
)
57+
)
58+
case Block(stats, last) => Block(stats, transform(last))
59+
case Inlined(x,List(),body) => transform(body)
60+
case l@Literal(x) =>
61+
l.seal match
62+
case '{ $l: $L } =>
63+
'{ CBM.pure(${term.seal.cast[L]}) }.unseal
64+
case other =>
65+
throw RuntimeException(s"Not supported $other")
66+
67+
def shiftLambda(term:Term): Term =
68+
term match
69+
case lt@Lambda(params, body) =>
70+
val paramTypes = params.map(_.tpt.tpe)
71+
val paramNames = params.map(_.name)
72+
val mt = MethodType(paramNames)(_ => paramTypes, _ => Type[CB].unseal.tpe.appliedTo(body.tpe.widen) )
73+
Lambda(mt, args => changeArgs(params,args,transform(body)) )
74+
case Block(stats, last) =>
75+
Block(stats, shiftLambda(last))
76+
case _ =>
77+
throw RuntimeException("lambda expected")
78+
79+
def changeArgs(oldArgs:List[Tree], newArgs:List[Tree], body:Term):Term =
80+
val association: Map[Symbol, Term] = (oldArgs zip newArgs).foldLeft(Map.empty){
81+
case (m, (oldParam, newParam: Term)) => m.updated(oldParam.symbol, newParam)
82+
case (m, (oldParam, newParam: Tree)) => throw RuntimeException("Term expected")
83+
}
84+
val changes = new TreeMap() {
85+
override def transformTerm(tree:Term)(using Context): Term =
86+
tree match
87+
case ident@Ident(name) => association.getOrElse(ident.symbol, super.transformTerm(tree))
88+
case _ => super.transformTerm(tree)
89+
}
90+
changes.transformTerm(body)
91+
92+
val r = transform(f.unseal).seal.cast[CB[T]]
93+
r

tests/pos-macros/i10151/Test_2.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package x
2+
3+
4+
object Main {
5+
6+
def main(args:Array[String]):Unit =
7+
val arr = new MyArr[Int,Int]()
8+
val r = X.process{
9+
arr.map1( (x,y) =>
10+
( 1, await(CBM.pure(x)) )
11+
)
12+
}
13+
println("r")
14+
15+
}

0 commit comments

Comments
 (0)