@@ -60,11 +60,12 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
60
60
61
61
/** If argument is complex, hoist it out into its own method and refer to the
62
62
* 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
65
66
* @return The argument after possible hoisting
66
67
*/
67
- private def hoistSuperArg (arg : Tree , cdef : DefDef ): Tree = {
68
+ private def hoistSuperArg (arg : Tree , cdef : DefDef , lifted : List [ Symbol ] ): Tree = {
68
69
val constr = cdef.symbol
69
70
lazy val origParams = // The parameters that can be accessed in the supercall
70
71
if (constr == cls.primaryConstructor)
@@ -92,11 +93,14 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
92
93
val argTypeWrtConstr = argType.widenTermRefExpr.subst(origParams, allParamRefs(constr.info))
93
94
// argType with references to paramRefs of the primary constructor instead of
94
95
// local parameter accessors
96
+ val abstractedArgType =
97
+ if lifted.isEmpty then argTypeWrtConstr
98
+ else MethodType .fromSymbols(lifted, argTypeWrtConstr)
95
99
newSymbol(
96
100
owner = methOwner,
97
101
name = SuperArgName .fresh(cls.name.toTermName),
98
102
flags = Synthetic | Private | Method | staticFlag,
99
- info = replaceResult(constr.info, argTypeWrtConstr ),
103
+ info = replaceResult(constr.info, abstractedArgType ),
100
104
coord = constr.coord
101
105
).enteredAfter(thisPhase)
102
106
}
@@ -122,6 +126,7 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
122
126
case ntp : NamedType =>
123
127
val owner = ntp.symbol.maybeOwner
124
128
(owner == cls || owner == constr) && ntp.symbol.isParamOrAccessor
129
+ || lifted.contains(ntp.symbol)
125
130
case _ => false
126
131
}
127
132
@@ -134,7 +139,7 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
134
139
if pref.isType then pref.tpe.typeSymbol else pref.symbol)
135
140
val tmap = new TreeTypeMap (
136
141
typeMap = new TypeMap {
137
- lazy val origToParam = origParams.zip(paramSyms).toMap
142
+ lazy val origToParam = ( origParams ::: lifted) .zip(paramSyms).toMap
138
143
def apply (tp : Type ) = tp match {
139
144
case tp : NamedType if needsRewire(tp) =>
140
145
origToParam.get(tp.symbol) match {
@@ -164,45 +169,52 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
164
169
Nil
165
170
}
166
171
val (typeParams, termParams) = origParams.span(_.isType)
167
- val res = ref(superMeth)
172
+ var res = ref(superMeth)
168
173
.appliedToTypes(typeParams.map(_.typeRef))
169
174
.appliedToArgss(termParamRefs(constr.info, termParams))
175
+ if lifted.nonEmpty then
176
+ res = res.appliedToArgs(lifted.map(ref))
170
177
report.log(i " hoist $arg, cls = $cls = $res" )
171
178
res
172
179
case _ => arg
173
180
}
174
181
}
175
182
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
-
185
183
/** 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
187
185
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))
189
198
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)))
191
202
case _ =>
192
203
superCall
193
204
194
205
/** Hoist complex arguments in this-constructor call of secondary constructor out of the class. */
195
206
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)
203
215
case _ =>
204
- hoistSuperArgsFromCall(stat .rhs, stat )
205
- } )
216
+ hoistSuperArgsFromCall(constr .rhs, constr, lifted )
217
+ )
206
218
case _ =>
207
219
stat
208
220
}
@@ -212,7 +224,7 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase
212
224
tdef.rhs match {
213
225
case impl @ Template (cdef, superCall :: others, _, _) =>
214
226
val hoist = new Hoister (tdef.symbol)
215
- val hoistedSuperCall = hoist.hoistSuperArgsFromCall(superCall, cdef)
227
+ val hoistedSuperCall = hoist.hoistSuperArgsFromCall(superCall, cdef, new mutable. ListBuffer )
216
228
val hoistedBody = impl.body.mapconserve(hoist.hoistSuperArgsFromConstr)
217
229
if (hoist.superArgDefs.isEmpty) tdef
218
230
else {
0 commit comments