Skip to content

Commit cfd8dbf

Browse files
authored
Merge pull request #40465 from slavapestov/rqm-protocol-minimization-fixes
RequirementMachine: Protocol requirement signature minimization fixes
2 parents a46a3c5 + 8a08872 commit cfd8dbf

22 files changed

+713
-667
lines changed

include/swift/AST/ASTContext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,11 @@ class ASTContext final {
12311231
bool isRecursivelyConstructingRequirementMachine(
12321232
CanGenericSignature sig);
12331233

1234+
/// This is a hack to break cycles. Don't introduce new callers of this
1235+
/// method.
1236+
bool isRecursivelyConstructingRequirementMachine(
1237+
const ProtocolDecl *proto);
1238+
12341239
/// Retrieve a generic signature with a single unconstrained type parameter,
12351240
/// like `<T>`.
12361241
CanGenericSignature getSingleGenericParameterSignature() const;

lib/AST/ASTContext.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,6 +2017,11 @@ bool ASTContext::isRecursivelyConstructingRequirementMachine(
20172017
return getRewriteContext().isRecursivelyConstructingRequirementMachine(sig);
20182018
}
20192019

2020+
bool ASTContext::isRecursivelyConstructingRequirementMachine(
2021+
const ProtocolDecl *proto) {
2022+
return getRewriteContext().isRecursivelyConstructingRequirementMachine(proto);
2023+
}
2024+
20202025
Optional<llvm::TinyPtrVector<ValueDecl *>>
20212026
OverriddenDeclsRequest::getCachedResult() const {
20222027
auto decl = std::get<0>(getStorage());

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3991,6 +3991,8 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
39913991
auto protocolSubMap = SubstitutionMap::getProtocolSubstitutions(
39923992
proto, selfType.getDependentType(*this), ProtocolConformanceRef(proto));
39933993

3994+
auto result = ConstraintResult::Resolved;
3995+
39943996
// Use the requirement signature to avoid rewalking the entire protocol. This
39953997
// cannot compute the requirement signature directly, because that may be
39963998
// infinitely recursive: this code is also used to construct it.
@@ -4007,19 +4009,20 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
40074009
auto reqResult = substReq
40084010
? addRequirement(*substReq, innerSource, nullptr)
40094011
: ConstraintResult::Conflicting;
4010-
if (isErrorResult(reqResult)) return reqResult;
4012+
if (isErrorResult(reqResult) && !isErrorResult(result))
4013+
result = reqResult;
40114014
}
40124015

4013-
return ConstraintResult::Resolved;
4016+
return result;
40144017
}
40154018

40164019
if (!onlySameTypeConstraints) {
40174020
// Add all of the inherited protocol requirements, recursively.
40184021
auto inheritedReqResult =
40194022
addInheritedRequirements(proto, selfType.getUnresolvedType(), source,
40204023
nullptr);
4021-
if (isErrorResult(inheritedReqResult))
4022-
return inheritedReqResult;
4024+
if (isErrorResult(inheritedReqResult) && !isErrorResult(inheritedReqResult))
4025+
result = inheritedReqResult;
40234026
}
40244027

40254028
// Add any requirements in the where clause on the protocol.
@@ -4048,7 +4051,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
40484051
getASTContext()),
40494052
innerSource);
40504053

4051-
return ConstraintResult::Resolved;
4054+
return result;
40524055
}
40534056

40544057
// Remaining logic is not relevant in ObjC protocol cases.
@@ -4156,11 +4159,13 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
41564159
Type assocType =
41574160
DependentMemberType::get(selfType.getDependentType(*this), assocTypeDecl);
41584161
if (!onlySameTypeConstraints) {
4162+
(void) resolve(assocType, source);
4163+
41594164
auto assocResult =
41604165
addInheritedRequirements(assocTypeDecl, assocType, source,
41614166
/*inferForModule=*/nullptr);
4162-
if (isErrorResult(assocResult))
4163-
return assocResult;
4167+
if (isErrorResult(assocResult) && !isErrorResult(result))
4168+
result = assocResult;
41644169
}
41654170

41664171
// Add requirements from this associated type's where clause.
@@ -4314,7 +4319,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
43144319
}
43154320
}
43164321

4317-
return ConstraintResult::Resolved;
4322+
return result;
43184323
}
43194324

43204325
ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
@@ -8873,9 +8878,23 @@ RequirementSignatureRequest::evaluate(Evaluator &evaluator,
88738878
auto rqmResult = buildViaRQM();
88748879
auto gsbResult = buildViaGSB();
88758880

8876-
if (rqmResult.size() != gsbResult.size() ||
8877-
!std::equal(rqmResult.begin(), rqmResult.end(),
8878-
gsbResult.begin())) {
8881+
// For now, only compare conformance requirements, since those are the
8882+
// important ones from the ABI perspective.
8883+
SmallVector<Requirement, 2> rqmConformances;
8884+
for (auto req : rqmResult) {
8885+
if (req.getKind() == RequirementKind::Conformance)
8886+
rqmConformances.push_back(req);
8887+
}
8888+
SmallVector<Requirement, 2> gsbConformances;
8889+
for (auto req : gsbResult) {
8890+
if (req.getKind() == RequirementKind::Conformance)
8891+
gsbConformances.push_back(req);
8892+
}
8893+
8894+
if (rqmConformances.size() != gsbConformances.size() ||
8895+
!std::equal(rqmConformances.begin(),
8896+
rqmConformances.end(),
8897+
gsbConformances.begin())) {
88798898
llvm::errs() << "RequirementMachine protocol signature minimization is broken:\n";
88808899
llvm::errs() << "Protocol: " << proto->getName() << "\n";
88818900

0 commit comments

Comments
 (0)