1
- package dotty .tools .dotc
1
+ package dotty .tools
2
+ package dotc
2
3
package transform
3
4
4
5
import core .Phases ._
@@ -299,9 +300,9 @@ object Erasure {
299
300
* e -> unbox(e, PT) if `PT` is a primitive type and `e` is not of primitive type
300
301
* e -> cast(e, PT) otherwise
301
302
*/
302
- def adaptToType (tree : Tree , pt : Type )(implicit ctx : Context ): Tree =
303
- if (pt. isInstanceOf [ FunProto ]) tree
304
- else tree.tpe.widen match {
303
+ def adaptToType (tree : Tree , pt : Type )(implicit ctx : Context ): Tree = pt match
304
+ case _ : FunProto | AnyFunctionProto => tree
305
+ case _ => tree.tpe.widen match {
305
306
case MethodType (Nil ) if tree.isTerm =>
306
307
adaptToType(tree.appliedToNone, pt)
307
308
case tpw =>
@@ -461,7 +462,7 @@ object Erasure {
461
462
462
463
def selectArrayMember (qual : Tree , erasedPre : Type ): Tree =
463
464
if erasedPre.isAnyRef then
464
- runtimeCallWithProtoArgs (tree.name.genericArrayOp, pt, qual)
465
+ runtimeCall (tree.name.genericArrayOp, qual :: Nil )
465
466
else if ! (qual.tpe <:< erasedPre) then
466
467
selectArrayMember(cast(qual, erasedPre), erasedPre)
467
468
else
@@ -507,20 +508,9 @@ object Erasure {
507
508
outer.path(toCls = tree.symbol)
508
509
}
509
510
510
- private def runtimeCallWithProtoArgs (name : Name , pt : Type , args : Tree * )(implicit ctx : Context ): Tree = {
511
+ private def runtimeCall (name : Name , args : List [ Tree ] )(implicit ctx : Context ): Tree =
511
512
val meth = defn.runtimeMethodRef(name)
512
- val followingParams = meth.symbol.info.firstParamTypes.drop(args.length)
513
- val followingArgs = protoArgs(pt, meth.widen).zipWithConserve(followingParams)(typedExpr).asInstanceOf [List [tpd.Tree ]]
514
- ref(meth).appliedToArgs(args.toList ++ followingArgs)
515
- }
516
-
517
- private def protoArgs (pt : Type , methTp : Type ): List [untpd.Tree ] = (pt, methTp) match {
518
- case (pt : FunProto , methTp : MethodType ) if methTp.isErasedMethod =>
519
- protoArgs(pt.resType, methTp.resType)
520
- case (pt : FunProto , methTp : MethodType ) =>
521
- pt.args ++ protoArgs(pt.resType, methTp.resType)
522
- case _ => Nil
523
- }
513
+ untpd.Apply (ref(meth), args.toList).withType(applyResultType(meth.widen.asInstanceOf [MethodType ], args))
524
514
525
515
override def typedTypeApply (tree : untpd.TypeApply , pt : Type )(implicit ctx : Context ): Tree = {
526
516
val ntree = interceptTypeApply(tree.asInstanceOf [TypeApply ])(ctx.withPhase(ctx.erasurePhase)).withSpan(tree.span)
@@ -538,36 +528,51 @@ object Erasure {
538
528
}
539
529
}
540
530
541
- /** Besides normal typing, this method collects all arguments
542
- * to a compacted function into a single argument of array type.
543
- */
544
- override def typedApply (tree : untpd.Apply , pt : Type )(implicit ctx : Context ): Tree = {
531
+ private def applyResultType (mt : MethodType , args : List [Tree ], bunchArgs : Boolean = false )(using Context ): Type =
532
+ if bunchArgs || mt.paramNames.length <= args.length then
533
+ mt.resultType
534
+ else
535
+ MethodType (mt.paramInfos.drop(args.length), mt.resultType)
536
+
537
+ /** Besides normal typing, this method does uncurrying and collects parameters
538
+ * to anonymous functions of arity > 22.
539
+ *
540
+ */
541
+ override def typedApply (tree : untpd.Apply , pt : Type )(implicit ctx : Context ): Tree =
545
542
val Apply (fun, args) = tree
546
543
if (fun.symbol == defn.cbnArg)
547
544
typedUnadapted(args.head, pt)
548
- else typedExpr(fun, FunProto (args, pt)(this , isUsingApply = false )) match {
549
- case fun1 : Apply => // arguments passed in prototype were already passed
550
- fun1
551
- case fun1 =>
552
- fun1.tpe.widen match {
553
- case mt : MethodType =>
554
- val outers = outer.args(fun.asInstanceOf [tpd.Tree ]) // can't use fun1 here because its type is already erased
555
- val ownArgs = if (mt.paramNames.nonEmpty && ! mt.isErasedMethod) args else Nil
556
- var args0 = outers ::: ownArgs ::: protoArgs(pt, tree.typeOpt)
557
-
558
- if (args0.length > MaxImplementedFunctionArity && mt.paramInfos.length == 1 ) {
559
- val bunchedArgs = untpd.JavaSeqLiteral (args0, TypeTree (defn.ObjectType ))
560
- .withType(defn.ArrayOf (defn.ObjectType ))
561
- args0 = bunchedArgs :: Nil
562
- }
563
- assert(args0 hasSameLengthAs mt.paramInfos)
564
- val args1 = args0.zipWithConserve(mt.paramInfos)(typedExpr)
565
- untpd.cpy.Apply (tree)(fun1, args1) withType mt.resultType
566
- case _ =>
567
- throw new MatchError (i " tree $tree has unexpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}" )
568
- }
569
- }
570
- }
545
+ else
546
+ val origFun = fun.asInstanceOf [tpd.Tree ]
547
+ val origFunType = origFun.tpe.widen(using preErasureCtx)
548
+ val outers = outer.args(origFun)
549
+ val ownArgs = if origFunType.isErasedMethod then Nil else args
550
+ val args0 = outers ::: ownArgs
551
+ val fun1 = typedExpr(fun, AnyFunctionProto )
552
+ fun1.tpe.widen match
553
+ case mt : MethodType =>
554
+ val bunchArgs = mt.paramInfos match
555
+ case JavaArrayType (elemType) :: Nil => // pre-test for efficiency
556
+ elemType.isRef(defn.ObjectClass ) // pre-test for efficiency
557
+ && origFunType.paramInfoss.flatten.length > MaxImplementedFunctionArity //
558
+ case _ => false
559
+ val args1 =
560
+ if bunchArgs then args0.map(typedExpr(_, defn.ObjectType ))
561
+ else args0.zipWithConserve(mt.paramInfos)(typedExpr).asInstanceOf [List [Tree ]]
562
+ val (fun2, args2) = fun1 match
563
+ case Apply (fun2, SeqLiteral (prevArgs, argTpt) :: _) if bunchArgs =>
564
+ (fun2, JavaSeqLiteral (prevArgs ++ args1, argTpt) :: Nil )
565
+ case Apply (fun2, prevArgs) =>
566
+ (fun2, prevArgs ++ args1)
567
+ case _ if bunchArgs =>
568
+ (fun1, JavaSeqLiteral (args1, TypeTree (defn.ObjectType )) :: Nil )
569
+ case _ =>
570
+ (fun1, args1)
571
+ untpd.cpy.Apply (tree)(fun2, args2).withType(applyResultType(mt, args1, bunchArgs))
572
+ case t =>
573
+ if args0.isEmpty then fun1
574
+ else throw new MatchError (i " tree $tree has unexpected type of function $fun1: $t, was $origFunType, args = $args0" )
575
+ end typedApply
571
576
572
577
// The following four methods take as the proto-type the erasure of the pre-existing type,
573
578
// if the original proto-type is not a value type.
0 commit comments