Skip to content

Commit 977d3a7

Browse files
committed
GSB: Narrow down the condition under which we rebuild a generic signature
1 parent 59a218a commit 977d3a7

File tree

3 files changed

+43
-23
lines changed

3 files changed

+43
-23
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ class GenericSignatureBuilder {
654654

655655
class ExplicitRequirement;
656656

657-
bool isRedundantExplicitRequirement(ExplicitRequirement req) const;
657+
bool isRedundantExplicitRequirement(const ExplicitRequirement &req) const;
658658

659659
private:
660660
void computeRedundantRequirements();

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,8 @@ struct GenericSignatureBuilder::Implementation {
730730
std::vector<ConflictingConcreteTypeRequirement>
731731
ConflictingConcreteTypeRequirements;
732732

733+
llvm::DenseSet<ExplicitRequirement> ExplicitConformancesImpliedByConcrete;
734+
733735
#ifndef NDEBUG
734736
/// Whether we've already computed redundant requiremnts.
735737
bool computedRedundantRequirements = false;
@@ -6256,6 +6258,20 @@ static bool typeConflictsWithLayoutConstraint(Type t, LayoutConstraint layout) {
62566258
return false;
62576259
}
62586260

6261+
static bool isConcreteConformance(const EquivalenceClass &equivClass,
6262+
ProtocolDecl *proto,
6263+
GenericSignatureBuilder &builder) {
6264+
if (equivClass.concreteType &&
6265+
builder.lookupConformance(equivClass.concreteType, proto)) {
6266+
return true;
6267+
} else if (equivClass.superclass &&
6268+
builder.lookupConformance(equivClass.superclass, proto)) {
6269+
return true;
6270+
}
6271+
6272+
return false;
6273+
}
6274+
62596275
void GenericSignatureBuilder::computeRedundantRequirements() {
62606276
assert(!Impl->computedRedundantRequirements &&
62616277
"Already computed redundant requirements");
@@ -6289,6 +6305,14 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
62896305

62906306
// FIXME: Check for a conflict via the concrete type.
62916307
exact.push_back(constraint);
6308+
6309+
if (!source->isDerivedRequirement()) {
6310+
if (isConcreteConformance(equivClass, entry.first, *this)) {
6311+
Impl->ExplicitConformancesImpliedByConcrete.insert(
6312+
ExplicitRequirement::fromExplicitConstraint(
6313+
RequirementKind::Conformance, constraint));
6314+
}
6315+
}
62926316
}
62936317

62946318
graph.addConstraintsFromEquivClass(RequirementKind::Conformance,
@@ -8159,7 +8183,7 @@ void GenericSignatureBuilder::checkLayoutConstraints(
81598183
}
81608184

81618185
bool GenericSignatureBuilder::isRedundantExplicitRequirement(
8162-
ExplicitRequirement req) const {
8186+
const ExplicitRequirement &req) const {
81638187
assert(Impl->computedRedundantRequirements &&
81648188
"Must ensure computeRedundantRequirements() is called first");
81658189
auto &redundantReqs = Impl->RedundantRequirements;
@@ -8466,23 +8490,6 @@ static void checkGenericSignature(CanGenericSignature canSig,
84668490
}
84678491
#endif
84688492

8469-
bool GenericSignatureBuilder::hasExplicitConformancesImpliedByConcrete() const {
8470-
for (auto pair : Impl->RedundantRequirements) {
8471-
if (pair.first.getKind() != RequirementKind::Conformance)
8472-
continue;
8473-
8474-
for (auto impliedByReq : pair.second) {
8475-
if (impliedByReq.getKind() == RequirementKind::Superclass)
8476-
return true;
8477-
8478-
if (impliedByReq.getKind() == RequirementKind::SameType)
8479-
return true;
8480-
}
8481-
}
8482-
8483-
return false;
8484-
}
8485-
84868493
static Type stripBoundDependentMemberTypes(Type t) {
84878494
if (auto *depMemTy = t->getAs<DependentMemberType>()) {
84888495
return DependentMemberType::get(
@@ -8532,7 +8539,8 @@ GenericSignature GenericSignatureBuilder::rebuildSignatureWithoutRedundantRequir
85328539
assert(req.getKind() != RequirementKind::SameType &&
85338540
"Should not see same-type requirement here");
85348541

8535-
if (isRedundantExplicitRequirement(req))
8542+
if (isRedundantExplicitRequirement(req) &&
8543+
Impl->ExplicitConformancesImpliedByConcrete.count(req))
85368544
continue;
85378545

85388546
auto subjectType = req.getSource()->getStoredType();
@@ -8618,8 +8626,12 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
86188626
assert(!Impl->HadAnyError &&
86198627
"Rebuilt signature had errors");
86208628

8621-
assert(!hasExplicitConformancesImpliedByConcrete() &&
8622-
"Rebuilt signature still had redundant conformance requirements");
8629+
#ifndef NDEBUG
8630+
for (const auto &req : Impl->ExplicitConformancesImpliedByConcrete) {
8631+
assert(!isRedundantExplicitRequirement(req) &&
8632+
"Rebuilt signature still had redundant conformance requirements");
8633+
}
8634+
#endif
86238635
}
86248636

86258637
// If any of our explicit conformance requirements were implied by
@@ -8634,7 +8646,7 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
86348646
if (!rebuildingWithoutRedundantConformances &&
86358647
!buildingRequirementSignature &&
86368648
!Impl->HadAnyError &&
8637-
hasExplicitConformancesImpliedByConcrete()) {
8649+
!Impl->ExplicitConformancesImpliedByConcrete.empty()) {
86388650
return std::move(*this).rebuildSignatureWithoutRedundantRequirements(
86398651
allowConcreteGenericParams,
86408652
buildingRequirementSignature);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// RUN: %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | %FileCheck %s
3+
4+
protocol P : C {}
5+
final class C : P {}
6+
7+
// CHECK: Generic signature: <T where T : P>
8+
func foo<T : P>(_: T) {}

0 commit comments

Comments
 (0)