Skip to content

Commit 1e950b1

Browse files
committed
AST: Move checkGenericArguments() to AST and rename to checkRequirements()
1 parent a48dc87 commit 1e950b1

11 files changed

+117
-136
lines changed

include/swift/AST/Requirement.h

+23
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,29 @@ inline void simple_display(llvm::raw_ostream &out, const Requirement &req) {
207207
req.print(out, PrintOptions());
208208
}
209209

210+
enum class CheckRequirementsResult : uint8_t {
211+
Success,
212+
213+
/// One of the requirements was unsatisfied.
214+
RequirementFailure,
215+
216+
/// One of the requirements contained error types, either because of an
217+
/// invalid conformance or because it contained a member type that was
218+
/// dependent on an earlier conformance requirement that failed.
219+
SubstitutionFailure
220+
};
221+
222+
/// Check if each substituted requirement is satisfied. The requirement must
223+
/// not contain any type parameters.
224+
CheckRequirementsResult checkRequirements(ArrayRef<Requirement> requirements);
225+
226+
/// Check if each requirement is satisfied after applying the given
227+
/// substitutions. The substitutions must replace all type parameters that
228+
/// appear in the requirement with concrete types or archetypes.
229+
CheckRequirementsResult checkRequirements(
230+
ModuleDecl *module, ArrayRef<Requirement> requirements,
231+
TypeSubstitutionFn substitutions, SubstOptions options=llvm::None);
232+
210233
/// A requirement as written in source, together with a source location. See
211234
/// ProtocolDecl::getStructuralRequirements().
212235
struct StructuralRequirement {

lib/AST/Requirement.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,46 @@ int Requirement::compare(const Requirement &other) const {
246246
return compareProtos;
247247
}
248248

249+
CheckRequirementsResult swift::checkRequirements(ArrayRef<Requirement> requirements) {
250+
SmallVector<Requirement, 4> worklist(requirements.begin(), requirements.end());
251+
252+
bool hadSubstFailure = false;
253+
254+
while (!worklist.empty()) {
255+
auto req = worklist.pop_back_val();
256+
switch (req.checkRequirement(worklist, /*allowMissing=*/true)) {
257+
case CheckRequirementResult::Success:
258+
case CheckRequirementResult::ConditionalConformance:
259+
case CheckRequirementResult::PackRequirement:
260+
break;
261+
262+
case CheckRequirementResult::RequirementFailure:
263+
return CheckRequirementsResult::RequirementFailure;
264+
265+
case CheckRequirementResult::SubstitutionFailure:
266+
hadSubstFailure = true;
267+
break;
268+
}
269+
}
270+
271+
if (hadSubstFailure)
272+
return CheckRequirementsResult::SubstitutionFailure;
273+
274+
return CheckRequirementsResult::Success;
275+
}
276+
277+
CheckRequirementsResult swift::checkRequirements(
278+
ModuleDecl *module, ArrayRef<Requirement> requirements,
279+
TypeSubstitutionFn substitutions, SubstOptions options) {
280+
SmallVector<Requirement, 4> substReqs;
281+
for (auto req : requirements) {
282+
substReqs.push_back(req.subst(substitutions,
283+
LookUpConformanceInModule(module), options));
284+
}
285+
286+
return checkRequirements(substReqs);
287+
}
288+
249289
InverseRequirement::InverseRequirement(Type subject,
250290
ProtocolDecl *protocol,
251291
SourceLoc loc)

lib/Sema/CSStep.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -663,12 +663,12 @@ bool IsDeclRefinementOfRequest::evaluate(Evaluator &evaluator,
663663
if (!substTypeB)
664664
return false;
665665

666-
auto result = TypeChecker::checkGenericArguments(
666+
auto result = checkRequirements(
667667
declA->getDeclContext()->getParentModule(),
668668
genericSignatureB.getRequirements(),
669669
QueryTypeSubstitutionMap{ substMap });
670670

671-
if (result != CheckGenericArgumentsResult::Success)
671+
if (result != CheckRequirementsResult::Success)
672672
return false;
673673

674674
return substTypeA->isEqual(substTypeB);

lib/Sema/CodeSynthesis.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -740,14 +740,14 @@ createDesignatedInitOverride(ClassDecl *classDecl,
740740
// requirements on the base class's own generic parameters that are not
741741
// satisfied by the derived class. In this case, we don't want to inherit
742742
// this initializer; there's no way to call it on the derived class.
743-
auto checkResult = TypeChecker::checkGenericArguments(
743+
auto checkResult = checkRequirements(
744744
classDecl->getParentModule(),
745745
superclassCtorSig.getRequirements(),
746746
[&](Type type) -> Type {
747747
auto substType = type.subst(subMap);
748748
return GenericEnvironment::mapTypeIntoContext(genericEnv, substType);
749749
});
750-
if (checkResult != CheckGenericArgumentsResult::Success)
750+
if (checkResult != CheckRequirementsResult::Success)
751751
return nullptr;
752752
}
753753

lib/Sema/IDETypeCheckingRequests.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,10 @@ static bool isExtensionAppliedInternal(const DeclContext *DC, Type BaseTy,
134134
auto *module = DC->getParentModule();
135135
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap(
136136
module, ED->getExtendedNominal());
137-
return TypeChecker::checkGenericArguments(module,
138-
genericSig.getRequirements(),
139-
QuerySubstitutionMap{substMap}) ==
140-
CheckGenericArgumentsResult::Success;
137+
return checkRequirements(module,
138+
genericSig.getRequirements(),
139+
QuerySubstitutionMap{substMap}) ==
140+
CheckRequirementsResult::Success;
141141
}
142142

143143
static bool isMemberDeclAppliedInternal(const DeclContext *DC, Type BaseTy,
@@ -171,10 +171,10 @@ static bool isMemberDeclAppliedInternal(const DeclContext *DC, Type BaseTy,
171171

172172
// Note: we treat substitution failure as success, to avoid tripping
173173
// up over generic parameters introduced by the declaration itself.
174-
return TypeChecker::checkGenericArguments(module,
175-
genericSig.getRequirements(),
176-
QuerySubstitutionMap{substMap}) !=
177-
CheckGenericArgumentsResult::RequirementFailure;
174+
return checkRequirements(module,
175+
genericSig.getRequirements(),
176+
QuerySubstitutionMap{substMap}) !=
177+
CheckRequirementsResult::RequirementFailure;
178178
}
179179

180180
bool

lib/Sema/TypeCheckAttr.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -3739,8 +3739,7 @@ TypeEraserHasViableInitRequest::evaluate(Evaluator &evaluator,
37393739
nominalTypeDecl);
37403740
QuerySubstitutionMap getSubstitution{baseMap};
37413741

3742-
// Use invalid 'SourceLoc's to suppress diagnostics.
3743-
auto result = TypeChecker::checkGenericArguments(
3742+
auto result = checkRequirements(
37443743
module, genericSignature.getRequirements(),
37453744
[&](SubstitutableType *type) -> Type {
37463745
if (type->isEqual(genericParamType))
@@ -3749,7 +3748,7 @@ TypeEraserHasViableInitRequest::evaluate(Evaluator &evaluator,
37493748
return getSubstitution(type);
37503749
});
37513750

3752-
if (result != CheckGenericArgumentsResult::Success) {
3751+
if (result != CheckRequirementsResult::Success) {
37533752
unviable.push_back(
37543753
std::make_tuple(init, UnviableReason::UnsatisfiedRequirements,
37553754
genericParamType));

lib/Sema/TypeCheckGeneric.cpp

-64
Original file line numberDiff line numberDiff line change
@@ -1064,70 +1064,6 @@ CheckGenericArgumentsResult TypeChecker::checkGenericArgumentsForDiagnostics(
10641064
return CheckGenericArgumentsResult::createSuccess();
10651065
}
10661066

1067-
CheckGenericArgumentsResult::Kind TypeChecker::checkGenericArguments(
1068-
ModuleDecl *module, ArrayRef<Requirement> requirements,
1069-
TypeSubstitutionFn substitutions, SubstOptions options) {
1070-
SmallVector<Requirement, 4> worklist;
1071-
1072-
bool hadSubstFailure = false;
1073-
1074-
for (auto req : requirements) {
1075-
worklist.push_back(req.subst(substitutions,
1076-
LookUpConformanceInModule(module), options));
1077-
}
1078-
1079-
while (!worklist.empty()) {
1080-
auto req = worklist.pop_back_val();
1081-
switch (req.checkRequirement(worklist, /*allowMissing=*/true)) {
1082-
case CheckRequirementResult::Success:
1083-
case CheckRequirementResult::ConditionalConformance:
1084-
case CheckRequirementResult::PackRequirement:
1085-
break;
1086-
1087-
case CheckRequirementResult::RequirementFailure:
1088-
return CheckGenericArgumentsResult::RequirementFailure;
1089-
1090-
case CheckRequirementResult::SubstitutionFailure:
1091-
hadSubstFailure = true;
1092-
break;
1093-
}
1094-
}
1095-
1096-
if (hadSubstFailure)
1097-
return CheckGenericArgumentsResult::SubstitutionFailure;
1098-
1099-
return CheckGenericArgumentsResult::Success;
1100-
}
1101-
1102-
CheckGenericArgumentsResult::Kind TypeChecker::checkGenericArguments(
1103-
ArrayRef<Requirement> requirements) {
1104-
SmallVector<Requirement, 4> worklist(requirements.begin(), requirements.end());
1105-
1106-
bool hadSubstFailure = false;
1107-
1108-
while (!worklist.empty()) {
1109-
auto req = worklist.pop_back_val();
1110-
switch (req.checkRequirement(worklist, /*allowMissing=*/true)) {
1111-
case CheckRequirementResult::Success:
1112-
case CheckRequirementResult::ConditionalConformance:
1113-
case CheckRequirementResult::PackRequirement:
1114-
break;
1115-
1116-
case CheckRequirementResult::RequirementFailure:
1117-
return CheckGenericArgumentsResult::RequirementFailure;
1118-
1119-
case CheckRequirementResult::SubstitutionFailure:
1120-
hadSubstFailure = true;
1121-
break;
1122-
}
1123-
}
1124-
1125-
if (hadSubstFailure)
1126-
return CheckGenericArgumentsResult::SubstitutionFailure;
1127-
1128-
return CheckGenericArgumentsResult::Success;
1129-
}
1130-
11311067
Requirement
11321068
RequirementRequest::evaluate(Evaluator &evaluator,
11331069
WhereClauseOwner owner,

lib/Sema/TypeCheckProtocol.cpp

+12-18
Original file line numberDiff line numberDiff line change
@@ -5138,21 +5138,21 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
51385138

51395139
const auto result = TypeChecker::checkGenericArgumentsForDiagnostics(
51405140
module, reqSig, QuerySubstitutionMap{substitutions});
5141-
switch (result) {
5142-
case CheckGenericArgumentsResult::Success:
5141+
switch (result.getKind()) {
5142+
case CheckRequirementsResult::Success:
51435143
// Go on to check exportability.
51445144
break;
51455145

5146-
case CheckGenericArgumentsResult::RequirementFailure:
5147-
case CheckGenericArgumentsResult::SubstitutionFailure:
5146+
case CheckRequirementsResult::RequirementFailure:
5147+
case CheckRequirementsResult::SubstitutionFailure:
51485148
// Diagnose the failure generically.
51495149
// FIXME: Would be nice to give some more context here!
51505150
if (!Conformance->isInvalid()) {
51515151
diags.diagnose(Loc, diag::type_does_not_conform,
51525152
Adoptee,
51535153
Proto->getDeclaredInterfaceType());
51545154

5155-
if (result == CheckGenericArgumentsResult::RequirementFailure) {
5155+
if (result.getKind() == CheckRequirementsResult::RequirementFailure) {
51565156
TypeChecker::diagnoseRequirementFailure(
51575157
result.getRequirementFailureInfo(), Loc, Loc,
51585158
proto->getDeclaredInterfaceType(),
@@ -5795,27 +5795,21 @@ ProtocolConformanceRef
57955795
TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M,
57965796
bool allowMissing) {
57975797
// Look up conformance in the module.
5798-
auto lookupResult = M->lookupConformance(
5799-
T, Proto, allowMissing);
5800-
5798+
auto lookupResult = M->lookupConformance(T, Proto, allowMissing);
58015799
if (lookupResult.isInvalid()) {
58025800
return ProtocolConformanceRef::forInvalid();
58035801
}
58045802

5805-
auto condReqs = lookupResult.getConditionalRequirementsIfAvailable();
5806-
assert(condReqs &&
5807-
"unhandled recursion: missing conditional requirements when they're "
5808-
"required");
5803+
auto condReqs = lookupResult.getConditionalRequirements();
58095804

58105805
// If we have a conditional requirements that we need to check, do so now.
5811-
if (!condReqs->empty()) {
5812-
auto conditionalCheckResult = checkGenericArguments(*condReqs);
5813-
switch (conditionalCheckResult) {
5814-
case CheckGenericArgumentsResult::Success:
5806+
if (!condReqs.empty()) {
5807+
switch (checkRequirements(condReqs)) {
5808+
case CheckRequirementsResult::Success:
58155809
break;
58165810

5817-
case CheckGenericArgumentsResult::RequirementFailure:
5818-
case CheckGenericArgumentsResult::SubstitutionFailure:
5811+
case CheckRequirementsResult::RequirementFailure:
5812+
case CheckRequirementsResult::SubstitutionFailure:
58195813
return ProtocolConformanceRef::forInvalid();
58205814
}
58215815
}

lib/Sema/TypeCheckProtocolInference.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -1353,17 +1353,17 @@ bool AssociatedTypeInference::checkCurrentTypeWitnesses(
13531353
sanitizeProtocolRequirements(proto, requirements,
13541354
sanitizedRequirements);
13551355

1356-
switch (TypeChecker::checkGenericArguments(
1356+
switch (checkRequirements(
13571357
dc->getParentModule(), sanitizedRequirements,
13581358
QuerySubstitutionMap{substitutions}, options)) {
1359-
case CheckGenericArgumentsResult::RequirementFailure:
1359+
case CheckRequirementsResult::RequirementFailure:
13601360
++NumSolutionStatesFailedCheck;
13611361
LLVM_DEBUG(llvm::dbgs() << std::string(valueWitnesses.size(), '+')
13621362
<< "+ Requirement failure\n";);
13631363
return true;
13641364

1365-
case CheckGenericArgumentsResult::Success:
1366-
case CheckGenericArgumentsResult::SubstitutionFailure:
1365+
case CheckRequirementsResult::Success:
1366+
case CheckRequirementsResult::SubstitutionFailure:
13671367
break;
13681368
}
13691369

@@ -1401,14 +1401,14 @@ bool AssociatedTypeInference::checkConstrainedExtension(ExtensionDecl *ext) {
14011401
auto subs = typeInContext->getContextSubstitutions(ext);
14021402

14031403
SubstOptions options = getSubstOptionsWithCurrentTypeWitnesses();
1404-
switch (TypeChecker::checkGenericArguments(
1404+
switch (checkRequirements(
14051405
dc->getParentModule(), ext->getGenericSignature().getRequirements(),
14061406
QueryTypeSubstitutionMap{subs}, options)) {
1407-
case CheckGenericArgumentsResult::Success:
1408-
case CheckGenericArgumentsResult::SubstitutionFailure:
1407+
case CheckRequirementsResult::Success:
1408+
case CheckRequirementsResult::SubstitutionFailure:
14091409
return false;
14101410

1411-
case CheckGenericArgumentsResult::RequirementFailure:
1411+
case CheckRequirementsResult::RequirementFailure:
14121412
return true;
14131413
}
14141414
llvm_unreachable("unhandled result");

lib/Sema/TypeCheckType.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -651,8 +651,8 @@ bool TypeChecker::checkContextualRequirements(GenericTypeDecl *decl,
651651

652652
const auto result = TypeChecker::checkGenericArgumentsForDiagnostics(
653653
module, genericSig.getRequirements(), substitutions);
654-
switch (result) {
655-
case CheckGenericArgumentsResult::RequirementFailure:
654+
switch (result.getKind()) {
655+
case CheckRequirementsResult::RequirementFailure:
656656
if (loc.isValid()) {
657657
TypeChecker::diagnoseRequirementFailure(
658658
result.getRequirementFailureInfo(), loc, noteLoc,
@@ -661,9 +661,9 @@ bool TypeChecker::checkContextualRequirements(GenericTypeDecl *decl,
661661
}
662662

663663
return false;
664-
case CheckGenericArgumentsResult::SubstitutionFailure:
664+
case CheckRequirementsResult::SubstitutionFailure:
665665
return false;
666-
case CheckGenericArgumentsResult::Success:
666+
case CheckRequirementsResult::Success:
667667
return true;
668668
}
669669
llvm_unreachable("invalid requirement check type");
@@ -1158,8 +1158,8 @@ Type TypeResolution::applyUnboundGenericArguments(
11581158

11591159
const auto result = TypeChecker::checkGenericArgumentsForDiagnostics(
11601160
module, genericSig.getRequirements(), substitutions);
1161-
switch (result) {
1162-
case CheckGenericArgumentsResult::RequirementFailure:
1161+
switch (result.getKind()) {
1162+
case CheckRequirementsResult::RequirementFailure:
11631163
if (loc.isValid()) {
11641164
TypeChecker::diagnoseRequirementFailure(
11651165
result.getRequirementFailureInfo(), loc, noteLoc,
@@ -1168,9 +1168,9 @@ Type TypeResolution::applyUnboundGenericArguments(
11681168
}
11691169

11701170
LLVM_FALLTHROUGH;
1171-
case CheckGenericArgumentsResult::SubstitutionFailure:
1171+
case CheckRequirementsResult::SubstitutionFailure:
11721172
return ErrorType::get(getASTContext());
1173-
case CheckGenericArgumentsResult::Success:
1173+
case CheckRequirementsResult::Success:
11741174
break;
11751175
}
11761176
}

0 commit comments

Comments
 (0)