@@ -4079,65 +4079,74 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
4079
4079
}
4080
4080
}
4081
4081
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
+ }
4102
4099
}
4103
4100
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
+ }
4141
4150
}
4142
4151
}
4143
4152
0 commit comments