Skip to content

Commit c257cdb

Browse files
committed
Sema: Relax primary associated type matching in matchExistentialTypes()
Recently I found a soundness hole here, where we would allow conversion between `any P<T>` and `any Q<T>` even if P and Q have different primary associated types. However, the fix was too strict, because we still want to allow the conversion when the associated types have the same name. Fixes rdar://141968103.
1 parent c170443 commit c257cdb

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-6
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4221,7 +4221,7 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
42214221

42224222
// Finally, check parameterized protocol requirements.
42234223
if (!layout.getParameterizedProtocols().empty()) {
4224-
SmallVector<std::pair<AssociatedTypeDecl *, Type>, 4> fromReqs;
4224+
SmallVector<std::pair<Identifier, Type>, 4> fromReqs;
42254225

42264226
if (type1->isExistentialType()) {
42274227
auto fromLayout = type1->getExistentialLayout();
@@ -4232,8 +4232,7 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
42324232

42334233
for (unsigned i : indices(argTypes)) {
42344234
auto argType = argTypes[i];
4235-
auto *assocType = assocTypes[i]->getAssociatedTypeAnchor();
4236-
fromReqs.push_back(std::make_pair(assocType, argType));
4235+
fromReqs.push_back(std::make_pair(assocTypes[i]->getName(), argType));
42374236
}
42384237
}
42394238
}
@@ -4248,10 +4247,9 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
42484247

42494248
for (unsigned i : indices(argTypes)) {
42504249
auto argType = argTypes[i];
4251-
auto *assocType = assocTypes[i]->getAssociatedTypeAnchor();
42524250
bool found = false;
42534251
for (auto fromReq : fromReqs) {
4254-
if (fromReq.first == assocType) {
4252+
if (fromReq.first == assocTypes[i]->getName()) {
42554253
// FIXME: Extend the locator path to point to the argument
42564254
// inducing the requirement.
42574255
auto result = matchTypes(fromReq.second, argType,

test/Constraints/parameterized_existential_unrelated_args.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,25 @@ var q: any Q<String> = p // expected-error {{cannot convert value of type 'any P
3131
// Previously we accepted the above conversion, and then getB()
3232
// would return something that was dynamically Array<String>
3333
// and not String as expected.
34-
print(q.getB())
34+
// print(q.getB())
35+
36+
37+
// However, this is OK -- the two A's have the same name, so by the
38+
// semantics of the generics system they must be equivalent as type
39+
// parameters.
40+
41+
protocol P1<A> {
42+
associatedtype A
43+
}
44+
45+
protocol P2<A> {
46+
associatedtype A
47+
}
48+
49+
protocol P3<A>: P1, P2 {
50+
associatedtype A
51+
}
52+
53+
func f<T>(_ value: any P3<T>) -> (any P1<T>, any P2<T>) {
54+
return (value, value)
55+
}

0 commit comments

Comments
 (0)