Skip to content

Commit 166d059

Browse files
authored
Merge pull request #70937 from slavapestov/rename-conformance-lookup
TypeChecker::conformsToProtocol() => ModuleDecl::checkConformance()
2 parents 5a3cad9 + 14d1fcb commit 166d059

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+261
-322
lines changed

include/swift/AST/Module.h

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -823,10 +823,7 @@ class ModuleDecl
823823
DeclName name,
824824
SmallVectorImpl<ValueDecl*> &results) const;
825825

826-
/// Look for the conformance of the given type to the given protocol.
827-
///
828-
/// This routine determines whether the given \c type conforms to the given
829-
/// \c protocol.
826+
/// Global conformance lookup, does not check conditional requirements.
830827
///
831828
/// \param type The type for which we are computing conformance.
832829
///
@@ -836,23 +833,33 @@ class ModuleDecl
836833
/// might include "missing" conformances, which are synthesized for some
837834
/// protocols as an error recovery mechanism.
838835
///
839-
/// \returns The result of the conformance search, which will be
840-
/// None if the type does not conform to the protocol or contain a
841-
/// ProtocolConformanceRef if it does conform.
836+
/// \returns An invalid conformance if the search failed, otherwise an
837+
/// abstract, concrete or pack conformance, depending on the lookup type.
842838
ProtocolConformanceRef lookupConformance(Type type, ProtocolDecl *protocol,
843839
bool allowMissing = false);
844840

841+
/// Global conformance lookup, checks conditional requirements.
842+
///
843+
/// \param type The type for which we are computing conformance. Must not
844+
/// contain type parameters.
845+
///
846+
/// \param protocol The protocol to which we are computing conformance.
847+
///
848+
/// \param allowMissing When \c true, the resulting conformance reference
849+
/// might include "missing" conformances, which are synthesized for some
850+
/// protocols as an error recovery mechanism.
851+
///
852+
/// \returns An invalid conformance if the search failed, otherwise an
853+
/// abstract, concrete or pack conformance, depending on the lookup type.
854+
ProtocolConformanceRef checkConformance(Type type, ProtocolDecl *protocol,
855+
// Note: different default than above
856+
bool allowMissing = true);
857+
845858
/// Look for the conformance of the given existential type to the given
846859
/// protocol.
847860
ProtocolConformanceRef lookupExistentialConformance(Type type,
848861
ProtocolDecl *protocol);
849862

850-
/// Exposes TypeChecker functionality for querying protocol conformance.
851-
/// Returns a valid ProtocolConformanceRef only if all conditional
852-
/// requirements are successfully resolved.
853-
ProtocolConformanceRef conformsToProtocol(Type sourceTy,
854-
ProtocolDecl *targetProtocol);
855-
856863
/// Collect the conformances of \c fromType to each of the protocols of an
857864
/// existential type's layout.
858865
///

include/swift/AST/Requirement.h

Lines changed: 23 additions & 0 deletions
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/Module.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2249,6 +2249,31 @@ LookupConformanceInModuleRequest::evaluate(
22492249
return ProtocolConformanceRef(conformance);
22502250
}
22512251

