@@ -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,23 @@ 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
+
347
+ def mapOwner (sym : Symbol ): Symbol = {
348
+ val owner = sym.owner
349
+ if ((owner eq defn.AnyClass ) || (owner eq defn.AnyValClass )) {
350
+ assert(sym.isConstructor, s " ${sym.showLocated}" )
351
+ defn.ObjectClass
352
+ }
353
+ else if (defn.isUnimplementedFunctionClass(owner))
354
+ defn.FunctionXXLClass
355
+ else
356
+ owner
357
+ }
358
+
359
+ var sym = tree.symbol
360
+ val owner = mapOwner(sym)
361
+ if (owner ne sym.owner) sym = owner.info.decl(sym.name).symbol
362
+ assert(sym.exists, owner)
336
363
337
364
def select (qual : Tree , sym : Symbol ): Tree = {
338
365
val name = tree.typeOpt match {
@@ -366,11 +393,7 @@ object Erasure extends TypeTestsCasts{
366
393
def recur (qual : Tree ): Tree = {
367
394
val qualIsPrimitive = qual.tpe.widen.isPrimitiveValueType
368
395
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)
396
+ if (qualIsPrimitive && ! symIsPrimitive || qual.tpe.widenDealias.isErasedValueType)
374
397
recur(box(qual))
375
398
else if (! qualIsPrimitive && symIsPrimitive)
376
399
recur(unbox(qual, sym.owner.typeRef))
@@ -423,6 +446,9 @@ object Erasure extends TypeTestsCasts{
423
446
}
424
447
}
425
448
449
+ /** Besides normal typing, this method collects all arguments
450
+ * to a compacted function into a single argument of array type.
451
+ */
426
452
override def typedApply (tree : untpd.Apply , pt : Type )(implicit ctx : Context ): Tree = {
427
453
val Apply (fun, args) = tree
428
454
if (fun.symbol == defn.dummyApply)
@@ -434,7 +460,13 @@ object Erasure extends TypeTestsCasts{
434
460
fun1.tpe.widen match {
435
461
case mt : MethodType =>
436
462
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)
463
+ var args0 = outers ::: args ++ protoArgs(pt)
464
+ if (args0.length > MaxImplementedFunctionArity && mt.paramTypes.length == 1 ) {
465
+ val bunchedArgs = untpd.JavaSeqLiteral (args0, TypeTree (defn.ObjectType ))
466
+ .withType(defn.ArrayOf (defn.ObjectType ))
467
+ args0 = bunchedArgs :: Nil
468
+ }
469
+ val args1 = args0.zipWithConserve(mt.paramTypes)(typedExpr)
438
470
untpd.cpy.Apply (tree)(fun1, args1) withType mt.resultType
439
471
case _ =>
440
472
throw new MatchError (i " tree $tree has unexpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}" )
@@ -470,18 +502,36 @@ object Erasure extends TypeTestsCasts{
470
502
super .typedValDef(untpd.cpy.ValDef (vdef)(
471
503
tpt = untpd.TypedSplice (TypeTree (sym.info).withPos(vdef.tpt.pos))), sym)
472
504
505
+ /** Besides normal typing, this function also compacts anonymous functions
506
+ * with more than `MaxImplementedFunctionArity` parameters to ise a single
507
+ * parameter of type `[]Object`.
508
+ */
473
509
override def typedDefDef (ddef : untpd.DefDef , sym : Symbol )(implicit ctx : Context ) = {
474
510
val restpe =
475
511
if (sym.isConstructor) defn.UnitType
476
512
else sym.info.resultType
513
+ var vparamss1 = (outer.paramDefs(sym) ::: ddef.vparamss.flatten) :: Nil
514
+ var rhs1 = ddef.rhs match {
515
+ case id @ Ident (nme.WILDCARD ) => untpd.TypedSplice (id.withType(restpe))
516
+ case _ => ddef.rhs
517
+ }
518
+ if (sym.isAnonymousFunction && vparamss1.head.length > MaxImplementedFunctionArity ) {
519
+ val bunchedParam = ctx.newSymbol(sym, nme.ALLARGS , Flags .TermParam , JavaArrayType (defn.ObjectType ))
520
+ def selector (n : Int ) = ref(bunchedParam)
521
+ .select(defn.Array_apply )
522
+ .appliedTo(Literal (Constant (n)))
523
+ val paramDefs = vparamss1.head.zipWithIndex.map {
524
+ case (paramDef, idx) =>
525
+ assignType(untpd.cpy.ValDef (paramDef)(rhs = selector(idx)), paramDef.symbol)
526
+ }
527
+ vparamss1 = (tpd.ValDef (bunchedParam) :: Nil ) :: Nil
528
+ rhs1 = untpd.Block (paramDefs, rhs1)
529
+ }
477
530
val ddef1 = untpd.cpy.DefDef (ddef)(
478
531
tparams = Nil ,
479
- vparamss = (outer.paramDefs(sym) ::: ddef.vparamss.flatten) :: Nil ,
532
+ vparamss = vparamss1 ,
480
533
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
- })
534
+ rhs = rhs1)
485
535
super .typedDefDef(ddef1, sym)
486
536
}
487
537
0 commit comments