Skip to content

Commit bf730ff

Browse files
committed
[GSB] Concretize nested types when merging two potential archetypes.
When two potential archetypes are merged and only one of them was a concrete type beforehand, concretize the nested types in the equivalence class of the non-concrete potential archetype. Otherwise, we're liable to miss redundancies. This feels like an ad hoc extension to an ad hoc mechanism, but gets us back to parity with this patch series.
1 parent c879b95 commit bf730ff

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3349,6 +3349,7 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
33493349

33503350
// Merge the equivalence classes.
33513351
auto equivClass = T1->getOrCreateEquivalenceClass();
3352+
auto equivClass1Members = equivClass->members;
33523353
auto equivClass2Members = T2->getEquivalenceClassMembers();
33533354
for (auto equiv : equivClass2Members)
33543355
equivClass->members.push_back(equiv);
@@ -3370,8 +3371,10 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
33703371
}
33713372

33723373
// Same-type-to-concrete requirements.
3373-
if (equivClass2 && equivClass2->concreteType) {
3374-
if (equivClass->concreteType) {
3374+
bool t1IsConcrete = !equivClass->concreteType.isNull();
3375+
bool t2IsConcrete = equivClass2 && !equivClass2->concreteType.isNull();
3376+
if (t2IsConcrete) {
3377+
if (t1IsConcrete) {
33753378
(void)addSameTypeRequirement(equivClass->concreteType,
33763379
equivClass2->concreteType, Source,
33773380
UnresolvedHandlingKind::GenerateConstraints,
@@ -3422,6 +3425,14 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
34223425
auto dependentT1 = T1->getDependentType({ }, /*allowUnresolved=*/true);
34233426
for (auto equivT2 : equivClass2Members) {
34243427
for (auto T2Nested : equivT2->NestedTypes) {
3428+
// If T1 is concrete but T2 is not, concretize the nested types of T2.
3429+
if (t1IsConcrete && !t2IsConcrete) {
3430+
concretizeNestedTypeFromConcreteParent(T1, T2Nested.second.front(),
3431+
*this);
3432+
continue;
3433+
}
3434+
3435+
// Otherwise, make the nested types equivalent.
34253436
Type nestedT1 = DependentMemberType::get(dependentT1, T2Nested.first);
34263437
if (isErrorResult(
34273438
addSameTypeRequirement(
@@ -3433,6 +3444,16 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
34333444
}
34343445
}
34353446

3447+
// If T2 is concrete but T1 was not, concretize the nested types of T1.
3448+
if (t2IsConcrete && !t1IsConcrete) {
3449+
for (auto equivT1 : equivClass1Members) {
3450+
for (auto T1Nested : equivT1->NestedTypes) {
3451+
concretizeNestedTypeFromConcreteParent(T2, T1Nested.second.front(),
3452+
*this);
3453+
}
3454+
}
3455+
}
3456+
34363457
return ConstraintResult::Resolved;
34373458
}
34383459

test/Constraints/same_types.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,18 +119,24 @@ func fail6<T>(_ t: T) -> Int where T == Int { // expected-error{{same-type requi
119119
}
120120

121121
func test8<T: Barrable, U: Barrable>(_ t: T, u: U) -> (Y, Y, X, X)
122-
where T.Bar == Y, U.Bar.Foo == X, T.Bar == U.Bar { // expected-warning{{redundant same-type constraint 'U.Bar.Foo' == 'X'}}
123-
// expected-note@-1{{same-type constraint 'T.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}}
122+
where T.Bar == Y, // expected-note{{same-type constraint 'U.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}}
123+
U.Bar.Foo == X, T.Bar == U.Bar { // expected-warning{{redundant same-type constraint 'U.Bar.Foo' == 'X'}}
124124
return (t.bar, u.bar, t.bar.foo, u.bar.foo)
125125
}
126126

127127
func test8a<T: Barrable, U: Barrable>(_ t: T, u: U) -> (Y, Y, X, X)
128128
where
129-
T.Bar == Y, U.Bar.Foo == X, U.Bar == T.Bar { // expected-warning{{redundant same-type constraint 'U.Bar.Foo' == 'X'}}
130-
// expected-note@-1{{same-type constraint 'T.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}}
129+
T.Bar == Y, // expected-note{{same-type constraint 'U.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}}
130+
U.Bar.Foo == X, U.Bar == T.Bar { // expected-warning{{redundant same-type constraint 'U.Bar.Foo' == 'X'}}
131131
return (t.bar, u.bar, t.bar.foo, u.bar.foo)
132132
}
133133

134+
func test8b<T: Barrable, U: Barrable>(_ t: T, u: U)
135+
where U.Bar.Foo == X, // expected-warning{{redundant same-type constraint 'U.Bar.Foo' == 'X'}}
136+
T.Bar == Y, // expected-note{{same-type constraint 'U.Bar.Foo' == 'Y.Foo' (aka 'X') implied here}}
137+
T.Bar == U.Bar {
138+
}
139+
134140
// rdar://problem/19137463
135141
func rdar19137463<T>(_ t: T) where T.a == T {} // expected-error{{'a' is not a member type of 'T'}}
136142
rdar19137463(1)

0 commit comments

Comments
 (0)