@@ -1316,6 +1316,14 @@ Type ConstraintSystem::getFixedTypeRecursive(Type type, TypeMatchOptions &flags,
13161316 return getFixedTypeRecursive (simplified, flags, wantRValue);
13171317 }
13181318
1319+ if (auto metatype = type->getAs <AnyMetatypeType>()) {
1320+ auto simplified = simplifyType (type);
1321+ if (simplified.getPointer () == type.getPointer ())
1322+ return type;
1323+
1324+ return getFixedTypeRecursive (simplified, flags, wantRValue);
1325+ }
1326+
13191327 if (auto typeVar = type->getAs <TypeVariableType>()) {
13201328 if (auto fixed = getFixedType (typeVar))
13211329 return getFixedTypeRecursive (fixed, flags, wantRValue);
@@ -2420,10 +2428,25 @@ Type constraints::typeEraseOpenedArchetypesWithRoot(
24202428 /* force=*/ true );
24212429}
24222430
2431+ static bool isExistentialMemberAccessWithExplicitBaseExpression (
2432+ Type baseInstanceTy, ValueDecl *member, ConstraintLocator *locator,
2433+ bool isDynamicLookup) {
2434+ if (isDynamicLookup) {
2435+ return false ;
2436+ }
2437+
2438+ // '.x' does not have an explicit base expression.
2439+ if (locator->isLastElement <LocatorPathElt::UnresolvedMember>()) {
2440+ return false ;
2441+ }
2442+
2443+ return baseInstanceTy->isExistentialType () &&
2444+ member->getDeclContext ()->getSelfProtocolDecl ();
2445+ }
2446+
24232447Type ConstraintSystem::getMemberReferenceTypeFromOpenedType (
24242448 Type &openedType, Type baseObjTy, ValueDecl *value, DeclContext *outerDC,
2425- ConstraintLocator *locator, bool hasAppliedSelf,
2426- bool isStaticMemberRefOnProtocol, bool isDynamicResult,
2449+ ConstraintLocator *locator, bool hasAppliedSelf, bool isDynamicLookup,
24272450 OpenedTypeMap &replacements) {
24282451 Type type = openedType;
24292452
@@ -2450,7 +2473,7 @@ Type ConstraintSystem::getMemberReferenceTypeFromOpenedType(
24502473
24512474 // Check if we need to apply a layer of optionality to the uncurried type.
24522475 if (!isRequirementOrWitness (locator)) {
2453- if (isDynamicResult || value->getAttrs ().hasAttribute <OptionalAttr>()) {
2476+ if (isDynamicLookup || value->getAttrs ().hasAttribute <OptionalAttr>()) {
24542477 const auto applyOptionality = [&](FunctionType *fnTy) -> Type {
24552478 Type resultTy;
24562479 // Optional and dynamic subscripts are a special case, because the
@@ -2490,12 +2513,13 @@ Type ConstraintSystem::getMemberReferenceTypeFromOpenedType(
24902513 type = type->replaceSelfParameterType (baseObjTy);
24912514 }
24922515
2493- // Superficially, protocol members with an existential base are accessed
2494- // directly on the existential, and not an opened archetype, and we may have
2495- // to adjust the type of the reference (e.g. covariant 'Self' type-erasure) to
2496- // support certain accesses.
2497- if (!isStaticMemberRefOnProtocol && !isDynamicResult &&
2498- baseObjTy->isExistentialType () && outerDC->getSelfProtocolDecl () &&
2516+ // From the user perspective, protocol members that are accessed with an
2517+ // existential base are accessed directly on the existential, and not an
2518+ // opened archetype, so the type of the member reference must be abstracted
2519+ // away (upcast) from context-specific types like `Self` in covariant
2520+ // position.
2521+ if (isExistentialMemberAccessWithExplicitBaseExpression (
2522+ baseObjTy, value, locator, isDynamicLookup) &&
24992523 // If there are no type variables, there were no references to 'Self'.
25002524 type->hasTypeVariable ()) {
25012525 const auto selfGP = cast<GenericTypeParamType>(
@@ -2504,13 +2528,6 @@ Type ConstraintSystem::getMemberReferenceTypeFromOpenedType(
25042528
25052529 type = typeEraseOpenedExistentialReference (type, baseObjTy, openedTypeVar,
25062530 TypePosition::Covariant);
2507-
2508- Type contextualTy;
2509-
2510- if (auto *anchor = getAsExpr (simplifyLocatorToAnchor (locator))) {
2511- contextualTy =
2512- getContextualType (getParentExpr (anchor), /* forConstraint=*/ false );
2513- }
25142531 }
25152532
25162533 // Construct an idealized parameter type of the initializer associated
@@ -2591,12 +2608,9 @@ bool ConstraintSystem::isPartialApplication(ConstraintLocator *locator) {
25912608 return level < (baseTy->is <MetatypeType>() ? 1 : 2 );
25922609}
25932610
2594- DeclReferenceType
2595- ConstraintSystem::getTypeOfMemberReference (
2596- Type baseTy, ValueDecl *value, DeclContext *useDC,
2597- bool isDynamicResult,
2598- FunctionRefKind functionRefKind,
2599- ConstraintLocator *locator,
2611+ DeclReferenceType ConstraintSystem::getTypeOfMemberReference (
2612+ Type baseTy, ValueDecl *value, DeclContext *useDC, bool isDynamicLookup,
2613+ FunctionRefKind functionRefKind, ConstraintLocator *locator,
26002614 OpenedTypeMap *replacementsPtr) {
26012615 // Figure out the instance type used for the base.
26022616 Type resolvedBaseTy = getFixedTypeRecursive (baseTy, /* wantRValue=*/ true );
@@ -2619,10 +2633,11 @@ ConstraintSystem::getTypeOfMemberReference(
26192633 // metatype and `bar` is static member declared in a protocol or its
26202634 // extension.
26212635 bool isStaticMemberRefOnProtocol = false ;
2622- if (resolvedBaseTy->is <MetatypeType>() && baseObjTy->isExistentialType () &&
2623- value->isStatic ()) {
2624- isStaticMemberRefOnProtocol =
2625- locator->isLastElement <LocatorPathElt::UnresolvedMember>();
2636+ if (baseObjTy->isExistentialType () && value->isStatic () &&
2637+ locator->isLastElement <LocatorPathElt::UnresolvedMember>()) {
2638+ assert (resolvedBaseTy->is <MetatypeType>() &&
2639+ " Assumed base of unresolved member access must be a metatype" );
2640+ isStaticMemberRefOnProtocol = true ;
26262641 }
26272642
26282643 if (auto *typeDecl = dyn_cast<TypeDecl>(value)) {
@@ -2791,7 +2806,7 @@ ConstraintSystem::getTypeOfMemberReference(
27912806 // if it didn't conform.
27922807 addConstraint (ConstraintKind::Bind, baseOpenedTy, selfObjTy,
27932808 getConstraintLocator (locator));
2794- } else if (!isDynamicResult ) {
2809+ } else if (!isDynamicLookup ) {
27952810 addSelfConstraint (*this , baseOpenedTy, selfObjTy, locator);
27962811 }
27972812
@@ -2857,14 +2872,14 @@ ConstraintSystem::getTypeOfMemberReference(
28572872 // Compute the type of the reference.
28582873 Type type = getMemberReferenceTypeFromOpenedType (
28592874 openedType, baseObjTy, value, outerDC, locator, hasAppliedSelf,
2860- isStaticMemberRefOnProtocol, isDynamicResult , replacements);
2875+ isDynamicLookup , replacements);
28612876
28622877 // Do the same thing for the original type, if there can be any difference.
28632878 Type origType = type;
28642879 if (openedType.getPointer () != origOpenedType.getPointer ()) {
28652880 origType = getMemberReferenceTypeFromOpenedType (
28662881 origOpenedType, baseObjTy, value, outerDC, locator, hasAppliedSelf,
2867- isStaticMemberRefOnProtocol, isDynamicResult , replacements);
2882+ isDynamicLookup , replacements);
28682883 }
28692884
28702885 // If we opened up any type variables, record the replacements.
@@ -4035,6 +4050,35 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
40354050 }
40364051
40374052 if (auto *decl = choice.getDeclOrNull ()) {
4053+ // If this is an existential member access and adjustments were made to the
4054+ // member reference type, require that the constraint system is happy with
4055+ // the ensuing conversion.
4056+ if (auto baseTy = choice.getBaseType ()) {
4057+ baseTy = getFixedTypeRecursive (baseTy, /* wantRValue=*/ true );
4058+ const auto instanceTy = baseTy->getMetatypeInstanceType ();
4059+
4060+ if (isExistentialMemberAccessWithExplicitBaseExpression (
4061+ instanceTy, decl, locator,
4062+ /* isDynamicLookup=*/ choice.getKind () ==
4063+ OverloadChoiceKind::DeclViaDynamic)) {
4064+
4065+ // Strip curried 'self' parameters.
4066+ auto fromTy = openedType->castTo <AnyFunctionType>()->getResult ();
4067+ auto toTy = refType;
4068+ if (!doesMemberRefApplyCurriedSelf (baseTy, decl)) {
4069+ toTy = toTy->castTo <AnyFunctionType>()->getResult ();
4070+ }
4071+
4072+ if (!fromTy->isEqual (toTy)) {
4073+ ConstraintLocatorBuilder conversionLocator = locator;
4074+ conversionLocator = conversionLocator.withPathElement (
4075+ ConstraintLocator::ExistentialMemberAccessConversion);
4076+ addConstraint (ConstraintKind::Conversion, fromTy, toTy,
4077+ conversionLocator);
4078+ }
4079+ }
4080+ }
4081+
40384082 // If the declaration is unavailable, note that in the score.
40394083 if (isDeclUnavailable (decl, locator))
40404084 increaseScore (SK_Unavailable, locator);
@@ -6293,6 +6337,7 @@ void constraints::simplifyLocator(ASTNode &anchor,
62936337 case ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice:
62946338 case ConstraintLocator::FallbackType:
62956339 case ConstraintLocator::KeyPathSubscriptIndex:
6340+ case ConstraintLocator::ExistentialMemberAccessConversion:
62966341 break ;
62976342 }
62986343
0 commit comments