2.2 KiB
swift-0001: isInMinimizationDomain — O(P) linear scan in O(R) rule loop
Severity: HIGH
Location
lib/AST/RequirementMachine/RewriteSystem.cpp:484- Called from loops in:
lib/AST/RequirementMachine/HomotopyReduction.cpp:611,659,753lib/AST/RequirementMachine/MinimalConformances.cpp:326lib/AST/RequirementMachine/Diagnostics.cpp:349lib/AST/RequirementMachine/PropertyUnification.cpp:133
Description
RewriteSystem::isInMinimizationDomain() performs a linear std::find scan over
Protos (an ArrayRef<const ProtocolDecl *>) on every call. This function is invoked
inside loops over all rewrite Rules (size scales with protocol graph complexity).
Complexity: O(R × P) where R = rule count, P = protocol count in connected component. For a deeply hierarchical protocol graph with N protocols, both R and P are O(N), yielding O(N²) total cost during requirement signature minimization.
Root Cause
// RewriteSystem.cpp:478
bool RewriteSystem::isInMinimizationDomain(const ProtocolDecl *proto) const {
// ...
if (std::find(Protos.begin(), Protos.end(), proto) != Protos.end())
return true;
return false;
}
Protos is ArrayRef<const ProtocolDecl *> — a plain pointer array. std::find is O(P).
Called inside every rule-scanning loop; no caching or set-based lookup.
Fix
Replace ArrayRef<const ProtocolDecl *> Protos with llvm::DenseSet<const ProtocolDecl *> ProtoSet
populated once at construction, or cache a llvm::SmallPtrSet alongside the ArrayRef.
Then isInMinimizationDomain becomes an O(1) hash set lookup.
// In RewriteSystem.h, add:
llvm::SmallPtrSet<const ProtocolDecl *, 8> ProtoSet;
// In RewriteSystem::init or wherever Protos is set:
ProtoSet.insert(Protos.begin(), Protos.end());
// In isInMinimizationDomain:
bool RewriteSystem::isInMinimizationDomain(const ProtocolDecl *proto) const {
if (proto == nullptr && Protos.empty())
return true;
return ProtoSet.count(proto) > 0;
}
Impact
Protocol-heavy Swift code (many protocols with complex inheritance) hits O(N²) during generic signature computation. Manifest as slow compilation on codebases with many protocols or deep protocol hierarchies (e.g., Combine/SwiftUI framework chains).