Skip to content

Commit 368b387

Browse files
authored
Merge pull request #36811 from slavapestov/start-purging-derived-via-concrete
GSB: Start purging the notion of "derived via concrete" requirements
2 parents fd06683 + e8c4418 commit 368b387

File tree

4 files changed

+63
-30
lines changed

4 files changed

+63
-30
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: 51 additions & 28 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;
@@ -1094,12 +1096,14 @@ const RequirementSource *RequirementSource::getMinimalConformanceSource(
10941096
ArchetypeResolutionKind::WellFormed);
10951097
assert(parentEquivClass && "Not a well-formed type?");
10961098

1097-
if (parentEquivClass->concreteType)
1098-
derivedViaConcrete = true;
1099-
else if (parentEquivClass->superclass &&
1100-
builder.lookupConformance(parentEquivClass->superclass,
1101-
source->getProtocolDecl()))
1102-
derivedViaConcrete = true;
1099+
if (requirementSignatureSelfProto) {
1100+
if (parentEquivClass->concreteType)
1101+
derivedViaConcrete = true;
1102+
else if (parentEquivClass->superclass &&
1103+
builder.lookupConformance(parentEquivClass->superclass,
1104+
source->getProtocolDecl()))
1105+
derivedViaConcrete = true;
1106+
}
11031107

11041108
// The parent potential archetype must conform to the protocol in which
11051109
// this requirement resides. Add this constraint.
@@ -6256,6 +6260,20 @@ static bool typeConflictsWithLayoutConstraint(Type t, LayoutConstraint layout) {
62566260
return false;
62576261
}
62586262

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

62906308
// FIXME: Check for a conflict via the concrete type.
62916309
exact.push_back(constraint);
6310+
6311+
if (!source->isDerivedRequirement()) {
6312+
if (isConcreteConformance(equivClass, entry.first, *this)) {
6313+
Impl->ExplicitConformancesImpliedByConcrete.insert(
6314+
ExplicitRequirement::fromExplicitConstraint(
6315+
RequirementKind::Conformance, constraint));
6316+
}
6317+
}
62926318
}
62936319

62946320
graph.addConstraintsFromEquivClass(RequirementKind::Conformance,
@@ -7176,6 +7202,9 @@ void GenericSignatureBuilder::diagnoseRedundantRequirements() const {
71767202

71777203
for (auto otherReq : found->second) {
71787204
auto *otherSource = otherReq.getSource();
7205+
if (otherSource->isInferredRequirement())
7206+
continue;
7207+
71797208
auto otherLoc = otherSource->getLoc();
71807209
if (otherLoc.isInvalid())
71817210
continue;
@@ -7213,6 +7242,9 @@ void GenericSignatureBuilder::diagnoseRedundantRequirements() const {
72137242

72147243
for (auto otherReq : found->second) {
72157244
auto *otherSource = otherReq.getSource();
7245+
if (otherSource->isInferredRequirement())
7246+
continue;
7247+
72167248
auto otherLoc = otherSource->getLoc();
72177249
if (otherLoc.isInvalid())
72187250
continue;
@@ -7252,6 +7284,9 @@ void GenericSignatureBuilder::diagnoseRedundantRequirements() const {
72527284

72537285
for (auto otherReq : found->second) {
72547286
auto *otherSource = otherReq.getSource();
7287+
if (otherSource->isInferredRequirement())
7288+
continue;
7289+
72557290
auto otherLoc = otherSource->getLoc();
72567291
if (otherLoc.isInvalid())
72577292
continue;
@@ -8159,7 +8194,7 @@ void GenericSignatureBuilder::checkLayoutConstraints(
81598194
}
81608195

81618196
bool GenericSignatureBuilder::isRedundantExplicitRequirement(
8162-
ExplicitRequirement req) const {
8197+
const ExplicitRequirement &req) const {
81638198
assert(Impl->computedRedundantRequirements &&
81648199
"Must ensure computeRedundantRequirements() is called first");
81658200
auto &redundantReqs = Impl->RedundantRequirements;
@@ -8466,23 +8501,6 @@ static void checkGenericSignature(CanGenericSignature canSig,
84668501
}
84678502
#endif
84688503

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-
84868504
static Type stripBoundDependentMemberTypes(Type t) {
84878505
if (auto *depMemTy = t->getAs<DependentMemberType>()) {
84888506
return DependentMemberType::get(
@@ -8532,7 +8550,8 @@ GenericSignature GenericSignatureBuilder::rebuildSignatureWithoutRedundantRequir
85328550
assert(req.getKind() != RequirementKind::SameType &&
85338551
"Should not see same-type requirement here");
85348552

8535-
if (isRedundantExplicitRequirement(req))
8553+
if (isRedundantExplicitRequirement(req) &&
8554+
Impl->ExplicitConformancesImpliedByConcrete.count(req))
85368555
continue;
85378556

85388557
auto subjectType = req.getSource()->getStoredType();
@@ -8618,8 +8637,12 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
86188637
assert(!Impl->HadAnyError &&
86198638
"Rebuilt signature had errors");
86208639

8621-
assert(!hasExplicitConformancesImpliedByConcrete() &&
8622-
"Rebuilt signature still had redundant conformance requirements");
8640+
#ifndef NDEBUG
8641+
for (const auto &req : Impl->ExplicitConformancesImpliedByConcrete) {
8642+
assert(!isRedundantExplicitRequirement(req) &&
8643+
"Rebuilt signature still had redundant conformance requirements");
8644+
}
8645+
#endif
86238646
}
86248647

86258648
// If any of our explicit conformance requirements were implied by
@@ -8634,7 +8657,7 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
86348657
if (!rebuildingWithoutRedundantConformances &&
86358658
!buildingRequirementSignature &&
86368659
!Impl->HadAnyError &&
8637-
hasExplicitConformancesImpliedByConcrete()) {
8660+
!Impl->ExplicitConformancesImpliedByConcrete.empty()) {
86388661
return std::move(*this).rebuildSignatureWithoutRedundantRequirements(
86398662
allowConcreteGenericParams,
86408663
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) {}

test/Generics/rdar75656022.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ struct OriginalExampleWithWarning<A, B> where A : P2, B : P2, A.T == B.T {
4949
where C : P1,
5050
D : P1, // expected-warning {{redundant conformance constraint 'D' : 'P1'}}
5151
C.T : P1, // expected-warning {{redundant conformance constraint 'C.T' : 'P1'}}
52-
A == S1<C, C.T.T, S2<C.T>>,
52+
A == S1<C, C.T.T, S2<C.T>>, // expected-note {{conformance constraint 'D' : 'P1' implied here}}
53+
// expected-note@-1 {{conformance constraint 'C.T' : 'P1' implied here}}
5354
C.T == D,
5455
E == D.T { }
5556
}
@@ -71,6 +72,7 @@ struct WithoutBogusGenericParametersWithWarning<A, B> where A : P2, B : P2, A.T
7172
where C : P1,
7273
C.T : P1, // expected-warning {{redundant conformance constraint 'C.T' : 'P1'}}
7374
A == S1<C, C.T.T, S2<C.T>> {}
75+
// expected-note@-1 {{conformance constraint 'C.T' : 'P1' implied here}}
7476
}
7577

7678
// Same as above but without unnecessary generic parameters

0 commit comments

Comments
 (0)