Skip to content

Commit 0f3ec0f

Browse files
committed
RequirementMachine: Simpler handling of concrete conformances in minimal conformances algorithm
This logic was tricky and unsound. Correct handling of concrete conformances requires rebuilding the signature after dropping protocol conformance requiremnts made redundant by concrete type requirements. The old support for "derived-via-concrete" requirements in the minimal conformances algorithm was causing other problems, and it is the wrong approach anyway, so just remove it.
1 parent 4d1a8df commit 0f3ec0f

File tree

1 file changed

+13
-130
lines changed

1 file changed

+13
-130
lines changed

lib/AST/RequirementMachine/MinimalConformances.cpp

Lines changed: 13 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -195,22 +195,9 @@ class MinimalConformances {
195195
MutableTerm term, unsigned ruleID,
196196
SmallVectorImpl<unsigned> &result) const;
197197

198-
enum class ConcreteConformances : uint8_t {
199-
/// Don't consider paths involving concrete conformances at all.
200-
Disallowed,
201-
202-
/// Consider paths involving a concrete conformance only if it appears
203-
/// at the end of the path.
204-
AllowedAtEnd,
205-
206-
/// Consider paths involving concrete conformances anywhere.
207-
AllowedAnywhere
208-
};
209-
210198
bool isValidConformancePath(
211199
llvm::SmallDenseSet<unsigned, 4> &visited,
212-
const llvm::SmallVectorImpl<unsigned> &path,
213-
ConcreteConformances allowConcrete) const;
200+
const llvm::SmallVectorImpl<unsigned> &path) const;
214201

