@@ -13,6 +13,7 @@ import core.StdNames._
13
13
import core .NameOps ._
14
14
import core .Decorators ._
15
15
import core .Constants ._
16
+ import core .Definitions ._
16
17
import typer .NoChecking
17
18
import typer .ProtoTypes ._
18
19
import typer .ErrorReporting ._
@@ -36,9 +37,17 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
36
37
37
38
def transform (ref : SingleDenotation )(implicit ctx : Context ): SingleDenotation = ref match {
38
39
case ref : SymDenotation =>
40
+ def isCompacted (sym : Symbol ) =
41
+ sym.isAnonymousFunction && {
42
+ sym.info(ctx.withPhase(ctx.phase.next)) match {
43
+ case MethodType (nme.ALLARGS :: Nil , _) => true
44
+ case _ => false
45
+ }
46
+ }
47
+
39
48
assert(ctx.phase == this , s " transforming $ref at ${ctx.phase}" )
40
49
if (ref.symbol eq defn.ObjectClass ) {
41
- // Aftre erasure, all former Any members are now Object members
50
+ // After erasure, all former Any members are now Object members
42
51
val ClassInfo (pre, _, ps, decls, selfInfo) = ref.info
43
52
val extendedScope = decls.cloneScope
44
53
for (decl <- defn.AnyClass .classInfo.decls)
@@ -59,7 +68,10 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
59
68
val oldInfo = ref.info
60
69
val newInfo = transformInfo(ref.symbol, oldInfo)
61
70
val oldFlags = ref.flags
62
- val newFlags = ref.flags &~ Flags .HasDefaultParams // HasDefaultParams needs to be dropped because overriding might become overloading
71
+ val newFlags =
72
+ if (oldSymbol.is(Flags .TermParam ) && isCompacted(oldSymbol.owner)) oldFlags &~ Flags .Param
73
+ else oldFlags &~ Flags .HasDefaultParams // HasDefaultParams needs to be dropped because overriding might become overloading
74
+
63
75
// TODO: define derivedSymDenotation?
64
76
if ((oldSymbol eq newSymbol) && (oldOwner eq newOwner) && (oldInfo eq newInfo) && (oldFlags == newFlags)) ref
65
77
else {
@@ -331,8 +343,20 @@ object Erasure extends TypeTestsCasts{
331
343
* e.m -> e.[]m if `m` is an array operation other than `clone`.
332
344
*/
333
345
override def typedSelect (tree : untpd.Select , pt : Type )(implicit ctx : Context ): Tree = {
334
- val sym = tree.symbol
335
- assert(sym.exists, tree.show)
346
+ val oldSym = tree.symbol
347
+ assert(oldSym.exists)
348
+ val oldOwner = oldSym.owner
349
+ val owner =
350
+ if ((oldOwner eq defn.AnyClass ) || (oldOwner eq defn.AnyValClass )) {
351
+ assert(oldSym.isConstructor, s " ${oldSym.showLocated}" )
352
+ defn.ObjectClass
353
+ }
354
+ else if (defn.isUnimplementedFunctionClass(oldOwner))
355
+ defn.FunctionXXLClass
356
+ else
357
+ oldOwner
358
+ val sym = if (owner eq oldOwner) oldSym else owner.info.decl(oldSym.name).symbol
359
+ assert(sym.exists, owner)
336
360
337
361
def select (qual : Tree , sym : Symbol ): Tree = {
338
362
val name = tree.typeOpt match {
@@ -366,11 +390,7 @@ object Erasure extends TypeTestsCasts{
366
390
def recur (qual : Tree ): Tree = {
367
391
val qualIsPrimitive = qual.tpe.widen.isPrimitiveValueType
368
392
val symIsPrimitive = sym.owner.isPrimitiveValueClass
369
- if ((sym.owner eq defn.AnyClass ) || (sym.owner eq defn.AnyValClass )) {
370
- assert(sym.isConstructor, s " ${sym.showLocated}" )
371
- select(qual, defn.ObjectClass .info.decl(sym.name).symbol)
372
- }
373
- else if (qualIsPrimitive && ! symIsPrimitive || qual.tpe.widenDealias.isErasedValueType)
393
+ if (qualIsPrimitive && ! symIsPrimitive || qual.tpe.widenDealias.isErasedValueType)
374
394
recur(box(qual))
375
395
else if (! qualIsPrimitive && symIsPrimitive)
376
396
recur(unbox(qual, sym.owner.typeRef))
@@ -423,6 +443,9 @@ object Erasure extends TypeTestsCasts{
423
443
}
424
444
}
425
445
446
+ /** Besides notmal typing, this method collects all arguments
447
+ * to a compacted function into a single argument of array type.
448
+ */
426
449
override def typedApply (tree : untpd.Apply , pt : Type )(implicit ctx : Context ): Tree = {
427
450
val Apply (fun, args) = tree
428
451
if (fun.symbol == defn.dummyApply)
@@ -434,7 +457,13 @@ object Erasure extends TypeTestsCasts{
434
457
fun1.tpe.widen match {
435
458
case mt : MethodType =>
436
459
val outers = outer.args(fun.asInstanceOf [tpd.Tree ]) // can't use fun1 here because its type is already erased
437
- val args1 = (outers ::: args ++ protoArgs(pt)).zipWithConserve(mt.paramTypes)(typedExpr)
460
+ var args0 = outers ::: args ++ protoArgs(pt)
461
+ if (args0.length > MaxImplementedFunctionArity && mt.paramTypes.length == 1 ) {
462
+ val bunchedArgs = untpd.JavaSeqLiteral (args0, TypeTree (defn.ObjectType ))
463
+ .withType(defn.ArrayOf (defn.ObjectType ))
464
+ args0 = bunchedArgs :: Nil
465
+ }
466
+ val args1 = args0.zipWithConserve(mt.paramTypes)(typedExpr)
438
467
untpd.cpy.Apply (tree)(fun1, args1) withType mt.resultType
439
468
case _ =>
440
469
throw new MatchError (i " tree $tree has unexpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}" )
@@ -470,18 +499,36 @@ object Erasure extends TypeTestsCasts{
470
499
super .typedValDef(untpd.cpy.ValDef (vdef)(
471
500
tpt = untpd.TypedSplice (TypeTree (sym.info).withPos(vdef.tpt.pos))), sym)
472
501
502
+ /** Besides normal typing, this function also compacts anonymous functions
503
+ * with more than `MaxImplementedFunctionArity` parameters to ise a single
504
+ * parameter of type `[]Object`.
505
+ */
473
506
override def typedDefDef (ddef : untpd.DefDef , sym : Symbol )(implicit ctx : Context ) = {
474
507
val restpe =
475
508
if (sym.isConstructor) defn.UnitType
476
509
else sym.info.resultType
510
+ var vparamss1 = (outer.paramDefs(sym) ::: ddef.vparamss.flatten) :: Nil
511
+ var rhs1 = ddef.rhs match {
512
+ case id @ Ident (nme.WILDCARD ) => untpd.TypedSplice (id.withType(restpe))
513
+ case _ => ddef.rhs
514
+ }
515
+ if (sym.isAnonymousFunction && vparamss1.head.length > MaxImplementedFunctionArity ) {
516
+ val bunchedParam = ctx.newSymbol(sym, nme.ALLARGS , Flags .TermParam , JavaArrayType (defn.ObjectType ))
517
+ def selector (n : Int ) = ref(bunchedParam)
518
+ .select(defn.Array_apply )
519
+ .appliedTo(Literal (Constant (n)))
520
+ val paramDefs = vparamss1.head.zipWithIndex.map {
521
+ case (paramDef, idx) =>
522
+ assignType(untpd.cpy.ValDef (paramDef)(rhs = selector(idx)), paramDef.symbol)
523
+ }
524
+ vparamss1 = (tpd.ValDef (bunchedParam) :: Nil ) :: Nil
525
+ rhs1 = untpd.Block (paramDefs, rhs1)
526
+ }
477
527
val ddef1 = untpd.cpy.DefDef (ddef)(
478
528
tparams = Nil ,
479
- vparamss = (outer.paramDefs(sym) ::: ddef.vparamss.flatten) :: Nil ,
529
+ vparamss = vparamss1 ,
480
530
tpt = untpd.TypedSplice (TypeTree (restpe).withPos(ddef.tpt.pos)),
481
- rhs = ddef.rhs match {
482
- case id @ Ident (nme.WILDCARD ) => untpd.TypedSplice (id.withType(restpe))
483
- case _ => ddef.rhs
484
- })
531
+ rhs = rhs1)
485
532
super .typedDefDef(ddef1, sym)
486
533
}
487
534
0 commit comments