Skip to content

Commit 38de2dc

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

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

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

Lines changed: 20 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,24 @@ object Splicer {
289289
unexpectedTree(tree)
290290
}
291291

292+
private def interpretArgs(argss: List[List[Tree]], fnType: Type)(using Env): List[Object] = {
293+
fnType 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+
val interprededHeadParams =
298+
for (info, arg) <- fnType.paramInfos.lazyZip(argss.head) yield
299+
info match
300+
case _: ExprType => () => interpretTree(arg) // by-name argument
301+
case _ => interpretTree(arg) // by-value argument
302+
interprededHeadParams.toList ::: interpretArgs(argss.tail, fnType.resType)
303+
case _ =>
304+
// If the final result type is a context function the rest of the args are interpreted as by-value.
305+
// for `def f(x: Int): Int ?=> Int` we call directly the verison that does not create the closure
306+
// `def f$direct(x: Int)(x$1: Int): Int`.
307+
argss.flatMap(_.map(interpretTree))
308+
}
309+
292310
private def interpretBlock(stats: List[Tree], expr: Tree)(implicit env: Env) = {
293311
var unexpected: Option[Object] = None
294312
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)