From 0b512d681275f9ebeeed99275579664f8a9deea4 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 5 Apr 2024 09:34:59 +0200 Subject: [PATCH] Fix by-name parameter in beta-reduction Fixes #20095 --- .../dotty/tools/dotc/transform/BetaReduce.scala | 17 +++++++++++------ tests/run/i20095.check | 2 ++ tests/run/i20095.scala | 9 +++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 tests/run/i20095.check create mode 100644 tests/run/i20095.scala diff --git a/compiler/src/dotty/tools/dotc/transform/BetaReduce.scala b/compiler/src/dotty/tools/dotc/transform/BetaReduce.scala index 720ed45bbe6c..dd20ff9557ca 100644 --- a/compiler/src/dotty/tools/dotc/transform/BetaReduce.scala +++ b/compiler/src/dotty/tools/dotc/transform/BetaReduce.scala @@ -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, diff --git a/tests/run/i20095.check b/tests/run/i20095.check new file mode 100644 index 000000000000..0d55bed3a35c --- /dev/null +++ b/tests/run/i20095.check @@ -0,0 +1,2 @@ +foo +foo diff --git a/tests/run/i20095.scala b/tests/run/i20095.scala new file mode 100644 index 000000000000..e5761f49b539 --- /dev/null +++ b/tests/run/i20095.scala @@ -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)