Skip to content

Commit be30d76

Browse files
committed
[RequirementMachine] Diagnose redundant requirements found during minimization
of the rewrite system.
1 parent 3c95cac commit be30d76

File tree

4 files changed

+122
-5
lines changed

4 files changed

+122
-5
lines changed

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,16 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
421421

422422
if (ctx.LangOpts.RequirementMachineProtocolSignatures ==
423423
RequirementMachineMode::Enabled) {
424+
// Diagnose trivially invalid requirements from the rewrite
425+
// system.
424426
diagnoseRequirementErrors(ctx, machine->System.getErrors(),
425427
/*allowConcreteGenericParams=*/false);
428+
429+
// Diagnose redundant requirements found during signature
430+
// minimization.
431+
auto redundancies = machine->System.getRedundantRequirements();
432+
diagnoseRequirementErrors(ctx, redundancies,
433+
/*allowConcreteGenericParams=*/false);
426434
}
427435

428436
// Return the result for the specific protocol this request was kicked off on.
@@ -673,9 +681,20 @@ InferredGenericSignatureRequestRQM::evaluate(
673681

674682
if (ctx.LangOpts.RequirementMachineInferredSignatures ==
675683
RequirementMachineMode::Enabled) {
676-
hadError |= diagnoseRequirementErrors(ctx, errors, allowConcreteGenericParams);
684+
// Diagnose invalid requirements dropped during desugaring.
685+
hadError |= diagnoseRequirementErrors(ctx, errors,
686+
allowConcreteGenericParams);
687+
688+
// Diagnose trivially invalid requirements from the rewrite
689+
// system.
677690
hadError |= diagnoseRequirementErrors(ctx, machine->System.getErrors(),
678691
allowConcreteGenericParams);
692+
693+
// Diagnose redundant requirements found during signature
694+
// minimization.
695+
auto redundancies = machine->System.getRedundantRequirements();
696+
hadError |= diagnoseRequirementErrors(ctx, redundancies,
697+
allowConcreteGenericParams);
679698
}
680699

681700
// FIXME: Handle allowConcreteGenericParams

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,50 @@ void RewriteSystem::verifyRewriteRules(ValidityPolicy policy) const {
720720
#undef ASSERT_RULE
721721
}
722722

723+
std::vector<RequirementError>
724+
RewriteSystem::getRedundantRequirements() {
725+
// The resulting set of redundant requirements.
726+
std::vector<RequirementError> redundantRequirements;
727+
728+
// Collect all rule IDs for each unique requirement ID.
729+
llvm::SmallDenseMap<unsigned, llvm::SmallDenseSet<unsigned, 2>>
730+
rulesPerRequirement;
731+
732+
for (unsigned ruleID : indices(getRules())) {
733+
auto &rule = getRules()[ruleID];
734+
735+
if (!rule.isExplicit())
736+
continue;
737+
738+
auto requirementID = rule.getRequirementID();
739+
if (!requirementID.hasValue())
740+
continue;
741+
742+
rulesPerRequirement[*requirementID].insert(ruleID);
743+
}
744+
745+
auto isRedundantRule = [&](unsigned ruleID) {
746+
auto &rule = getRules()[ruleID];
747+
return rule.isRedundant();
748+
};
749+
750+
for (auto pair : rulesPerRequirement) {
751+
unsigned requirementID = pair.first;
752+
auto ruleIDs = pair.second;
753+
754+
// If all rules derived from this structural requirement are redundant,
755+
// then the requirement is unnecessary in the source code.
756+
if (llvm::all_of(ruleIDs, isRedundantRule)) {
757+
auto requirement = WrittenRequirements[requirementID];
758+
redundantRequirements.push_back(
759+
RequirementError::forRedundantRequirement(requirement.req,
760+
requirement.loc));
761+
}
762+
}
763+
764+
return redundantRequirements;
765+
}
766+
723767
void RewriteSystem::dump(llvm::raw_ostream &out) const {
724768
out << "Rewrite system: {\n";
725769
for (const auto &rule : Rules) {

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,6 @@ class RewriteSystem final {
296296
return ProtocolMap;
297297
}
298298

299-
ArrayRef<RequirementError> getErrors() {
300-
return Errors;
301-
}
302-
303299
DebugOptions getDebugOptions() const { return Debug; }
304300

305301
void initialize(bool recordLoops, ArrayRef<const ProtocolDecl *> protos,
@@ -372,6 +368,18 @@ class RewriteSystem final {
372368

373369
void verifyRewriteRules(ValidityPolicy policy) const;
374370

371+
//////////////////////////////////////////////////////////////////////////////
372+
///
373+
/// Diagnostics
374+
///
375+
//////////////////////////////////////////////////////////////////////////////
376+
377+
ArrayRef<RequirementError> getErrors() {
378+
return Errors;
379+
}
380+
381+
std::vector<RequirementError> getRedundantRequirements();
382+
375383
private:
376384
struct CriticalPair {
377385
MutableTerm LHS;

test/Generics/requirement_machine_diagnostics.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,49 @@ protocol TrivialRedundantSameType where Self == Self {
111111
associatedtype T where T == T
112112
// expected-warning@-1 {{redundant same-type constraint 'Self.T' == 'Self.T'}}
113113
}
114+
115+
struct G<T> { }
116+
117+
protocol Pair {
118+
associatedtype A
119+
associatedtype B
120+
}
121+
122+
func test1<T: Pair>(_: T) where T.A == G<Int>, T.A == G<T.B>, T.B == Int { }
123+
// expected-warning@-1 {{redundant same-type constraint 'T.A' == 'G<T.B>'}}
124+
125+
126+
protocol P1 {
127+
func p1()
128+
}
129+
130+
protocol P2 : P1 { }
131+
132+
protocol P3 {
133+
associatedtype P3Assoc : P2
134+
}
135+
136+
protocol P4 {
137+
associatedtype P4Assoc : P1
138+
}
139+
140+
func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
141+
// expected-warning@-1{{redundant conformance constraint 'U.P4Assoc' : 'P2'}}
142+
143+
protocol P5 {
144+
associatedtype Element
145+
}
146+
147+
protocol P6 {
148+
associatedtype AssocP6 : P5
149+
}
150+
151+
protocol P7 : P6 {
152+
associatedtype AssocP7: P6
153+
}
154+
155+
extension P7 where AssocP6.Element : P6,
156+
AssocP7.AssocP6.Element : P6, // expected-warning{{redundant conformance constraint 'Self.AssocP7.AssocP6.Element' : 'P6'}}
157+
AssocP6.Element == AssocP7.AssocP6.Element {
158+
func nestedSameType1() { }
159+
}

0 commit comments

Comments
 (0)