@@ -21,6 +21,7 @@ import scala.collection.mutable.ListBuffer
21
21
import scala .reflect .internal .util .ListOfNil
22
22
import scala .tools .nsc .Reporting .WarningCategory
23
23
import scala .tools .nsc .symtab .Flags ._
24
+ import scala .util .chaining ._
24
25
25
26
/** - uncurry all symbol and tree types (@see UnCurryPhase) -- this includes normalizing all proper types.
26
27
* - for every curried parameter list: (ps_1) ... (ps_n) ==> (ps_1, ..., ps_n)
@@ -215,15 +216,32 @@ abstract class UnCurry extends InfoTransform
215
216
* new \$anon()
216
217
*
217
218
*/
218
- def transformFunction (fun :Function ): Tree =
219
+ def transformFunction (fun :Function ): Tree = {
220
+ // in the forwarding expansion def f(ps) = lifted_f(ps) ensure ps never applied
221
+ def noApplyInExpansion (expansion :Tree ): Unit =
222
+ expansionmatch {
223
+ case Block (ClassDef (_, _, _,Template (_, _, body)):: Nil , _)=>
224
+ body.lastmatch {
225
+ case dd :DefDef =>
226
+ treeInfo.dissectApplied(dd.rhs).argssmatch {
227
+ case args:: _=> args.foreach(noApply.addOne)
228
+ case _=>
229
+ }
230
+ case _=>
231
+ }
232
+ case _=>
233
+ }
219
234
// Undo eta expansion for parameterless and nullary methods, EXCEPT if `fun` targets a SAM.
220
- // Normally, we can unwrap `() => cbn` to `cbn` where `cbn` refers to a CBN argument (typically `cbn` is an Ident),
235
+ // Normally, we can unwrap `() => cbn` to `cbn` where `cbn` refers to a CBN argument (typically `cbn` is an Ident)
221
236
// because we know `cbn` will already be a `Function0` thunk. When we're targeting a SAM,
222
237
// the types don't align and we must preserve the function wrapper.
223
- if (fun.vparams.isEmpty&& isByNameRef(fun.body)&& fun.attachments.get[SAMFunction ].isEmpty) { noApply+= fun.body ; fun.body }
238
+ if (fun.vparams.isEmpty&& isByNameRef(fun.body)&& ! fun.attachments.contains[SAMFunction ]) {
239
+ noApply+= fun.body
240
+ fun.body
241
+ }
224
242
else if (forceExpandFunction|| inConstructorFlag!= 0 ) {
225
243
// Expand the function body into an anonymous class
226
- gen.expandFunction(localTyper)(fun, inConstructorFlag)
244
+ gen.expandFunction(localTyper)(fun, inConstructorFlag).tap(noApplyInExpansion)
227
245
}else {
228
246
val mustExpand = mustExpandFunction(fun)
229
247
// method definition with the same arguments, return type, and body as the original lambda
@@ -233,20 +251,23 @@ abstract class UnCurry extends InfoTransform
233
251
val newFun = deriveFunction(fun)(_=> localTyper.typedPos(fun.pos)(
234
252
gen.mkForwarder(gen.mkAttributedRef(liftedMethod.symbol), (fun.vparams map (_.symbol)):: Nil )
235
253
))
254
+ def typeNewFun = localTyper.typedPos(fun.pos)(Block (liftedMethod:: Nil ,super .transform(newFun)))
236
255
237
256
if (! mustExpand) {
238
257
liftedMethod.symbol.updateAttachment(DelambdafyTarget )
239
258
liftedMethod.updateAttachment(DelambdafyTarget )
259
+ typeNewFun
240
260
}
241
-
242
- val typedNewFun = localTyper.typedPos(fun.pos)( Block (liftedMethod :: Nil , super .transform(newFun)))
243
- if (mustExpand) {
244
- val Block (stats, expr : Function ) = typedNewFun : @ unchecked
245
- treeCopy. Block (typedNewFun, stats, gen.expandFunction(localTyper)(expr, inConstructorFlag) )
246
- } else {
247
- typedNewFun
261
+ else typeNewFun match {
262
+ case typedNewFun@ Block (stats, expr : Function ) =>
263
+ val expansion = gen.expandFunction(localTyper)(expr, inConstructorFlag).tap(noApplyInExpansion)
264
+ // if ( expr.vparams.exists(p => isByNameParamType(p.symbol.info)))
265
+ // noApplyInExpansion(expansion )
266
+ treeCopy. Block (typedNewFun, stats, expansion)
267
+ case x => throw new MatchError (x)
248
268
}
249
269
}
270
+ }
250
271
251
272
def transformArgs (pos :Position ,fun :Symbol ,args :List [Tree ],params :List [Symbol ]): List [Tree ]= {
252
273
val isJava = fun.isJavaDefined
@@ -333,7 +354,7 @@ abstract class UnCurry extends InfoTransform
333
354
}
334
355
}
335
356
}
336
- val args1 = ListBuffer [Tree ]()
357
+ val args1 = ListBuffer .empty [Tree ]
337
358
args1++= args.iterator.take(params.length- 1 )
338
359
args1+= suffix setType params.last.info
339
360
args1.toList
@@ -344,12 +365,14 @@ abstract class UnCurry extends InfoTransform
344
365
345
366
map2Conserve(args1, params) { (arg, param)=>
346
367
if (! isByNameParamType(param.info)) arg
347
- else if (isByNameRef(arg)) {// thunk does not need to be forced because it's a reference to a by-name arg passed to a by-name param
368
+ else if (isByNameRef(arg)) {
369
+ // thunk does not need to be forced because it's a reference to a by-name arg passed to a by-name param
348
370
byNameArgs+= arg
349
371
arg setType functionType(Nil , arg.tpe)
350
372
}else {
351
373
log(s " Argument ' $arg' at line ${arg.pos.line} is ${param.info} from ${fun.fullName}" )
352
- def canUseDirectly (qual :Tree )= qual.tpe.typeSymbol.isSubClass(FunctionClass (0 ))&& treeInfo.isExprSafeToInline(qual)
374
+ def canUseDirectly (qual :Tree )=
375
+ qual.tpe.typeSymbol.isSubClass(FunctionClass (0 ))&& treeInfo.isExprSafeToInline(qual)
353
376
argmatch {
354
377
// don't add a thunk for by-name argument if argument already is an application of
355
378
// a Function0. We can then remove the application and use the existing Function0.
@@ -456,7 +479,7 @@ abstract class UnCurry extends InfoTransform
456
479
else translateSynchronized(tree)match {
457
480
case dd@ DefDef (mods, name, tparams, _, tpt, rhs)=>
458
481
// Remove default argument trees from parameter ValDefs, scala/bug#4812
459
- val vparamssNoRhs = dd.vparamss mapConserve (_ mapConserve {p=>
482
+ val vparamssNoRhs = dd.vparamss. mapConserve(_. mapConserve { p=>
460
483
treeCopy.ValDef (p, p.mods, p.name, p.tpt,EmptyTree )
461
484
})
462
485
@@ -546,10 +569,10 @@ abstract class UnCurry extends InfoTransform
546
569
val tree1 = super .transform(tree)
547
570
if (isByNameRef(tree1)) {
548
571
val tree2 = tree1 setType functionType(Nil , tree1.tpe)
549
- return {
550
- if (noApply contains tree2) tree2
572
+ val tree3 =
573
+ if (noApply. contains( tree2) ) tree2
551
574
else localTyper.typedPos(tree1.pos)(Apply (Select (tree2, nme.apply),Nil ))
552
- }
575
+ return tree3
553
576
}
554
577
tree1
555
578
}