Skip to content

Commit a129eac

Browse files
committed
Refactor bridge forwarders
1 parent 209fdc6 commit a129eac

File tree

1 file changed

+49
-66
lines changed

1 file changed

+49
-66
lines changed

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

Lines changed: 49 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -116,81 +116,64 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(using Context) {
116116
root.delete(other)
117117
toBeRemoved += other
118118
}
119-
/** Eta expand given `tree` that has the given method type `mt`, so that
120-
* it conforms to erased result type `pt`.
121-
* To do this correctly, we have to look at the tree's original pre-erasure
119+
120+
val memberCount = contextResultCount(member)
121+
122+
/** Eta expand application `ref(args)` as needed.
123+
* To do this correctly, we have to look at the member's original pre-erasure
122124
* type and figure out which context function types in its result are
123125
* not yet instantiated.
124126
*/
125-
def forwarder(ref: Tree, args: List[Tree], owner: Symbol, pt: Type, other: Symbol)(using Context): Tree =
126-
val origOwner = ctx.owner
127-
val member = ref.symbol
128-
val memberCount = contextResultCount(member)
129-
if memberCount == 0 then
130-
ref.appliedToTermArgs(args)
131-
else
132-
def expandArgs(args: List[Tree], owner: Symbol)(using Context): List[Tree] = args match
133-
case (bunchedParam @ Ident(nme.ALLARGS)) :: Nil =>
134-
owner.info.firstParamTypes.indices.toList.map(n =>
135-
bunchedParam
136-
.select(nme.primitive.arrayApply)
137-
.appliedTo(Literal(Constant(n)))).showing("Expand $args%, % --> $result%, %")
138-
case _ => args
139-
140-
val toAbstract: List[TermSymbol] =
141-
def anonFuns(tp: Type, n: Int, owner: Symbol): List[TermSymbol] =
142-
if n <= 0 then Nil
143-
else
144-
val defn.ContextFunctionType(argTpes, resTpe, isErased) = tp: @unchecked
145-
val anonFun = newAnonFun(
146-
owner,
147-
MethodType(if isErased then Nil else argTpes, resTpe),
148-
coord = owner.coord)
149-
anonFun :: anonFuns(resTpe, n - 1, anonFun)
150-
if memberCount == 0 then Nil
127+
def etaExpand(ref: Tree, args: List[Tree])(using Context): Tree =
128+
val toAbstract: List[TermSymbol] =
129+
def anonFuns(tp: Type, n: Int, owner: Symbol): List[TermSymbol] =
130+
if n <= 0 then Nil
151131
else
152-
val otherCount = contextResultCount(other)
153-
val resType = contextFunctionResultTypeAfter(member, otherCount)(using preErasureCtx)
154-
anonFuns(resType, memberCount - otherCount, owner)
155-
156-
def etaExpand(args: List[Tree], anonFuns: List[TermSymbol], owner: Symbol): Tree =
157-
anonFuns match
158-
case Nil =>
159-
val app = untpd.cpy.Apply(ref)(ref, args)
160-
assert(ctx.typer.isInstanceOf[Erasure.Typer])
161-
ctx.typer.typed(app, pt)
162-
// .changeOwnerAfter(origOwner, ctx.owner, erasurePhase.asInstanceOf[Erasure])
163-
//ref.appliedToTermArgs(args)//.changeOwner(ctx.owner, owner)
164-
case anonFun :: anonFuns1 =>
165-
val origType = anonFun.info
166-
anonFun.info = transformInfo(anonFun, anonFun.info)
167-
inContext(ctx.withOwner(owner)) {
168-
def lambdaBody(refss: List[List[Tree]]) =
169-
val refs :: Nil = refss: @unchecked
170-
val expandedRefs = refs.map(_.withSpan(owner.span.endPos)) match
171-
case (bunchedParam @ Ident(nme.ALLARGS)) :: Nil =>
172-
origType.firstParamTypes.indices.toList.map(n =>
173-
bunchedParam
174-
.select(nme.primitive.arrayApply)
175-
.appliedTo(Literal(Constant(n))))
176-
case refs1 => refs1
177-
etaExpand(args ::: expandedRefs, anonFuns1, anonFun)
178-
179-
val unadapted = Closure(anonFun, lambdaBody)
180-
cpy.Block(unadapted)(unadapted.stats,
181-
adaptClosure(unadapted.expr.asInstanceOf[Closure]))
182-
}
183-
184-
//println(i"forward $ref with $args%, %, owner = $owner, $pt")
185-
etaExpand(expandArgs(args, owner)(using preErasureCtx), toAbstract, owner)
186-
//.showing(i"forward $ref with $args%, %, owner = $owner, $pt = $result")
187-
end forwarder
132+
val defn.ContextFunctionType(argTpes, resTpe, isErased) = tp: @unchecked
133+
val anonFun = newAnonFun(
134+
owner,
135+
MethodType(if isErased then Nil else argTpes, resTpe),
136+
coord = owner.coord)
137+
anonFun :: anonFuns(resTpe, n - 1, anonFun)
138+
val otherCount = contextResultCount(other)
139+
val resType = contextFunctionResultTypeAfter(member, otherCount)(using preErasureCtx)
140+
anonFuns(resType, memberCount - otherCount, bridge)
141+
142+
def expand(args: List[Tree], anonFuns: List[TermSymbol], owner: Symbol): Tree =
143+
anonFuns match
144+
case Nil =>
145+
val app = untpd.cpy.Apply(ref)(ref, args)
146+
assert(ctx.typer.isInstanceOf[Erasure.Typer])
147+
ctx.typer.typed(app, member.info.finalResultType)
148+
case anonFun :: anonFuns1 =>
149+
val origType = anonFun.info
150+
anonFun.info = transformInfo(anonFun, anonFun.info)
151+
inContext(ctx.withOwner(owner)) {
152+
def lambdaBody(refss: List[List[Tree]]) =
153+
val refs :: Nil = refss: @unchecked
154+
val expandedRefs = refs.map(_.withSpan(owner.span.endPos)) match
155+
case (bunchedParam @ Ident(nme.ALLARGS)) :: Nil =>
156+
origType.firstParamTypes.indices.toList.map(n =>
157+
bunchedParam
158+
.select(nme.primitive.arrayApply)
159+
.appliedTo(Literal(Constant(n))))
160+
case refs1 => refs1
161+
expand(args ::: expandedRefs, anonFuns1, anonFun)
162+
163+
val unadapted = Closure(anonFun, lambdaBody)
164+
cpy.Block(unadapted)(unadapted.stats,
165+
adaptClosure(unadapted.expr.asInstanceOf[Closure]))
166+
}
167+
168+
expand(args, toAbstract, bridge)
169+
end etaExpand
188170

189171
def bridgeRhs(argss: List[List[Tree]]) =
190172
assert(argss.tail.isEmpty)
191173
val ref = This(root).select(member)
192174
if member.info.isParameterless then ref // can happen if `member` is a module
193-
else forwarder(ref, argss.head, bridge, member.info.finalResultType, other)
175+
else if memberCount == 0 then ref.appliedToTermArgs(argss.head)
176+
else etaExpand(ref, argss.head)
194177

195178
bridges += DefDef(bridge, bridgeRhs(_).withSpan(bridge.span))
196179
}

0 commit comments

Comments
 (0)