mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
RequirementMachine: Teach generating conformances to understand protocol refinement
For implementation reasons we want the requirement signature of a protocol to directly include all protocol refinement relationships, even if they can be derived via same-type requirements between Self and some nested type. Therefore, a protocol refinement rule [P].[Q] => [P] can only be replaced with a generating conformance equation that consists entirely of other conformance rules. This exactly simulates the existing behavior of the GSB's redundant requirements algorithm.
This commit is contained in:
@@ -369,6 +369,23 @@ bool RewriteSystem::isValidConformancePath(
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Rules of the form [P].[Q] => [P] encode protocol refinement and can only
|
||||
/// be redundant if they're equivalent to a sequence of other protocol
|
||||
/// refinements.
|
||||
///
|
||||
/// This helps ensure that the inheritance clause of a protocol is complete
|
||||
/// and correct, allowing name lookup to find associated types of inherited
|
||||
/// protocols while building the protocol requirement signature.
|
||||
bool RewriteSystem::isValidRefinementPath(
|
||||
const llvm::SmallVectorImpl<unsigned> &path) const {
|
||||
for (unsigned ruleID : path) {
|
||||
if (!getRule(ruleID).isProtocolRefinementRule())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RewriteSystem::dumpGeneratingConformanceEquation(
|
||||
llvm::raw_ostream &out,
|
||||
unsigned baseRuleID,
|
||||
@@ -444,6 +461,8 @@ void RewriteSystem::computeGeneratingConformances(
|
||||
llvm::DenseSet<unsigned> &redundantConformances) {
|
||||
llvm::MapVector<unsigned, std::vector<SmallVector<unsigned, 2>>> conformancePaths;
|
||||
|
||||
llvm::DenseSet<unsigned> protocolRefinements;
|
||||
|
||||
// Prepare the initial set of equations: every non-redundant conformance rule
|
||||
// can be expressed as itself.
|
||||
for (unsigned ruleID : indices(Rules)) {
|
||||
@@ -457,6 +476,9 @@ void RewriteSystem::computeGeneratingConformances(
|
||||
SmallVector<unsigned, 2> path;
|
||||
path.push_back(ruleID);
|
||||
conformancePaths[ruleID].push_back(path);
|
||||
|
||||
if (rule.isProtocolRefinementRule())
|
||||
protocolRefinements.insert(ruleID);
|
||||
}
|
||||
|
||||
computeCandidateConformancePaths(conformancePaths);
|
||||
@@ -475,7 +497,14 @@ void RewriteSystem::computeGeneratingConformances(
|
||||
|
||||
// Find a minimal set of generating conformances.
|
||||
for (const auto &pair : conformancePaths) {
|
||||
bool isProtocolRefinement = protocolRefinements.count(pair.first) > 0;
|
||||
|
||||
for (const auto &path : pair.second) {
|
||||
// Only consider a protocol refinement rule to be redundant if it is
|
||||
// witnessed by a composition of other protocol refinement rules.
|
||||
if (isProtocolRefinement && !isValidRefinementPath(path))
|
||||
continue;
|
||||
|
||||
llvm::SmallDenseSet<unsigned, 4> visited;
|
||||
visited.insert(pair.first);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user