@@ -4079,65 +4079,74 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
40794079 }
40804080 }
40814081
4082- auto constraintType1 = type1;
4083- if (auto existential = constraintType1->getAs<ExistentialType>())
4084- constraintType1 = existential->getConstraintType();
4085-
4086- auto constraintType2 = type2;
4087- if (auto existential = constraintType2->getAs<ExistentialType>())
4088- constraintType2 = existential->getConstraintType();
4089-
4090- auto ppt1 = constraintType1->getAs<ParameterizedProtocolType>();
4091- auto ppt2 = constraintType2->getAs<ParameterizedProtocolType>();
4092-
4093- // With two parameterized protocols, we've already made sure conformance
4094- // constraints are satisfied. Try to match the arguments!
4095- if (ppt1 && ppt2) {
4096- ArrayRef<Type> longerArgs = ppt1->getArgs();
4097- ArrayRef<Type> shorterArgs = ppt2->getArgs();
4098- // The more constrained of the two types had better be the first type -
4099- // otherwise we're forgetting requirements.
4100- if (longerArgs.size() < shorterArgs.size()) {
4101- return getTypeMatchFailure(locator);
4082+ // Finally, check parameterized protocol requirements.
4083+ if (!layout.getParameterizedProtocols().empty()) {
4084+ SmallVector<std::pair<AssociatedTypeDecl *, Type>, 4> fromReqs;
4085+
4086+ if (type1->isExistentialType()) {
4087+ auto fromLayout = type1->getExistentialLayout();
4088+ for (auto *parameterizedType : fromLayout.getParameterizedProtocols()) {
4089+ auto *protoDecl = parameterizedType->getProtocol();
4090+ auto assocTypes = protoDecl->getPrimaryAssociatedTypes();
4091+ auto argTypes = parameterizedType->getArgs();
4092+
4093+ for (unsigned i : indices(argTypes)) {
4094+ auto argType = argTypes[i];
4095+ auto *assocType = assocTypes[i]->getAssociatedTypeAnchor();
4096+ fromReqs.push_back(std::make_pair(assocType, argType));
4097+ }
4098+ }
41024099 }
41034100
4104- // Line up the arguments of the parameterized protocol.
4105- // FIXME: Extend the locator path to point to the argument
4106- // inducing the requirement.
4107- for (const auto &pair : llvm::zip_first(shorterArgs, longerArgs)) {
4108- auto result = matchTypes(std::get<0>(pair), std::get<1>(pair),
4109- ConstraintKind::Bind,
4110- subflags, locator);
4111- if (result.isFailure())
4112- return result;
4113- }
4114- } else if (ppt1 && type2->isExistentialType()) {
4115- // P<T, U, V, ...> converts to (P & Q & ...) trivially...
4116- return getTypeMatchSuccess();
4117- } else if (ppt2 && type1->isExistentialType()) {
4118- // But (P & Q & ...) does not convert to P<T, U, V, ...>
4119- return getTypeMatchFailure(locator);
4120- } else if (ppt1 || ppt2) {
4121- auto parameterized = constraintType1;
4122- auto base = constraintType2;
4123- if (ppt2)
4124- std::swap(parameterized, base);
4125-
4126- // One of the two is parameterized, and the other is a concrete type.
4127- // Substitute the base into the requirements of the parameterized type and
4128- // discharge the requirements of the parameterized protocol.
4129- // FIXME: Extend the locator path to point to the argument
4130- // inducing the requirement.
4131- SmallVector<Requirement, 2> reqs;
4132- parameterized->castTo<ParameterizedProtocolType>()
4133- ->getRequirements(base, reqs);
4134- for (const auto &req : reqs) {
4135- assert(req.getKind() == RequirementKind::SameType);
4136- auto result = matchTypes(req.getFirstType(), req.getSecondType(),
4137- ConstraintKind::Bind,
4138- subflags, locator);
4139- if (result.isFailure())
4140- return result;
4101+ for (auto *parameterizedType : layout.getParameterizedProtocols()) {
4102+ // With two parameterized protocols, we've already made sure conformance
4103+ // constraints are satisfied. Try to match the arguments!
4104+ if (type1->isExistentialType()) {
4105+ auto *protoDecl = parameterizedType->getProtocol();
4106+ auto assocTypes = protoDecl->getPrimaryAssociatedTypes();
4107+ auto argTypes = parameterizedType->getArgs();
4108+
4109+ for (unsigned i : indices(argTypes)) {
4110+ auto argType = argTypes[i];
4111+ auto *assocType = assocTypes[i]->getAssociatedTypeAnchor();
4112+ bool found = false;
4113+ for (auto fromReq : fromReqs) {
4114+ if (fromReq.first == assocType) {
4115+ // FIXME: Extend the locator path to point to the argument
4116+ // inducing the requirement.
4117+ auto result = matchTypes(fromReq.second, argType,
4118+ ConstraintKind::Bind,
4119+ subflags, locator);
4120+ if (result.isFailure())
4121+ return result;
4122+
4123+ found = true;
4124+ break;
4125+ }
4126+ }
4127+
4128+ if (!found)
4129+ return getTypeMatchFailure(locator);
4130+ }
4131+ } else {
4132+ // The source type is a concrete type.
4133+ //
4134+ // Substitute the source into the requirements of the parameterized type
4135+ // and discharge the requirements of the parameterized protocol.
4136+ //
4137+ // FIXME: Extend the locator path to point to the argument
4138+ // inducing the requirement.
4139+ SmallVector<Requirement, 2> reqs;
4140+ parameterizedType->getRequirements(type1, reqs);
4141+ for (const auto &req : reqs) {
4142+ assert(req.getKind() == RequirementKind::SameType);
4143+ auto result = matchTypes(req.getFirstType(), req.getSecondType(),
4144+ ConstraintKind::Bind,
4145+ subflags, locator);
4146+ if (result.isFailure())
4147+ return result;
4148+ }
4149+ }
41414150 }
41424151 }
41434152
0 commit comments