Skip to content

Commit 524e588

Browse files
committed
GSB: Skip same-type requirement minimization if there are no same-type requirements
The logic here is pretty expensive, and there's no reason to do it at all if we aren't going to end up with any same-type requirements.
1 parent a7f2e5c commit 524e588

File tree

2 files changed

+76
-55
lines changed

2 files changed

+76
-55
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 59 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6470,14 +6470,16 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar
64706470
checkLayoutConstraints(genericParams, &equivClass);
64716471
};
64726472

6473-
// FIXME: Expand all conformance requirements. This is expensive :(
6474-
for (auto &equivClass : Impl->EquivalenceClasses) {
6473+
if (!Impl->ExplicitSameTypeRequirements.empty()) {
6474+
// FIXME: Expand all conformance requirements. This is expensive :(
6475+
for (auto &equivClass : Impl->EquivalenceClasses) {
64756476
expandSameTypeConstraints(*this, &equivClass);
6476-
}
6477+
}
64776478

6478-
// Check same-type constraints.
6479-
for (auto &equivClass : Impl->EquivalenceClasses) {
6480-
checkSameTypeConstraints(genericParams, &equivClass);
6479+
// Check same-type constraints.
6480+
for (auto &equivClass : Impl->EquivalenceClasses) {
6481+
checkSameTypeConstraints(genericParams, &equivClass);
6482+
}
64816483
}
64826484

64836485
// Check for generic parameters which have been made concrete or equated
@@ -8082,63 +8084,65 @@ void GenericSignatureBuilder::enumerateRequirements(
80828084
}
80838085

80848086
// Collect all same type requirements.
8085-
for (auto &equivClass : Impl->EquivalenceClasses) {
8086-
if (equivClass.derivedSameTypeComponents.empty()) {
8087-
checkSameTypeConstraints(genericParams, &equivClass);
8088-
}
8089-
8090-
for (unsigned i : indices(equivClass.derivedSameTypeComponents)) {
8091-
// Dig out the subject type and its corresponding component.
8092-
auto &component = equivClass.derivedSameTypeComponents[i];
8093-
Type subjectType = component.type;
8087+
if (!Impl->ExplicitSameTypeRequirements.empty()) {
8088+
for (auto &equivClass : Impl->EquivalenceClasses) {
8089+
if (equivClass.derivedSameTypeComponents.empty()) {
8090+
checkSameTypeConstraints(genericParams, &equivClass);
8091+
}
80948092

8095-
assert(!subjectType->hasError());
8096-
assert(!subjectType->findUnresolvedDependentMemberType());
8093+
for (unsigned i : indices(equivClass.derivedSameTypeComponents)) {
8094+
// Dig out the subject type and its corresponding component.
8095+
auto &component = equivClass.derivedSameTypeComponents[i];
8096+
Type subjectType = component.type;
8097+
8098+
assert(!subjectType->hasError());
8099+
assert(!subjectType->findUnresolvedDependentMemberType());
8100+
8101+
// If this equivalence class is bound to a concrete type, equate the
8102+
// anchor with a concrete type.
8103+
if (Type concreteType = equivClass.concreteType) {
8104+
concreteType = getCanonicalTypeInContext(concreteType, genericParams);
8105+
8106+
// If the parent of this anchor is also a concrete type, don't
8107+
// create a requirement.
8108+
if (!subjectType->is<GenericTypeParamType>() &&
8109+
maybeResolveEquivalenceClass(
8110+
subjectType->castTo<DependentMemberType>()->getBase(),
8111+
ArchetypeResolutionKind::WellFormed,
8112+
/*wantExactPotentialArchetype=*/false)
8113+
.getEquivalenceClass(*this)->concreteType)
8114+
continue;
80978115

8098-
// If this equivalence class is bound to a concrete type, equate the
8099-
// anchor with a concrete type.
8100-
if (Type concreteType = equivClass.concreteType) {
8101-
concreteType = getCanonicalTypeInContext(concreteType, genericParams);
8116+
// Drop recursive and invalid concrete-type constraints.
8117+
if (equivClass.recursiveConcreteType ||
8118+
equivClass.invalidConcreteType)
8119+
continue;
81028120

8103-
// If the parent of this anchor is also a concrete type, don't
8104-
// create a requirement.
8105-
if (!subjectType->is<GenericTypeParamType>() &&
8106-
maybeResolveEquivalenceClass(
8107-
subjectType->castTo<DependentMemberType>()->getBase(),
8108-
ArchetypeResolutionKind::WellFormed,
8109-
/*wantExactPotentialArchetype=*/false)
8110-
.getEquivalenceClass(*this)->concreteType)
8121+
// Filter out derived requirements... except for concrete-type
8122+
// requirements on generic parameters. The exception is due to
8123+
// the canonicalization of generic signatures, which never
8124+
// eliminates generic parameters even when they have been
8125+
// mapped to a concrete type.
8126+
if (subjectType->is<GenericTypeParamType>() ||
8127+
component.concreteTypeSource == nullptr ||
8128+
!component.concreteTypeSource->isDerivedRequirement()) {
8129+
recordRequirement(RequirementKind::SameType,
8130+
subjectType, concreteType);
8131+
}
81118132
continue;
8133+
}
81128134

8113-
// Drop recursive and invalid concrete-type constraints.
8114-
if (equivClass.recursiveConcreteType ||
8115-
equivClass.invalidConcreteType)
8116-
continue;
8135+
// If we're at the last anchor in the component, do nothing;
8136+
if (i + 1 != equivClass.derivedSameTypeComponents.size()) {
8137+
// Form a same-type constraint from this anchor within the component
8138+
// to the next.
8139+
// FIXME: Distinguish between explicit and inferred here?
8140+
auto &nextComponent = equivClass.derivedSameTypeComponents[i + 1];
8141+
Type otherSubjectType = nextComponent.type;
81178142

8118-
// Filter out derived requirements... except for concrete-type
8119-
// requirements on generic parameters. The exception is due to
8120-
// the canonicalization of generic signatures, which never
8121-
// eliminates generic parameters even when they have been
8122-
// mapped to a concrete type.
8123-
if (subjectType->is<GenericTypeParamType>() ||
8124-
component.concreteTypeSource == nullptr ||
8125-
!component.concreteTypeSource->isDerivedRequirement()) {
81268143
recordRequirement(RequirementKind::SameType,
8127-
subjectType, concreteType);
8144+
subjectType, otherSubjectType);
81288145
}
8129-
continue;
8130-
}
8131-
8132-
// If we're at the last anchor in the component, do nothing;
8133-
if (i + 1 != equivClass.derivedSameTypeComponents.size()) {
8134-
// Form a same-type constraint from this anchor within the component
8135-
// to the next.
8136-
// FIXME: Distinguish between explicit and inferred here?
8137-
auto &nextComponent = equivClass.derivedSameTypeComponents[i + 1];
8138-
Type otherSubjectType = nextComponent.type;
8139-
8140-
recordRequirement(RequirementKind::SameType,
8141-
subjectType, otherSubjectType);
81428146
}
81438147
}
81448148
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | %FileCheck %s
3+
4+
class S<T, U> where T : P, U == T.T {}
5+
6+
protocol P {
7+
associatedtype T
8+
}
9+
10+
struct G<X, T, U> {}
11+
12+
class C : P {
13+
typealias T = Int
14+
}
15+
16+
// CHECK-LABEL: Generic signature: <X, T, U where X : S<T, C.T>, T : C, U == C.T>
17+
extension G where X : S<T, U>, T : C {}

0 commit comments

Comments
 (0)