Skip to content

Commit 514a042

Browse files
committed
GSB: Concretize nested types when adding a superclass constraint
When adding a superclass constraint, we need to find any nested types belonging to protocols that the superclass conforms to, and introduce implicit same-type constraints between each nested type and the corresponding type witness in the superclass's conformance to that protocol. Fixes <rdar://problem/39481178>, <https://bugs.swift.org/browse/SR-11232>.
1 parent a59a67a commit 514a042

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2542,7 +2542,13 @@ static void concretizeNestedTypeFromConcreteParent(
25422542
GenericSignatureBuilder &builder) {
25432543
auto parentEquiv = parent->getEquivalenceClassIfPresent();
25442544
assert(parentEquiv && "can't have a concrete type without an equiv class");
2545+
2546+
bool isSuperclassConstrained = false;
25452547
auto concreteParent = parentEquiv->concreteType;
2548+
if (!concreteParent) {
2549+
isSuperclassConstrained = true;
2550+
concreteParent = parentEquiv->superclass;
2551+
}
25462552
assert(concreteParent &&
25472553
"attempting to resolve concrete nested type of non-concrete PA");
25482554

@@ -2564,8 +2570,14 @@ static void concretizeNestedTypeFromConcreteParent(
25642570
"No conformance requirement");
25652571
const RequirementSource *parentConcreteSource = nullptr;
25662572
for (const auto &constraint : parentEquiv->conformsTo.find(proto)->second) {
2567-
if (constraint.source->kind == RequirementSource::Concrete) {
2568-
parentConcreteSource = constraint.source;
2573+
if (!isSuperclassConstrained) {
2574+
if (constraint.source->kind == RequirementSource::Concrete) {
2575+
parentConcreteSource = constraint.source;
2576+
}
2577+
} else {
2578+
if (constraint.source->kind == RequirementSource::Superclass) {
2579+
parentConcreteSource = constraint.source;
2580+
}
25692581
}
25702582
}
25712583

@@ -4299,6 +4311,15 @@ bool GenericSignatureBuilder::updateSuperclass(
42994311
for (const auto &conforms : equivClass->conformsTo) {
43004312
(void)resolveSuperConformance(type, conforms.first);
43014313
}
4314+
4315+
// Eagerly resolve any existing nested types to their concrete forms (others
4316+
// will be "concretized" as they are constructed, in getNestedType).
4317+
for (auto equivT : equivClass->members) {
4318+
for (auto nested : equivT->getNestedTypes()) {
4319+
concretizeNestedTypeFromConcreteParent(equivT, nested.second.front(),
4320+
*this);
4321+
}
4322+
}
43024323
};
43034324

43044325
// If we haven't yet recorded a superclass constraint for this equivalence
@@ -7188,6 +7209,12 @@ void GenericSignatureBuilder::dump(llvm::raw_ostream &out) {
71887209
pa->dump(out, &Context.SourceMgr, 2);
71897210
}
71907211
out << "\n";
7212+
7213+
out << "Equivalence classes:\n";
7214+
for (auto &equiv : Impl->EquivalenceClasses) {
7215+
equiv.dump(out, this);
7216+
}
7217+
out << "\n";
71917218
}
71927219

71937220
void GenericSignatureBuilder::addGenericSignature(GenericSignature sig) {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// rdar://problem/39481178 - Introducing a superclass constraint does not add
4+
// same-type constraints on nested types
5+
6+
protocol P {
7+
associatedtype Q
8+
}
9+
10+
class C : P {
11+
typealias Q = Int
12+
}
13+
14+
// Use the "generic parameter cannot be concrete" check as a proxy for the
15+
// same-type constraint 'T == C.Q (aka Int)' having been inferred:
16+
17+
extension P {
18+
func f1<T>(_: T) where T == Q, Self : C {}
19+
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
20+
21+
func f2<T>(_: T) where Self : C, T == Q {}
22+
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
23+
}

validation-test/compiler_crashers_2/sr11232.swift renamed to validation-test/compiler_crashers_2_fixed/sr11232.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// RUN: not --crash %target-swift-emit-silgen %s
2-
3-
// REQUIRES: asserts
1+
// RUN: not %target-swift-emit-silgen %s
42

53
protocol Pub {
64
associatedtype Other

0 commit comments

Comments
 (0)