Skip to content

Commit 0b512d6

Browse files
committed
Fix by-name parameter in beta-reduction
Fixes #20095
1 parent f3139cd commit 0b512d6

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

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

+11-6
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,20 @@ object BetaReduce:
128128
case ref @ TermRef(NoPrefix, _) if isPurePath(arg) =>
129129
ref.symbol
130130
case _ =>
131-
val flags = Synthetic | (param.symbol.flags & Erased)
132-
val tpe =
131+
val isByNameArg = param.tpt.tpe.isInstanceOf[ExprType]
132+
val flags =
133+
if isByNameArg then Synthetic | Method | (param.symbol.flags & Erased)
134+
else Synthetic | (param.symbol.flags & Erased)
135+
val tpe0 =
133136
if arg.tpe.isBottomType then param.tpe.widenTermRefExpr
134137
else if arg.tpe.dealias.isInstanceOf[ConstantType] then arg.tpe.dealias
135138
else arg.tpe.widen
136-
val binding = ValDef(newSymbol(ctx.owner, param.name, flags, tpe, coord = arg.span), arg).withSpan(arg.span)
137-
if !((tpe.isInstanceOf[ConstantType] || tpe.derivesFrom(defn.UnitClass)) && isPureExpr(arg)) then
138-
bindings += binding
139-
binding.symbol
139+
val tpe = if isByNameArg then ExprType(tpe0) else tpe0
140+
val bindingSymbol = newSymbol(ctx.owner, param.name, flags, tpe, coord = arg.span)
141+
val binding = if isByNameArg then DefDef(bindingSymbol, arg) else ValDef(bindingSymbol, arg)
142+
if isByNameArg || !((tpe.isInstanceOf[ConstantType] || tpe.derivesFrom(defn.UnitClass)) && isPureExpr(arg)) then
143+
bindings += binding.withSpan(arg.span)
144+
bindingSymbol
140145

141146
val expansion = TreeTypeMap(
142147
oldOwners = ddef.symbol :: Nil,

tests/run/i20095.check

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
foo
2+
foo

tests/run/i20095.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
inline def twice(inline thunk: =>Unit): Unit =
2+
thunk
3+
thunk
4+
5+
inline def pipe(inline t: =>Unit, inline f: (=>Unit) => Unit): Unit = f(t)
6+
7+
@main def Test =
8+
pipe((), twice)
9+
pipe(println("foo"), twice)

0 commit comments

Comments
 (0)