@@ -590,8 +590,7 @@ swift::isMemberAvailableOnExistential(Type baseTy, const ValueDecl *member) {
590
590
return result;
591
591
}
592
592
593
- std::optional<
594
- std::tuple<TypeVariableType *, Type, OpenedExistentialAdjustments>>
593
+ std::optional<std::pair<TypeVariableType *, Type>>
595
594
swift::canOpenExistentialCallArgument (ValueDecl *callee, unsigned paramIdx,
596
595
Type paramTy, Type argTy) {
597
596
if (!callee)
@@ -623,24 +622,6 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
623
622
if (!paramTy->hasTypeVariable ())
624
623
return std::nullopt;
625
624
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
-
644
625
auto param = getParameterAt (callee, paramIdx);
645
626
if (!param)
646
627
return std::nullopt;
@@ -649,26 +630,40 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
649
630
if (param->isVariadic ())
650
631
return std::nullopt;
651
632
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 ())
668
637
return std::nullopt;
669
638
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)
672
667
return std::nullopt;
673
668
674
669
// Only allow opening the innermost generic parameters.
@@ -681,14 +676,11 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
681
676
if (genericParam->getDepth () < genericSig->getMaxDepth ())
682
677
return std::nullopt;
683
678
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 ();
692
684
if (!existentialTy->isExistentialType ())
693
685
return std::nullopt;
694
686
@@ -726,7 +718,7 @@ swift::canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
726
718
if (referenceInfo.hasNonCovariantRef ())
727
719
return std::nullopt;
728
720
729
- return std::make_tuple (paramTypeVar, argTy, adjustments );
721
+ return std::pair (typeVar, bindingTy );
730
722
}
731
723
732
724
// / For each occurrence of a type **type** in `refTy` that satisfies
0 commit comments