1- package dotty .tools .dotc
1+ package dotty .tools
2+ package dotc
23package transform
34
45import core .Phases ._
@@ -299,9 +300,9 @@ object Erasure {
299300 * e -> unbox(e, PT) if `PT` is a primitive type and `e` is not of primitive type
300301 * e -> cast(e, PT) otherwise
301302 */
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 {
305306 case MethodType (Nil ) if tree.isTerm =>
306307 adaptToType(tree.appliedToNone, pt)
307308 case tpw =>
@@ -461,7 +462,7 @@ object Erasure {
461462
462463 def selectArrayMember (qual : Tree , erasedPre : Type ): Tree =
463464 if erasedPre.isAnyRef then
464- runtimeCallWithProtoArgs (tree.name.genericArrayOp, pt, qual)
465+ runtimeCall (tree.name.genericArrayOp, qual :: Nil )
465466 else if ! (qual.tpe <:< erasedPre) then
466467 selectArrayMember(cast(qual, erasedPre), erasedPre)
467468 else
@@ -507,20 +508,9 @@ object Erasure {
507508 outer.path(toCls = tree.symbol)
508509 }
509510
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 =
511512 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))
524514
525515 override def typedTypeApply (tree : untpd.TypeApply , pt : Type )(implicit ctx : Context ): Tree = {
526516 val ntree = interceptTypeApply(tree.asInstanceOf [TypeApply ])(ctx.withPhase(ctx.erasurePhase)).withSpan(tree.span)
@@ -538,36 +528,51 @@ object Erasure {
538528 }
539529 }
540530
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 =
545542 val Apply (fun, args) = tree
546543 if (fun.symbol == defn.cbnArg)
547544 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
571576
572577 // The following four methods take as the proto-type the erasure of the pre-existing type,
573578 // if the original proto-type is not a value type.
0 commit comments