@@ -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,30 @@ 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
+ val args = treeInfo.dissectApplied(dd.rhs).argss.head
227
+ args.foreach(noApply.addOne)
228
+ case _=>
229
+ }
230
+ case _=>
231
+ }
219
232
// 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),
233
+ // Normally, we can unwrap `() => cbn` to `cbn` where `cbn` refers to a CBN argument (typically `cbn` is an Ident)
221
234
// because we know `cbn` will already be a `Function0` thunk. When we're targeting a SAM,
222
235
// 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 }
236
+ if (fun.vparams.isEmpty&& isByNameRef(fun.body)&& ! fun.attachments.contains[SAMFunction ]) {
237
+ noApply+= fun.body
238
+ fun.body
239
+ }
224
240
else if (forceExpandFunction|| inConstructorFlag!= 0 ) {
225
241
// Expand the function body into an anonymous class
226
- gen.expandFunction(localTyper)(fun, inConstructorFlag)
242
+ gen.expandFunction(localTyper)(fun, inConstructorFlag).tap(noApplyInExpansion)
227
243
}else {
228
244
val mustExpand = mustExpandFunction(fun)
229
245
// method definition with the same arguments, return type, and body as the original lambda
@@ -233,20 +249,23 @@ abstract class UnCurry extends InfoTransform
233
249
val newFun = deriveFunction(fun)(_=> localTyper.typedPos(fun.pos)(
234
250
gen.mkForwarder(gen.mkAttributedRef(liftedMethod.symbol), (fun.vparams map (_.symbol)):: Nil )
235
251
))
252
+ def typeNewFun = localTyper.typedPos(fun.pos)(Block (liftedMethod:: Nil ,super .transform(newFun)))
236
253
237
254
if (! mustExpand) {
238
255
liftedMethod.symbol.updateAttachment(DelambdafyTarget )
239
256
liftedMethod.updateAttachment(DelambdafyTarget )
257
+ typeNewFun
240
258
}
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
259
+ else typeNewFun match {
260
+ case typedNewFun@ Block (stats, expr : Function ) =>
261
+ val expansion = gen.expandFunction(localTyper)(expr, inConstructorFlag).tap(noApplyInExpansion)
262
+ // if ( expr.vparams.exists(p => isByNameParamType(p.symbol.info)))
263
+ // noApplyInExpansion(expansion )
264
+ treeCopy. Block (typedNewFun, stats, expansion)
265
+ case x => throw new MatchError (x)
248
266
}
249
267
}
268
+ }
250
269
251
270
def transformArgs (pos :Position ,fun :Symbol ,args :List [Tree ],params :List [Symbol ]): List [Tree ]= {
252
271
val isJava = fun.isJavaDefined
@@ -333,7 +352,7 @@ abstract class UnCurry extends InfoTransform
333
352
}
334
353
}
335
354
}
336
- val args1 = ListBuffer [Tree ]()
355
+ val args1 = ListBuffer .empty [Tree ]
337
356
args1++= args.iterator.take(params.length- 1 )
338
357
args1+= suffix setType params.last.info
339
358
args1.toList
@@ -344,12 +363,14 @@ abstract class UnCurry extends InfoTransform
344
363
345
364
map2Conserve(args1, params) { (arg, param)=>
346
365
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
366
+ else if (isByNameRef(arg)) {
367
+ // thunk does not need to be forced because it's a reference to a by-name arg passed to a by-name param
348
368
byNameArgs+= arg
349
369
arg setType functionType(Nil , arg.tpe)
350
370
}else {
351
371
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)
372
+ def canUseDirectly (qual :Tree )=
373
+ qual.tpe.typeSymbol.isSubClass(FunctionClass (0 ))&& treeInfo.isExprSafeToInline(qual)
353
374
argmatch {
354
375
// don't add a thunk for by-name argument if argument already is an application of
355
376
// a Function0. We can then remove the application and use the existing Function0.
@@ -456,7 +477,7 @@ abstract class UnCurry extends InfoTransform
456
477
else translateSynchronized(tree)match {
457
478
case dd@ DefDef (mods, name, tparams, _, tpt, rhs)=>
458
479
// Remove default argument trees from parameter ValDefs, scala/bug#4812
459
- val vparamssNoRhs = dd.vparamss mapConserve (_ mapConserve {p=>
480
+ val vparamssNoRhs = dd.vparamss. mapConserve(_. mapConserve { p=>
460
481
treeCopy.ValDef (p, p.mods, p.name, p.tpt,EmptyTree )
461
482
})
462
483
@@ -546,10 +567,10 @@ abstract class UnCurry extends InfoTransform
546
567
val tree1 = super .transform(tree)
547
568
if (isByNameRef(tree1)) {
548
569
val tree2 = tree1 setType functionType(Nil , tree1.tpe)
549
- return {
550
- if (noApply contains tree2) tree2
570
+ val tree3 =
571
+ if (noApply. contains( tree2) ) tree2
551
572
else localTyper.typedPos(tree1.pos)(Apply (Select (tree2, nme.apply),Nil ))
552
- }
573
+ return tree3
553
574
}
554
575
tree1
555
576
}