Skip to content

Commit a437acb

Browse files
committed
Fix #9802: Interpret by-name params as () => interpret(arg)
1 parent a05fc4b commit a437acb

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

compiler/src/dotty/tools/dotc/transform/Splicer.scala

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ object Splicer {
250250
interpretModuleAccess(fn.symbol)
251251
else if (fn.symbol.is(Method) && fn.symbol.isStatic) {
252252
val staticMethodCall = interpretedStaticMethodCall(fn.symbol.owner, fn.symbol)
253-
staticMethodCall(args.flatten.map(interpretTree))
253+
staticMethodCall(interpretArgs(args, fn.symbol.info))
254254
}
255255
else if fn.symbol.isStatic then
256256
assert(args.isEmpty)
@@ -260,7 +260,7 @@ object Splicer {
260260
interpretModuleAccess(fn.qualifier.symbol)
261261
else {
262262
val staticMethodCall = interpretedStaticMethodCall(fn.qualifier.symbol.moduleClass, fn.symbol)
263-
staticMethodCall(args.flatten.map(interpretTree))
263+
staticMethodCall(interpretArgs(args, fn.symbol.info))
264264
}
265265
else if (env.contains(fn.symbol))
266266
env(fn.symbol)
@@ -289,6 +289,28 @@ object Splicer {
289289
unexpectedTree(tree)
290290
}
291291

292+
private def interpretArgs(argss: List[List[Tree]], fnType: Type)(using Env): List[Object] = {
293+
fnType.dealias match
294+
case fnType: PolyType => interpretArgs(argss, fnType.resType)
295+
case fnType: MethodType if fnType.isErasedMethod => interpretArgs(argss, fnType.resType)
296+
case fnType: MethodType =>
297+
assert(argss.head.size == fnType.paramInfos.size)
298+
val interprededHeadParams =
299+
for (info, arg) <- fnType.paramInfos.lazyZip(argss.head) yield
300+
info match
301+
case _: ExprType => () => interpretTree(arg) // by-name argument
302+
case _ => interpretTree(arg) // by-value argument
303+
interprededHeadParams.toList ::: interpretArgs(argss.tail, fnType.resType)
304+
case fnType: ExprType => interpretArgs(argss, fnType.resType)
305+
case fnType: AppliedType if defn.isContextFunctionType(fnType) =>
306+
val argTypes :+ resType = fnType.args
307+
assert(argss.head.size == argTypes.size)
308+
argss.head.map(interpretTree) ::: interpretArgs(argss.tail, resType)
309+
case _ =>
310+
assert(argss.isEmpty)
311+
Nil
312+
}
313+
292314
private def interpretBlock(stats: List[Tree], expr: Tree)(implicit env: Env) = {
293315
var unexpected: Option[Object] = None
294316
val newEnv = stats.foldLeft(env)((accEnv, stat) => stat match {

tests/pos-macros/i9802/Macro_1.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import scala.quoted._
2+
3+
inline def fun(inline prog: Double): Double = ${impl('prog)}
4+
5+
def impl(prog: => Expr[Double])(using QuoteContext) : Expr[Double] = '{ 42.0 }

tests/pos-macros/i9802/Test_2.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
def test: Unit = fun(4)

0 commit comments

Comments
 (0)