Skip to content

Commit f055cee

Browse files
committed
Elide unit binding when beta-reducing
See #20082 (comment)
1 parent ece87c3 commit f055cee

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import MegaPhase.*
88
import Symbols.*, Contexts.*, Types.*, Decorators.*
99
import StdNames.nme
1010
import ast.TreeTypeMap
11+
import Constants.Constant
1112

1213
import scala.collection.mutable.ListBuffer
1314

@@ -133,7 +134,7 @@ object BetaReduce:
133134
else if arg.tpe.dealias.isInstanceOf[ConstantType] then arg.tpe.dealias
134135
else arg.tpe.widen
135136
val binding = ValDef(newSymbol(ctx.owner, param.name, flags, tpe, coord = arg.span), arg).withSpan(arg.span)
136-
if !(tpe.isInstanceOf[ConstantType] && isPureExpr(arg)) then
137+
if !((tpe.isInstanceOf[ConstantType] || tpe.derivesFrom(defn.UnitClass)) && isPureExpr(arg)) then
137138
bindings += binding
138139
binding.symbol
139140

@@ -147,6 +148,7 @@ object BetaReduce:
147148
val expansion1 = new TreeMap {
148149
override def transform(tree: Tree)(using Context) = tree.tpe.widenTermRefExpr match
149150
case ConstantType(const) if isPureExpr(tree) => cpy.Literal(tree)(const)
151+
case tpe: TypeRef if tpe.derivesFrom(defn.UnitClass) && isPureExpr(tree) => cpy.Literal(tree)(Constant(()))
150152
case _ => super.transform(tree)
151153
}.transform(expansion)
152154

compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,4 +765,24 @@ class InlineBytecodeTests extends DottyBytecodeTest {
765765
diffInstructions(instructions1, instructions2))
766766
}
767767
}
768+
769+
@Test def beta_reduce_elide_unit_binding = {
770+
val source = """class Test:
771+
| def test = ((u: Unit) => u).apply(())
772+
""".stripMargin
773+
774+
checkBCode(source) { dir =>
775+
val clsIn = dir.lookupName("Test.class", directory = false).input
776+
val clsNode = loadClassNode(clsIn)
777+
778+
val fun = getMethod(clsNode, "test")
779+
val instructions = instructionsFromMethod(fun)
780+
val expected = List(Op(RETURN))
781+
782+
assert(instructions == expected,
783+
"`i was not properly beta-reduced in `test`\n" + diffInstructions(instructions, expected))
784+
785+
}
786+
}
787+
768788
}

0 commit comments

Comments
 (0)