@@ -590,8 +590,7 @@ swift::isMemberAvailableOnExistential(Type baseTy, const ValueDecl *member) {
590590 return result;
591591}
592592
593- std::optional<
594- std::tuple<TypeVariableType *, Type, OpenedExistentialAdjustments>>
593+ std::optional<std::pair<TypeVariableType *, Type>>
595594swift::canOpenExistentialCallArgument (ValueDecl *callee, unsigned paramIdx,
596595 Type paramTy, Type argTy) {
597596 if (!callee)
@@ -623,24 +622,6 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
623622 if (!paramTy->hasTypeVariable ())
624623 return std::nullopt ;
625624
626- OpenedExistentialAdjustments adjustments;
627-
628- // The argument may be a "var" instead of a "let".
629- if (auto lv = argTy->getAs <LValueType>()) {
630- argTy = lv->getObjectType ();
631- adjustments |= OpenedExistentialAdjustmentFlags::LValue;
632- }
633-
634- // If the argument is inout, strip it off and we can add it back.
635- if (auto inOutArg = argTy->getAs <InOutType>()) {
636- argTy = inOutArg->getObjectType ();
637- adjustments |= OpenedExistentialAdjustmentFlags::InOut;
638- }
639-
640- // The argument type needs to be an existential type or metatype thereof.
641- if (!argTy->isAnyExistentialType ())
642- return std::nullopt ;
643-
644625 auto param = getParameterAt (callee, paramIdx);
645626 if (!param)
646627 return std::nullopt ;
@@ -649,26 +630,40 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
649630 if (param->isVariadic ())
650631 return std::nullopt ;
651632
652- // Look through an inout and an optional type on the parameter types.
653- auto formalParamTy = param->getInterfaceType ()->getInOutObjectType ()
654- ->lookThroughSingleOptionalType ();
655- // Look through an inout and optional types on the parameter.
656- paramTy = paramTy->getInOutObjectType ()->lookThroughSingleOptionalType ();
657-
658- // If the argument is of an existential metatype, look through the
659- // metatype on the parameter.
660- if (argTy->is <AnyMetatypeType>()) {
661- formalParamTy = formalParamTy->getMetatypeInstanceType ();
662- paramTy = paramTy->getMetatypeInstanceType ();
663- }
664-
665- // The parameter type must be a type variable.
666- auto paramTypeVar = paramTy->getAs <TypeVariableType>();
667- if (!paramTypeVar)
633+ // The rvalue argument type needs to be an existential type or metatype
634+ // thereof.
635+ const auto rValueArgTy = argTy->getWithoutSpecifierType ();
636+ if (!rValueArgTy->isAnyExistentialType ())
668637 return std::nullopt ;
669638
670- auto genericParam = formalParamTy->getAs <GenericTypeParamType>();
671- if (!genericParam)
639+ GenericTypeParamType *genericParam;
640+ TypeVariableType *typeVar;
641+ Type bindingTy;
642+
643+ std::tie (genericParam, typeVar, bindingTy) = [=] {
644+ // Look through an inout and optional type.
645+ Type genericParam = param->getInterfaceType ()
646+ ->getInOutObjectType ()
647+ ->lookThroughSingleOptionalType ();
648+ Type typeVar =
649+ paramTy->getInOutObjectType ()->lookThroughSingleOptionalType ();
650+
651+ Type bindingTy = rValueArgTy;
652+
653+ // Look through a metatype.
654+ if (genericParam->is <AnyMetatypeType>()) {
655+ genericParam = genericParam->getMetatypeInstanceType ();
656+ typeVar = typeVar->getMetatypeInstanceType ();
657+ bindingTy = bindingTy->getMetatypeInstanceType ();
658+ }
659+
660+ return std::tuple (genericParam->getAs <GenericTypeParamType>(),
661+ typeVar->getAs <TypeVariableType>(), bindingTy);
662+ }();
663+
664+ // The should have reached a type variable and corresponding generic
665+ // parameter.
666+ if (!typeVar || !genericParam)
672667 return std::nullopt ;
673668
674669 // Only allow opening the innermost generic parameters.
@@ -681,14 +676,11 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
681676 if (genericParam->getDepth () < genericSig->getMaxDepth ())
682677 return std::nullopt ;
683678
684- Type existentialTy;
685- if (auto existentialMetaTy = argTy->getAs <ExistentialMetatypeType>())
686- existentialTy = existentialMetaTy->getInstanceType ();
687- else
688- existentialTy = argTy;
689-
690- ASSERT (existentialTy->isAnyExistentialType ());
691-
679+ // The binding could be an existential metatype. Get the instance type for
680+ // conformance checks and to build an opened existential signature. If the
681+ // instance type is not an existential type, i.e., the metatype is nested,
682+ // bail out.
683+ const Type existentialTy = bindingTy->getMetatypeInstanceType ();
692684 if (!existentialTy->isExistentialType ())
693685 return std::nullopt ;
694686
@@ -726,7 +718,7 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
726718 if (referenceInfo.hasNonCovariantRef ())
727719 return std::nullopt ;
728720
729- return std::make_tuple (paramTypeVar, argTy, adjustments );
721+ return std::pair (typeVar, bindingTy );
730722}
731723
732724// / For each occurrence of a type **type** in `refTy` that satisfies
0 commit comments