Skip to content

Commit d7d63e9

Browse files
retronymadriaanm
authored andcommitted
Tidy up the Uncurry component of delambdafy
- Use tree factories that accept symbols and encapsulate ValDef creation - Use `gen.mkForwarder` to handle the conditional addition of `: _*` for varargs functions. We don't need to predicate this on `etaExpandKeepsStar`; the only place that need to do that is EtaExpansion.
1 parent a1da835 commit d7d63e9

File tree

2 files changed

+26
-42
lines changed

2 files changed

+26
-42
lines changed

src/compiler/scala/tools/nsc/transform/UnCurry.scala

Lines changed: 20 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -217,14 +217,14 @@ abstract class UnCurry extends InfoTransform
217217
// nullary or parameterless
218218
case fun1 if fun1 ne fun => fun1
219219
case _ =>
220-
val parents = addSerializable(abstractFunctionForFunctionType(fun.tpe))
221-
val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation
222-
anonClass setInfo ClassInfoType(parents, newScope, anonClass)
220+
val formals :+ restpe = fun.tpe.typeArgs
223221

224-
val targs = fun.tpe.typeArgs
225-
val (formals, restpe) = (targs.init, targs.last)
222+
def typedFunPos(t: Tree) = localTyper.typedPos(fun.pos)(t)
226223

227224
if (inlineFunctionExpansion) {
225+
val parents = addSerializable(abstractFunctionForFunctionType(fun.tpe))
226+
val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation
227+
anonClass setInfo ClassInfoType(parents, newScope, anonClass)
228228
val applyMethodDef = {
229229
val methSym = anonClass.newMethod(nme.apply, fun.pos, FINAL)
230230
val paramSyms = map2(formals, fun.vparams) {
@@ -235,7 +235,7 @@ abstract class UnCurry extends InfoTransform
235235
fun.vparams foreach (_.symbol.owner = methSym)
236236
fun.body changeOwner (fun.symbol -> methSym)
237237

238-
val body = localTyper.typedPos(fun.pos)(fun.body)
238+
val body = typedFunPos(fun.body)
239239
val methDef = DefDef(methSym, List(fun.vparams), body)
240240

241241
// Have to repack the type to avoid mismatches when existentials
@@ -244,7 +244,7 @@ abstract class UnCurry extends InfoTransform
244244
methDef
245245
}
246246

247-
localTyper.typedPos(fun.pos) {
247+
typedFunPos {
248248
Block(
249249
List(ClassDef(anonClass, NoMods, ListOfNil, List(applyMethodDef), fun.pos)),
250250
Typed(New(anonClass.tpe), TypeTree(fun.tpe)))
@@ -270,59 +270,37 @@ abstract class UnCurry extends InfoTransform
270270
* @bodyF function that turns the method symbol and list of value params
271271
* into a body for the method
272272
*/
273-
def createMethod(owner: Symbol, name: TermName, additionalFlags: Long)(bodyF: (Symbol, List[ValDef]) => Tree) = {
273+
def createMethod(owner: Symbol, name: TermName, additionalFlags: Long)(bodyF: Symbol => Tree) = {
274274
val methSym = owner.newMethod(name, fun.pos, FINAL | additionalFlags)
275-
val vparams = fun.vparams map (_.duplicate)
276275

277-
val paramSyms = map2(formals, vparams) {
276+
val paramSyms = map2(formals, fun.vparams) {
278277
(tp, vparam) => methSym.newSyntheticValueParam(tp, vparam.name)
279278
}
280-
foreach2(vparams, paramSyms){(valdef, sym) => valdef.symbol = sym}
281-
vparams foreach (_.symbol.owner = methSym)
282279

283-
val methodType = MethodType(paramSyms, restpe.deconst)
284-
methSym setInfo methodType
280+
methSym setInfo MethodType(paramSyms, restpe.deconst)
285281

286-
// TODO this is probably cleaner if bodyF only works with symbols rather than parameter ValDefs
287-
val tempBody = bodyF(methSym, vparams)
288-
val body = localTyper.typedPos(fun.pos)(tempBody)
289-
val methDef = DefDef(methSym, List(vparams), body)
282+
val body = typedFunPos(bodyF(methSym))
283+
val methDef = DefDef(methSym, body)
290284

291285
// Have to repack the type to avoid mismatches when existentials
292286
// appear in the result - see SI-4869.
293287
methDef.tpt setType localTyper.packedType(body, methSym).deconst
294288
methDef
295289
}
296290

297-
val methodFlags = ARTIFACT
291+
val funParams = fun.vparams map (_.symbol)
298292
// method definition with the same arguments, return type, and body as the original lambda
299-
val liftedMethod = createMethod(fun.symbol.owner, tpnme.ANON_FUN_NAME.toTermName, methodFlags){
300-
case(methSym, vparams) =>
301-
fun.body.substituteSymbols(fun.vparams map (_.symbol), vparams map (_.symbol))
293+
val liftedMethod = createMethod(fun.symbol.owner, nme.ANON_FUN_NAME, additionalFlags = ARTIFACT) {
294+
methSym =>
295+
fun.body.substituteSymbols(funParams, methSym.paramss.head)
302296
fun.body changeOwner (fun.symbol -> methSym)
303297
}
304298

305-
// callsite for the lifted method
306-
val args = fun.vparams map { vparam =>
307-
val ident = Ident(vparam.symbol)
308-
// if -Yeta-expand-keeps-star is turned on then T* types can get through. In order
309-
// to forward them we need to forward x: T* ascribed as "x:_*"
310-
if (settings.etaExpandKeepsStar && definitions.isRepeatedParamType(vparam.tpt.tpe))
311-
gen.wildcardStar(ident)
312-
else
313-
ident
314-
}
315-
316-
val funTyper = localTyper.typedPos(fun.pos) _
317-
318-
val liftedMethodCall = funTyper(Apply(liftedMethod.symbol, args:_*))
319-
320299
// new function whose body is just a call to the lifted method
321-
val newFun = treeCopy.Function(fun, fun.vparams, liftedMethodCall)
322-
funTyper(Block(
323-
List(funTyper(liftedMethod)),
324-
super.transform(newFun)
325-
))
300+
val newFun = deriveFunction(fun)(_ => typedFunPos(
301+
gen.mkForwarder(gen.mkAttributedRef(liftedMethod.symbol), funParams :: Nil)
302+
))
303+
typedFunPos(Block(liftedMethod, super.transform(newFun)))
326304
}
327305
}
328306
}

src/reflect/scala/reflect/internal/Trees.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,6 +1804,12 @@ trait Trees extends api.Trees {
18041804
case t =>
18051805
sys.error("Not a LabelDef: " + t + "/" + t.getClass)
18061806
}
1807+
def deriveFunction(func: Tree)(applyToRhs: Tree => Tree): Function = func match {
1808+
case Function(params0, rhs0) =>
1809+
treeCopy.Function(func, params0, applyToRhs(rhs0))
1810+
case t =>
1811+
sys.error("Not a Function: " + t + "/" + t.getClass)
1812+
}
18071813

18081814
// -------------- Classtags --------------------------------------------------------
18091815

0 commit comments

Comments
 (0)