Skip to content

Commit 5fb865b

Browse files
authored
Merge pull request #8918 from dotty-staging/fix-#8881
Fix #8881: Lift lets over applications
2 parents 06941b2 + 40a2946 commit 5fb865b

File tree

4 files changed

+40
-3
lines changed

4 files changed

+40
-3
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class Compiler {
9393
new FunctionXXLForwarders, // Add forwarders for FunctionXXL apply method
9494
new ParamForwarding, // Add forwarders for aliases of superclass parameters
9595
new TupleOptimizations, // Optimize generic operations on tuples
96+
new LetOverApply, // Lift blocks from receivers of applications
9697
new ArrayConstructors) :: // Intercept creation of (non-generic) arrays and intrinsify.
9798
List(new Erasure) :: // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements.
9899
List(new ElimErasedValueType, // Expand erased value types to their underlying implmementation types

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -749,14 +749,13 @@ object Erasure {
749749
val origFunType = origFun.tpe.widen(using preErasureCtx)
750750
val ownArgs = if origFunType.isErasedMethod then Nil else args
751751
val fun1 = typedExpr(fun, AnyFunctionProto)
752-
val fun1core = stripBlock(fun1)
753752
fun1.tpe.widen match
754753
case mt: MethodType =>
755754
val (xmt, // A method type like `mt` but with bunched arguments expanded to individual ones
756755
bunchArgs, // whether arguments are bunched
757756
outers) = // the outer reference parameter(s)
758-
if fun1core.isInstanceOf[Apply] then
759-
(mt, fun1core.removeAttachment(BunchedArgs).isDefined, Nil)
757+
if fun1.isInstanceOf[Apply] then
758+
(mt, fun1.removeAttachment(BunchedArgs).isDefined, Nil)
760759
else
761760
val xmt = expandedMethodType(mt, origFun)
762761
(xmt, xmt ne mt, outer.args(origFun))
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package dotty.tools
2+
package dotc
3+
package transform
4+
5+
import core._
6+
import Contexts.Context, Symbols._, Decorators._
7+
import MegaPhase._
8+
import ast.Trees._
9+
10+
/** Rewrite `{ stats; expr}.f(args)` to `{ stats; expr.f(args) }` and
11+
* `{ stats; expr }(args)` to `{ stats; expr(args) }` before proceeding,
12+
* but leave closures alone. This is necessary to be able to
13+
* collapse applies of IFTs (this is done in Erasure).
14+
*/
15+
class LetOverApply extends MiniPhase:
16+
import ast.tpd._
17+
18+
override def phaseName: String = "letOverApply"
19+
20+
override def transformApply(tree: Apply)(using Context): Tree =
21+
tree.fun match
22+
case Select(blk @ Block(stats, expr), name) if !expr.isInstanceOf[Closure] =>
23+
cpy.Block(blk)(stats,
24+
cpy.Apply(tree)(
25+
cpy.Select(tree.fun)(expr, name), tree.args))
26+
case Block(stats, expr) =>
27+
cpy.Block(tree.fun)(stats,
28+
cpy.Apply(tree)(expr, tree.args))
29+
case _ =>
30+
tree
31+
32+
end LetOverApply

tests/pos/i8881.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Crash {
2+
def f(a: String, b: String, c: Int = 0): Int ?=> String = ""
3+
given Int = ???
4+
f(b = "b", a = "a")
5+
}

0 commit comments

Comments
 (0)