@@ -518,7 +518,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
518518 // If argument is undefined and there is a default getter, call it
519519 val verifiedOrDefault = if (param.hasDefault) {
520520 js.If (js.BinaryOp (js.BinaryOp .=== , jsArg, js.Undefined ()), {
521- genCallDefaultGetter(exported.sym, i, param.sym.sourcePos, static) {
521+ genCallDefaultGetter(exported.sym, i, static) {
522522 prevArgsCount => result.take(prevArgsCount).toList.map(_.ref)
523523 }
524524 }, {
@@ -537,7 +537,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
537537 result.toList
538538 }
539539
540- private def genCallDefaultGetter (sym : Symbol , paramIndex : Int , paramPos : SourcePosition , static : Boolean )(
540+ private def genCallDefaultGetter (sym : Symbol , paramIndex : Int , static : Boolean )(
541541 previousArgsValues : Int => List [js.Tree ])(
542542 implicit pos : SourcePosition ): js.Tree = {
543543
@@ -562,29 +562,17 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
562562 report.error(
563563 " When overriding a native method with default arguments, " +
564564 " the overriding method must explicitly repeat the default arguments." ,
565- paramPos )
565+ sym.srcPos )
566566 js.Undefined ()
567567 }
568568 } else {
569569 genApplyMethod(targetTree, defaultGetter, defaultGetterArgs)
570570 }
571571 }
572572
573- private def targetSymForDefaultGetter (sym : Symbol ): Symbol = {
574- if (sym.isClassConstructor) {
575- /* /* Get the companion module class.
576- * For inner classes the sym.owner.companionModule can be broken,
577- * therefore companionModule is fetched at uncurryPhase.
578- */
579- val companionModule = enteringPhase(currentRun.namerPhase) {
580- sym.owner.companionModule
581- }
582- companionModule.moduleClass*/
583- sym.owner.companionModule.moduleClass
584- } else {
585- sym.owner
586- }
587- }
573+ private def targetSymForDefaultGetter (sym : Symbol ): Symbol =
574+ if (sym.isClassConstructor) sym.owner.companionModule.moduleClass
575+ else sym.owner
588576
589577 private def defaultGetterDenot (targetSym : Symbol , sym : Symbol , paramIndex : Int ): Denotation =
590578 targetSym.info.member(DefaultGetterName (sym.name.asTermName, paramIndex))
@@ -607,9 +595,8 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
607595 js.This ()(encodeClassType(sym.owner))
608596 }
609597
610- def boxIfNeeded (call : js.Tree ): js.Tree = {
598+ def boxIfNeeded (call : js.Tree ): js.Tree =
611599 box(call, atPhase(elimErasedValueTypePhase)(sym.info.resultType))
612- }
613600
614601 if (currentClassSym.isNonNativeJSClass) {
615602 assert(sym.owner == currentClassSym.get, sym.fullName)
@@ -627,19 +614,18 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
627614 private def genThrowTypeError (msg : String = " No matching overload" )(implicit pos : Position ): js.Tree =
628615 js.Throw (js.JSNew (js.JSGlobalRef (" TypeError" ), js.StringLiteral (msg) :: Nil ))
629616
630- private final class ParamSpec (val sym : Symbol , val info : Type ,
631- val isRepeated : Boolean , val hasDefault : Boolean ) {
617+ private final class ParamSpec (val info : Type , val isRepeated : Boolean , val hasDefault : Boolean ) {
632618 override def toString (): String =
633- s " ParamSpec( ${sym.name} , ${ info.show} , isRepeated = $isRepeated, hasDefault = $hasDefault) "
619+ i " ParamSpec( $info, isRepeated = $isRepeated, hasDefault = $hasDefault) "
634620 }
635621
636622 private object ParamSpec {
637- def apply (methodSym : Symbol , sym : Symbol , infoAtElimRepeated : Type , infoAtElimEVT : Type ,
623+ def apply (methodSym : Symbol , infoAtElimRepeated : Type , infoAtElimEVT : Type ,
638624 methodHasDefaultParams : Boolean , paramIndex : Int ): ParamSpec = {
639625 val isRepeated = infoAtElimRepeated.isRepeatedParam
640626 val info = if (isRepeated) infoAtElimRepeated.repeatedToSingle else infoAtElimEVT
641627 val hasDefault = methodHasDefaultParams && defaultGetterDenot(methodSym, paramIndex).exists
642- new ParamSpec (sym, info, isRepeated, hasDefault)
628+ new ParamSpec (info, isRepeated, hasDefault)
643629 }
644630 }
645631
@@ -650,73 +636,70 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
650636
651637 // params: List[ParamSpec] ; captureParams and captureParamsBack: List[js.ParamDef]
652638 val (params, captureParamsFront, captureParamsBack) = {
653- val paramNamessNow = sym.info.paramNamess
654- val paramInfosNow = sym.info.paramInfoss.flatten
655- val paramSymsAtElimRepeated = atPhase(elimRepeatedPhase)(sym.paramSymss.flatten.filter(_.isTerm))
656- val (paramNamessAtElimRepeated, paramInfosAtElimRepeated, methodHasDefaultParams) =
657- atPhase(elimRepeatedPhase)((sym.info.paramNamess, sym.info.paramInfoss.flatten, sym.hasDefaultParams))
658- val (paramNamessAtElimEVT, paramInfosAtElimEVT) =
659- atPhase(elimErasedValueTypePhase)((sym.info.paramNamess, sym.info.paramInfoss.flatten))
660-
661- def buildFormalParams ( paramSyms : List [ Symbol ], paramInfosAtElimRepeated : List [ Type ],
662- paramInfosAtElimEVT : List [Type ]): IndexedSeq [ParamSpec ] = {
639+ val (paramNamesAtElimRepeated, paramInfosAtElimRepeated, methodHasDefaultParams) =
640+ atPhase(elimRepeatedPhase)((sym.info.paramNamess.flatten, sym.info.paramInfoss.flatten, sym.hasDefaultParams))
641+ val (paramNamesAtElimEVT, paramInfosAtElimEVT) =
642+ atPhase(elimErasedValueTypePhase)((sym.info.firstParamNames, sym.info.firstParamTypes))
643+ val (paramNamesNow, paramInfosNow) =
644+ (sym.info.firstParamNames, sym.info.firstParamTypes)
645+
646+ val formalParamCount = paramInfosAtElimRepeated.size
647+
648+ def buildFormalParams ( formalParamInfosAtElimEVT : List [Type ]): IndexedSeq [ParamSpec ] = {
663649 (for {
664- (paramSym, infoAtElimRepeated, infoAtElimEVT, paramIndex) <-
665- paramSyms.lazyZip( paramInfosAtElimRepeated) .lazyZip(paramInfosAtElimEVT ).lazyZip(0 until paramSyms.size )
650+ (infoAtElimRepeated, infoAtElimEVT, paramIndex) <-
651+ paramInfosAtElimRepeated.lazyZip(formalParamInfosAtElimEVT ).lazyZip(0 until formalParamCount )
666652 } yield {
667- ParamSpec (sym, paramSym, infoAtElimRepeated, infoAtElimEVT, methodHasDefaultParams, paramIndex)
653+ ParamSpec (sym, infoAtElimRepeated, infoAtElimEVT, methodHasDefaultParams, paramIndex)
668654 }).toIndexedSeq
669655 }
670656
657+ def buildCaptureParams (namesAndInfosNow : List [(TermName , Type )]): List [js.ParamDef ] = {
658+ implicit val pos : Position = sym.span
659+ for ((name, info) <- namesAndInfosNow) yield {
660+ js.ParamDef (freshLocalIdent(name.mangledString), NoOriginalName , toIRType(info),
661+ mutable = false , rest = false )
662+ }
663+ }
664+
671665 if (! isConstructorOfNestedJSClass) {
672- // Easy case: all params are formal params.
673- assert(paramInfosAtElimRepeated.size == paramInfosAtElimEVT.size,
674- s " Found ${paramInfosAtElimRepeated.size} params entering elimRepeated but " +
675- s " ${paramInfosAtElimEVT.size} params entering elimErasedValueType for " +
676- s " non-lifted symbol ${sym.fullName}" )
677- val formalParams = buildFormalParams(paramSymsAtElimRepeated, paramInfosAtElimRepeated, paramInfosAtElimEVT)
666+ // Easy case: all params are formal params
667+ assert(paramInfosAtElimEVT.size == formalParamCount && paramInfosNow.size == formalParamCount,
668+ s " Found $formalParamCount params entering elimRepeated but ${paramInfosAtElimEVT.size} params entering " +
669+ s " elimErasedValueType and ${paramInfosNow.size} params at the back-end for non-lifted symbol ${sym.fullName}" )
670+ val formalParams = buildFormalParams(paramInfosAtElimEVT)
678671 (formalParams, Nil , Nil )
672+ } else if (formalParamCount == 0 ) {
673+ // Fast path: all params are capture params
674+ val captureParams = buildCaptureParams(paramNamesNow.zip(paramInfosNow))
675+ (IndexedSeq .empty, Nil , captureParams)
679676 } else {
680- /* The `arg$outer` param is added by erasure, following "instructions"
681- * by explicitouter, while the other capture params are added by
682- * lambdalift (between elimErasedValueType and now).
683- *
684- * Since we cannot reliably get Symbols for parameters created by
685- * intermediate phases, we have to perform some dance with the
686- * paramNamess and paramInfoss observed at some phases, combined with
687- * the paramSymss observed at elimRepeated.
677+ /* Slow path: we have to isolate formal params (which were already present at elimRepeated)
678+ * from capture params (which are later, typically by erasure and/or lambdalift).
688679 */
689680
690- val hasOuterParam = {
691- paramInfosAtElimEVT.size == paramInfosAtElimRepeated.size + 1 &&
692- paramNamessAtElimEVT.flatten.head == nme.OUTER
681+ def findStartOfFormalParamsIn (paramNames : List [TermName ]): Int = {
682+ val start = paramNames.indexOfSlice(paramNamesAtElimRepeated)
683+ assert(start >= 0 , s " could not find formal param names $paramNamesAtElimRepeated in $paramNames" )
684+ start
693685 }
694- assert(
695- hasOuterParam || paramInfosAtElimEVT.size == paramInfosAtElimRepeated.size,
696- s " Found ${paramInfosAtElimRepeated.size} params entering elimRepeated but " +
697- s " ${paramInfosAtElimEVT.size} params entering elimErasedValueType for " +
698- s " lifted constructor symbol ${sym.fullName}" )
699-
700- val startOfFormalParams = paramNamessNow.flatten.indexOfSlice(paramNamessAtElimRepeated.flatten)
701- val formalParamCount = paramInfosAtElimRepeated.size
702-
703- val nonOuterParamInfosAtElimEVT =
704- if (hasOuterParam) paramInfosAtElimEVT.tail
705- else paramInfosAtElimEVT
706- val formalParams = buildFormalParams(paramSymsAtElimRepeated, paramInfosAtElimRepeated, nonOuterParamInfosAtElimEVT)
707-
708- val paramNamesAndInfosNow = paramNamessNow.flatten.zip(paramInfosNow)
709- val (captureParamsFrontNow, restOfParamsNow) = paramNamesAndInfosNow.splitAt(startOfFormalParams)
710- val captureParamsBackNow = restOfParamsNow.drop(formalParamCount)
711686
712- def makeCaptureParamDef (nameAndInfo : (TermName , Type )): js.ParamDef = {
713- implicit val pos : Position = sym.span
714- js.ParamDef (freshLocalIdent(nameAndInfo._1.mangledString), NoOriginalName , toIRType(nameAndInfo._2),
715- mutable = false , rest = false )
716- }
687+ // Find the infos of formal params at elimEVT
688+ val startOfFormalParamsAtElimEVT = findStartOfFormalParamsIn(paramNamesAtElimEVT)
689+ val formalParamInfosAtElimEVT = paramInfosAtElimEVT.drop(startOfFormalParamsAtElimEVT).take(formalParamCount)
690+
691+ // Build the formal param specs from their infos at elimRepeated and elimEVT
692+ val formalParams = buildFormalParams(formalParamInfosAtElimEVT)
693+
694+ // Find the formal params now to isolate the capture params (before and after the formal params)
695+ val startOfFormalParamsNow = findStartOfFormalParamsIn(paramNamesNow)
696+ val paramNamesAndInfosNow = paramNamesNow.zip(paramInfosNow)
697+ val (captureParamsFrontNow, restOfParamsNow) = paramNamesAndInfosNow.splitAt(startOfFormalParamsNow)
698+ val captureParamsBackNow = restOfParamsNow.drop(formalParamCount)
717699
718- val captureParamsFront = captureParamsFrontNow.map(makeCaptureParamDef(_))
719- val captureParamsBack = captureParamsBackNow.map(makeCaptureParamDef(_))
700+ // Build the capture param defs from the isolated capture params
701+ val captureParamsFront = buildCaptureParams(captureParamsFrontNow)
702+ val captureParamsBack = buildCaptureParams(captureParamsBackNow)
720703
721704 (formalParams, captureParamsFront, captureParamsBack)
722705 }
0 commit comments