215202
bool isValidRefinementPath(
216203
const llvm::SmallVectorImpl<unsigned> &path) const;
@@ -240,7 +227,7 @@ class MinimalConformances {
240227

241228
void verifyMinimalConformanceEquations() const;
242229

243-
void computeMinimalConformances(bool firstPass);
230+
void computeMinimalConformances();
244231

245232
void verifyMinimalConformances() const;
246233

@@ -622,39 +609,12 @@ void MinimalConformances::computeCandidateConformancePaths() {
622609
/// rules.
623610
bool MinimalConformances::isValidConformancePath(
624611
llvm::SmallDenseSet<unsigned, 4> &visited,
625-
const llvm::SmallVectorImpl<unsigned> &path,
626-
ConcreteConformances allowConcrete) const {
627-
628-
unsigned lastIdx = path.size() - 1;
612+
const llvm::SmallVectorImpl<unsigned> &path) const {
629613

630-
for (unsigned ruleIdx : indices(path)) {
631-
unsigned ruleID = path[ruleIdx];
614+
for (unsigned ruleID : path) {
632615
if (visited.count(ruleID) > 0)
633616
return false;
634617

635-
const auto &rule = System.getRule(ruleID);
636-
637-
bool isLastElement = (ruleIdx == lastIdx);
638-
bool isConcreteConformance = rule.getLHS().back().getKind()
639-
== Symbol::Kind::ConcreteConformance;
640-
641-
// Concrete conformances cannot appear in the middle of a conformance path.
642-
if (isConcreteConformance) {
643-
switch (allowConcrete) {
644-
case ConcreteConformances::Disallowed:
645-
return false;
646-
647-
case ConcreteConformances::AllowedAtEnd:
648-
if (!isLastElement)
649-
return false;
650-
651-
break;
652-
653-
case ConcreteConformances::AllowedAnywhere:
654-
break;
655-
}
656-
}
657-
658618
if (RedundantConformances.count(ruleID)) {
659619
SWIFT_DEFER {
660620
visited.erase(ruleID);
@@ -665,29 +625,9 @@ bool MinimalConformances::isValidConformancePath(
665625
if (found == ConformancePaths.end())
666626
return false;
667627

668-
ConcreteConformances allowConcreteRec;
669-
switch (allowConcrete) {
670-
case ConcreteConformances::Disallowed:
671-
allowConcreteRec = ConcreteConformances::Disallowed;
672-
break;
673-
674-
case ConcreteConformances::AllowedAnywhere:
675-
allowConcreteRec = ConcreteConformances::AllowedAnywhere;
676-
break;
677-
678-
case ConcreteConformances::AllowedAtEnd:
679-
if (isLastElement)
680-
allowConcreteRec = ConcreteConformances::AllowedAtEnd;
681-
else
682-
allowConcreteRec = ConcreteConformances::Disallowed;
683-
684-
break;
685-
}
686-
687628
bool foundValidConformancePath = false;
688629
for (const auto &otherPath : found->second) {
689-
if (isValidConformancePath(visited, otherPath,
690-
allowConcreteRec)) {
630+
if (isValidConformancePath(visited, otherPath)) {
691631
foundValidConformancePath = true;
692632
break;
693633
}
@@ -703,19 +643,11 @@ bool MinimalConformances::isValidConformancePath(
703643
};
704644
visited.insert(ruleID);
705645

706-
ConcreteConformances allowConcreteRec;
707-
if (isConcreteConformance)
708-
allowConcreteRec = ConcreteConformances::AllowedAnywhere;
709-
else
710-
allowConcreteRec = ConcreteConformances::AllowedAtEnd;
711-
712646
// If 'req' is based on some other conformance requirement
713647
// `T.[P.]A : Q', we want to make sure that we have a
714648
// non-redundant derivation for 'T : P'.
715-
if (!isValidConformancePath(visited, found->second,
716-
allowConcreteRec)) {
649+
if (!isValidConformancePath(visited, found->second))
717650
return false;
718-
}
719651
}
720652
}
721653
}
@@ -857,48 +789,15 @@ void MinimalConformances::verifyMinimalConformanceEquations() const {
857789
///
858790
/// In the first pass, we only consider conformance requirements that are
859791
/// made redundant by concrete conformances.
860-
void MinimalConformances::computeMinimalConformances(bool firstPass) {
792+
void MinimalConformances::computeMinimalConformances() {
861793
for (unsigned ruleID : ConformanceRules) {
862794
auto found = ConformancePaths.find(ruleID);
863795
if (found == ConformancePaths.end())
864796
continue;
865797

798+
const auto &rule = System.getRule(ruleID);
866799
const auto &paths = found->second;
867800

868-
if (firstPass) {
869-
bool derivedViaConcrete = false;
870-
for (const auto &path : paths) {
871-
if (path.empty())
872-
continue;
873-
874-
// If the rule is itself a concrete conformance, it is not
875-
// derived-via-concrete via itself.
876-
if (path.size() == 1 && path.front() == ruleID)
877-
continue;
878-
879-
if (System.getRule(path.back()).getLHS().back().getKind() ==
880-
Symbol::Kind::ConcreteConformance) {
881-
derivedViaConcrete = true;
882-
break;
883-
}
884-
}
885-
886-
// If this rule doesn't involve concrete conformances it will be
887-
// considered in the second pass.
888-
if (!derivedViaConcrete)
889-
continue;
890-
891-
if (Debug.contains(DebugFlags::MinimalConformances)) {
892-
llvm::dbgs() << "Derived-via-concrete: ";
893-
dumpMinimalConformanceEquation(llvm::dbgs(), ruleID, paths);
894-
llvm::dbgs() << "\n";
895-
}
896-
} else {
897-
// Ignore rules already determined to be redundant by the first pass.
898-
if (RedundantConformances.count(ruleID) > 0)
899-
continue;
900-
}
901-
902801
bool isProtocolRefinement = ProtocolRefinements.count(ruleID) > 0;
903802

904803
for (const auto &path : paths) {
@@ -910,13 +809,10 @@ void MinimalConformances::computeMinimalConformances(bool firstPass) {
910809
llvm::SmallDenseSet<unsigned, 4> visited;
911810
visited.insert(ruleID);
912811

913-
if (isValidConformancePath(visited, path,
914-
ConcreteConformances::AllowedAtEnd)) {
812+
if (isValidConformancePath(visited, path)) {
915813
if (Debug.contains(DebugFlags::MinimalConformances)) {
916-
llvm::dbgs() << "Redundant rule in ";
917-
llvm::dbgs() << (firstPass ? "first" : "second");
918-
llvm::dbgs() << " pass: ";
919-
llvm::dbgs() << System.getRule(ruleID).getLHS();
814+
llvm::dbgs() << "Redundant rule: ";
815+
llvm::dbgs() << rule.getLHS();
920816
llvm::dbgs() << "\n";
921817
llvm::dbgs() << "-- via valid path: ";
922818
dumpConformancePath(llvm::errs(), path);
@@ -945,19 +841,7 @@ void MinimalConformances::verifyMinimalConformances() const {
945841
llvm::SmallVector<unsigned, 1> path;
946842
path.push_back(ruleID);
947843

948-
ConcreteConformances allowConcrete;
949-
if (rule.isProtocolConformanceRule()) {
950-
// Protocol conformance rules are recoverable if the path
951-
// has a concrete conformance at the end.
952-
allowConcrete = ConcreteConformances::AllowedAtEnd;
953-
} else {
954-
// Concrete conformance rules are recoverable via paths
955-
// containing other concrete conformances anywhere.
956-
assert(rule.isAnyConformanceRule());
957-
allowConcrete = ConcreteConformances::AllowedAnywhere;
958-
}
959-
960-
if (!isValidConformancePath(visited, path, allowConcrete)) {
844+
if (!isValidConformancePath(visited, path)) {
961845
llvm::errs() << "Redundant conformance is not recoverable:\n";
962846
llvm::errs() << rule << "\n\n";
963847
dumpMinimalConformanceEquations(llvm::errs());
@@ -1006,8 +890,7 @@ void RewriteSystem::computeMinimalConformances(
1006890
}
1007891

1008892
builder.verifyMinimalConformanceEquations();
1009-
builder.computeMinimalConformances(/*firstPass=*/true);
1010-
builder.computeMinimalConformances(/*firstPass=*/false);
893+
builder.computeMinimalConformances();
1011894
builder.verifyMinimalConformances();
1012895

1013896
if (Debug.contains(DebugFlags::MinimalConformances)) {

0 commit comments

Comments
 (0)