2252+
ProtocolConformanceRef
2253+
ModuleDecl::checkConformance(Type type, ProtocolDecl *proto,
2254+
bool allowMissing) {
2255+
auto lookupResult = lookupConformance(type, proto, allowMissing);
2256+
if (lookupResult.isInvalid()) {
2257+
return ProtocolConformanceRef::forInvalid();
2258+
}
2259+
2260+
auto condReqs = lookupResult.getConditionalRequirements();
2261+
2262+
// If we have a conditional requirements that we need to check, do so now.
2263+
if (!condReqs.empty()) {
2264+
switch (checkRequirements(condReqs)) {
2265+
case CheckRequirementsResult::Success:
2266+
break;
2267+
2268+
case CheckRequirementsResult::RequirementFailure:
2269+
case CheckRequirementsResult::SubstitutionFailure:
2270+
return ProtocolConformanceRef::forInvalid();
2271+
}
2272+
}
2273+
2274+
return lookupResult;
2275+
}
2276+
22522277
Fingerprint SourceFile::getInterfaceHash() const {
22532278
assert(hasInterfaceHash() && "Interface hash not enabled");
22542279
auto &eval = getASTContext().evaluator;

lib/AST/Requirement.cpp

Lines changed: 40 additions & 0 deletions
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/IDE/ConformingMethodList.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ void ConformingMethodListCallbacks::getMatchingMethods(
179179

180180
// The return type conforms to any of the requested protocols.
181181
for (auto Proto : ExpectedTypes) {
182-
if (CurModule->conformsToProtocol(resultTy, Proto))
182+
if (CurModule->checkConformance(resultTy, Proto))
183183
return true;
184184
}
185185

lib/IDE/IDETypeChecking.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ class ExpressionTypeCollector: public SourceEntityWalker {
689689

690690
// Collecting protocols conformed by this expressions that are in the list.
691691
for (auto Proto: InterestedProtocols) {
692-
if (Module.conformsToProtocol(E->getType(), Proto.first)) {
692+
if (Module.checkConformance(E->getType(), Proto.first)) {
693693
Conformances.push_back(Proto.second);
694694
}
695695
}

lib/Refactoring/Async/AsyncHandlerDesc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ using namespace swift::refactoring::asyncrefactorings;
1919
static bool isErrorType(Type Ty, ModuleDecl *MD) {
2020
if (!Ty)
2121
return false;
22-
return !MD->conformsToProtocol(Ty, Ty->getASTContext().getErrorDecl())
22+
return !MD->checkConformance(Ty, Ty->getASTContext().getErrorDecl())
2323
.isInvalid();
2424
}
2525

lib/SIL/IR/SILType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,7 @@ SILType SILType::removingMoveOnlyWrapperToBoxedType(const SILFunction *fn) {
12521252

12531253
ProtocolConformanceRef
12541254
SILType::conformsToProtocol(SILFunction *fn, ProtocolDecl *protocol) const {
1255-
return fn->getParentModule()->conformsToProtocol(getASTType(), protocol);
1255+
return fn->getParentModule()->checkConformance(getASTType(), protocol);
12561256
}
12571257

12581258
bool SILType::isSendable(SILFunction *fn) const {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3027,7 +3027,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30273027
if (!bitwiseCopyableProtocol)
30283028
return;
30293029

3030-
auto conformance = M.conformsToProtocol(substType, bitwiseCopyableProtocol);
3030+
auto conformance = M.checkConformance(substType, bitwiseCopyableProtocol);
30313031

30323032
if (lowering.isTrivial() && !conformance) {
30333033
// A trivial type can only lack a conformance if one of its leaves is a
@@ -3063,7 +3063,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
30633063

30643064
// A BitwiseCopyable conformer appearing within its layout doesn't
30653065
// explain why substType doesn't itself conform.
3066-
if (M.conformsToProtocol(ty, bitwiseCopyableProtocol))
3066+
if (M.checkConformance(ty, bitwiseCopyableProtocol))
30673067
return true;
30683068

30693069
// ModuleTypes are trivial but don't warrant being given a conformance
@@ -3143,7 +3143,7 @@ void TypeConverter::verifyTrivialLowering(const TypeLowering &lowering,
31433143

31443144
// Unfortunately, the type parameter's conformance may not be visible
31453145
// here.
3146-
assert(M.conformsToProtocol(ty, bitwiseCopyableProtocol) &&
3146+
assert(M.checkConformance(ty, bitwiseCopyableProtocol) &&
31473147
"leaf of non-trivial BitwiseCopyable type that doesn't "
31483148
"conform to BitwiseCopyable!?");
31493149

lib/SIL/Utils/DynamicCasts.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,17 @@ classifyDynamicCastToProtocol(ModuleDecl *M, CanType source, CanType target,
103103
if (!TargetProtocol)
104104
return DynamicCastFeasibility::MaySucceed;
105105

106-
// If the target is a parameterized protocol type, conformsToProtocol
106+
// If the target is a parameterized protocol type, checkConformance
107107
// is insufficient to prove the feasibility of the cast as it does not
108108
// check the additional requirements.
109109
// FIXME: This is a weak predicate that doesn't take into account
110110
// class compositions - since any C & P<T> doesn't work yet anyways.
111111
if (isa<ParameterizedProtocolType>(unwrapExistential(target)))
112112
return DynamicCastFeasibility::MaySucceed;
113113

114-
// If conformsToProtocol returns a valid conformance, then all requirements
115-
// were proven by the type checker.
116-
if (M->conformsToProtocol(source, TargetProtocol))
114+
// If checkConformance() returns a valid conformance, then all conditional
115+
// requirements were satisfied.
116+
if (M->checkConformance(source, TargetProtocol))
117117
return DynamicCastFeasibility::WillSucceed;
118118

119119
auto *SourceNominalTy = source.getAnyNominal();
@@ -141,14 +141,14 @@ classifyDynamicCastToProtocol(ModuleDecl *M, CanType source, CanType target,
141141
}
142142

143143
// The WillFail conditions below assume any possible conformance on the
144-
// nominal source type has been ruled out. The prior conformsToProtocol query
144+
// nominal source type has been ruled out. The prior checkConformance query
145145
// identified any definite conformance. Now check if there is already a known
146146
// conditional conformance on the nominal type with requirements that were
147147
// not proven.
148148
//
149149
// TODO: The TypeChecker can easily prove that some requirements cannot be
150150
// met. Returning WillFail in those cases would be more optimal. To do that,
151-
// the conformsToProtocol interface needs to be reformulated as a query, and
151+
// the checkConformance interface needs to be reformulated as a query, and
152152
// the implementation, including checkGenericArguments, needs to be taught to
153153
// recognize that types with archetypes may potentially succeed.
154154
if (auto conformance = M->lookupConformance(source, TargetProtocol)) {

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5866,7 +5866,7 @@ SILValue SILGenFunction::emitApplyWithRethrow(SILLocation loc, SILValue fn,
58665866
assert(outerErrorType == SILType::getExceptionType(getASTContext()));
58675867

58685868
ProtocolConformanceRef conformances[1] = {
5869-
getModule().getSwiftModule()->conformsToProtocol(
5869+
getModule().getSwiftModule()->checkConformance(
58705870
innerError->getType().getASTType(),
58715871
getASTContext().getErrorDecl())
58725872
};

lib/SILGen/SILGenExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5950,7 +5950,7 @@ static void diagnoseImplicitRawConversion(Type sourceTy, Type pointerTy,
59505950
auto *SM = SGF.getModule().getSwiftModule();
59515951
if (auto *fixedWidthIntegerDecl = SM->getASTContext().getProtocol(
59525952
KnownProtocolKind::FixedWidthInteger)) {
5953-
if (SM->conformsToProtocol(eltTy, fixedWidthIntegerDecl))
5953+
if (SM->checkConformance(eltTy, fixedWidthIntegerDecl))
59545954
return;
59555955
}
59565956

lib/SILGen/SILGenStmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1606,7 +1606,7 @@ void SILGenFunction::emitThrow(SILLocation loc, ManagedValue exnMV,
16061606
assert(destErrorType == SILType::getExceptionType(getASTContext()));
16071607

16081608
ProtocolConformanceRef conformances[1] = {
1609-
getModule().getSwiftModule()->conformsToProtocol(
1609+
getModule().getSwiftModule()->checkConformance(
16101610
exn->getType().getASTType(), getASTContext().getErrorDecl())
16111611
};
16121612

lib/SILOptimizer/Utils/CastOptimizer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,14 +1461,14 @@ static bool optimizeStaticallyKnownProtocolConformance(
14611461
// SourceType is a non-existential type with a non-conditional
14621462
// conformance to a protocol represented by the TargetType.
14631463
//
1464-
// TypeChecker::conformsToProtocol checks any conditional conformances. If
1464+
// ModuleDecl::checkConformance() checks any conditional conformances. If
14651465
// they depend on information not known until runtime, the conformance
14661466
// will not be returned. For instance, if `X: P` where `T == Int` in `func
14671467
// foo<T>(_: T) { ... X<T>() as? P ... }`, the cast will succeed for
14681468
// `foo(0)` but not for `foo("string")`. There are many cases where
14691469
// everything is completely static (`X<Int>() as? P`), in which case a
14701470
// valid conformance will be returned.
1471-
auto Conformance = SM->conformsToProtocol(SourceType, Proto);
1471+
auto Conformance = SM->checkConformance(SourceType, Proto);
14721472
if (Conformance.isInvalid())
14731473
return false;
14741474

lib/SILOptimizer/Utils/Existential.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ ConcreteExistentialInfo::ConcreteExistentialInfo(SILValue existential,
389389

390390
// We have the open_existential; we still need the conformance.
391391
auto ConformanceRef =
392-
M->getSwiftModule()->conformsToProtocol(ConcreteTypeCandidate, Protocol);
392+
M->getSwiftModule()->checkConformance(ConcreteTypeCandidate, Protocol);
393393
if (ConformanceRef.isInvalid())
394394
return;
395395

0 commit comments

Comments
 (0)