@@ -60,11 +60,12 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
6060
6161 /** If argument is complex, hoist it out into its own method and refer to the
6262 * method instead.
63- * @param arg The argument that might be hoisted
64- * @param cdef The definition of the constructor from which the call is made
63+ * @param arg The argument that might be hoisted
64+ * @param cdef The definition of the constructor from which the call is made
65+ * @param lifted Argument definitions that were lifted out in a call prefix
6566 * @return The argument after possible hoisting
6667 */
67- private def hoistSuperArg (arg : Tree , cdef : DefDef ): Tree = {
68+ private def hoistSuperArg (arg : Tree , cdef : DefDef , lifted : List [ Symbol ] ): Tree = {
6869 val constr = cdef.symbol
6970 lazy val origParams = // The parameters that can be accessed in the supercall
7071 if (constr == cls.primaryConstructor)
@@ -92,11 +93,14 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
9293 val argTypeWrtConstr = argType.widenTermRefExpr.subst(origParams, allParamRefs(constr.info))
9394 // argType with references to paramRefs of the primary constructor instead of
9495 // local parameter accessors
96+ val abstractedArgType =
97+ if lifted.isEmpty then argTypeWrtConstr
98+ else MethodType .fromSymbols(lifted, argTypeWrtConstr)
9599 newSymbol(
96100 owner = methOwner,
97101 name = SuperArgName .fresh(cls.name.toTermName),
98102 flags = Synthetic | Private | Method | staticFlag,
99- info = replaceResult(constr.info, argTypeWrtConstr ),
103+ info = replaceResult(constr.info, abstractedArgType ),
100104 coord = constr.coord
101105 ).enteredAfter(thisPhase)
102106 }
@@ -122,6 +126,7 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
122126 case ntp : NamedType =>
123127 val owner = ntp.symbol.maybeOwner
124128 (owner == cls || owner == constr) && ntp.symbol.isParamOrAccessor
129+ || lifted.contains(ntp.symbol)
125130 case _ => false
126131 }
127132
@@ -134,7 +139,7 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
134139 if pref.isType then pref.tpe.typeSymbol else pref.symbol)
135140 val tmap = new TreeTypeMap (
136141 typeMap = new TypeMap {
137- lazy val origToParam = origParams.zip(paramSyms).toMap
142+ lazy val origToParam = ( origParams ::: lifted) .zip(paramSyms).toMap
138143 def apply (tp : Type ) = tp match {
139144 case tp : NamedType if needsRewire(tp) =>
140145 origToParam.get(tp.symbol) match {
@@ -164,45 +169,52 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
164169 Nil
165170 }
166171 val (typeParams, termParams) = origParams.span(_.isType)
167- val res = ref(superMeth)
172+ var res = ref(superMeth)
168173 .appliedToTypes(typeParams.map(_.typeRef))
169174 .appliedToArgss(termParamRefs(constr.info, termParams))
175+ if lifted.nonEmpty then
176+ res = res.appliedToArgs(lifted.map(ref))
170177 report.log(i " hoist $arg, cls = $cls = $res" )
171178 res
172179 case _ => arg
173180 }
174181 }
175182
176- /** Hoist super arg from a lifted parameter that gets evaluated before the call */
177- def hoistSuperArgFromDef (paramDef : Tree , cdef : DefDef ): Tree = paramDef match
178- case vdef : ValDef =>
179- cpy.ValDef (vdef)(rhs = hoistSuperArg(vdef.rhs, cdef))
180- case ddef : DefDef =>
181- cpy.DefDef (ddef)(rhs = hoistSuperArg(ddef.rhs, cdef))
182- case _ =>
183- paramDef
184-
185183 /** Hoist complex arguments in super call out of the class. */
186- def hoistSuperArgsFromCall (superCall : Tree , cdef : DefDef ): Tree = superCall match
184+ def hoistSuperArgsFromCall (superCall : Tree , cdef : DefDef , lifted : mutable. ListBuffer [ Symbol ] ): Tree = superCall match
187185 case Block (defs, expr) =>
188- cpy.Block (superCall)(defs.mapconserve(hoistSuperArgFromDef(_, cdef)), hoistSuperArgsFromCall(expr, cdef))
186+ cpy.Block (superCall)(
187+ stats = defs.mapconserve {
188+ case vdef : ValDef =>
189+ try cpy.ValDef (vdef)(rhs = hoistSuperArg(vdef.rhs, cdef, lifted.toList))
190+ finally lifted += vdef.symbol
191+ case ddef : DefDef =>
192+ try cpy.DefDef (ddef)(rhs = hoistSuperArg(ddef.rhs, cdef, lifted.toList))
193+ finally lifted += ddef.symbol
194+ case stat =>
195+ stat
196+ },
197+ expr = hoistSuperArgsFromCall(expr, cdef, lifted))
189198 case Apply (fn, args) =>
190- cpy.Apply (superCall)(hoistSuperArgsFromCall(fn, cdef), args.mapconserve(hoistSuperArg(_, cdef)))
199+ cpy.Apply (superCall)(
200+ hoistSuperArgsFromCall(fn, cdef, lifted),
201+ args.mapconserve(hoistSuperArg(_, cdef, lifted.toList)))
191202 case _ =>
192203 superCall
193204
194205 /** Hoist complex arguments in this-constructor call of secondary constructor out of the class. */
195206 def hoistSuperArgsFromConstr (stat : Tree ): Tree = stat match {
196- case stat : DefDef if stat.symbol.isClassConstructor =>
197- cpy.DefDef (stat)(rhs =
198- stat.rhs match {
199- case Block (superCall :: stats, expr) =>
200- val superCall1 = hoistSuperArgsFromCall(superCall, stat)
201- if (superCall1 eq superCall) stat.rhs
202- else cpy.Block (stat.rhs)(superCall1 :: stats, expr)
207+ case constr : DefDef if constr.symbol.isClassConstructor =>
208+ val lifted = new mutable.ListBuffer [Symbol ]
209+ cpy.DefDef (constr)(rhs =
210+ constr.rhs match
211+ case Block (stats @ (superCall :: stats1), expr : Literal ) =>
212+ cpy.Block (constr.rhs)(
213+ stats.derivedCons(hoistSuperArgsFromCall(superCall, constr, lifted), stats1),
214+ expr)
203215 case _ =>
204- hoistSuperArgsFromCall(stat .rhs, stat )
205- } )
216+ hoistSuperArgsFromCall(constr .rhs, constr, lifted )
217+ )
206218 case _ =>
207219 stat
208220 }
@@ -212,7 +224,7 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
212224 tdef.rhs match {
213225 case impl @ Template (cdef, superCall :: others, _, _) =>
214226 val hoist = new Hoister (tdef.symbol)
215- val hoistedSuperCall = hoist.hoistSuperArgsFromCall(superCall, cdef)
227+ val hoistedSuperCall = hoist.hoistSuperArgsFromCall(superCall, cdef, new mutable. ListBuffer )
216228 val hoistedBody = impl.body.mapconserve(hoist.hoistSuperArgsFromConstr)
217229 if (hoist.superArgDefs.isEmpty) tdef
218230 else {
0 commit comments