Skip to content

Commit

Permalink
Fix by-name parameter in beta-reduction (#20096)
Browse files Browse the repository at this point in the history
Fixes #20095
  • Loading branch information
nicolasstucki authored Apr 5, 2024
2 parents b8fb81b + 0b512d6 commit 3bf44f1
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 6 deletions.
17 changes: 11 additions & 6 deletions compiler/src/dotty/tools/dotc/transform/BetaReduce.scala
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,20 @@ object BetaReduce:
case ref @ TermRef(NoPrefix, _) if isPurePath(arg) =>
ref.symbol
case _ =>
val flags = Synthetic | (param.symbol.flags & Erased)
val tpe =
val isByNameArg = param.tpt.tpe.isInstanceOf[ExprType]
val flags =
if isByNameArg then Synthetic | Method | (param.symbol.flags & Erased)
else Synthetic | (param.symbol.flags & Erased)
val tpe0 =
if arg.tpe.isBottomType then param.tpe.widenTermRefExpr
else if arg.tpe.dealias.isInstanceOf[ConstantType] then arg.tpe.dealias
else arg.tpe.widen
val binding = ValDef(newSymbol(ctx.owner, param.name, flags, tpe, coord = arg.span), arg).withSpan(arg.span)
if !((tpe.isInstanceOf[ConstantType] || tpe.derivesFrom(defn.UnitClass)) && isPureExpr(arg)) then
bindings += binding
binding.symbol
val tpe = if isByNameArg then ExprType(tpe0) else tpe0
val bindingSymbol = newSymbol(ctx.owner, param.name, flags, tpe, coord = arg.span)
val binding = if isByNameArg then DefDef(bindingSymbol, arg) else ValDef(bindingSymbol, arg)
if isByNameArg || !((tpe.isInstanceOf[ConstantType] || tpe.derivesFrom(defn.UnitClass)) && isPureExpr(arg)) then
bindings += binding.withSpan(arg.span)
bindingSymbol

val expansion = TreeTypeMap(
oldOwners = ddef.symbol :: Nil,
Expand Down
2 changes: 2 additions & 0 deletions tests/run/i20095.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
foo
foo
9 changes: 9 additions & 0 deletions tests/run/i20095.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
inline def twice(inline thunk: =>Unit): Unit =
thunk
thunk

inline def pipe(inline t: =>Unit, inline f: (=>Unit) => Unit): Unit = f(t)

@main def Test =
pipe((), twice)
pipe(println("foo"), twice)

0 comments on commit 3bf44f1

Please sign in to comment.