Skip to content

Commit 14d1fcb

Browse files
committed
AST: TypeChecker::conformsToProtocol() => ModuleDecl::checkConformance()
1 parent 1e950b1 commit 14d1fcb

35 files changed

+151
-193
lines changed

include/swift/AST/Module.h

+20-13
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
///

lib/AST/Module.cpp

+25
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/IDE/ConformingMethodList.cpp

+1-1
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

+1-1
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

+1-1
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

+1-1
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

+3-3
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

+6-6
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

+1-1
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

+1-1
Original file line numberDiff line numberDiff line change
@@ -5949,7 +5949,7 @@ static void diagnoseImplicitRawConversion(Type sourceTy, Type pointerTy,
59495949
auto *SM = SGF.getModule().getSwiftModule();
59505950
if (auto *fixedWidthIntegerDecl = SM->getASTContext().getProtocol(
59515951
KnownProtocolKind::FixedWidthInteger)) {
5952-
if (SM->conformsToProtocol(eltTy, fixedWidthIntegerDecl))
5952+
if (SM->checkConformance(eltTy, fixedWidthIntegerDecl))
59535953
return;
59545954
}
59555955

lib/SILGen/SILGenStmt.cpp

+1-1
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

+2-2
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

+1-1
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

lib/Sema/CSApply.cpp

+19-27
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ Solution::computeSubstitutions(GenericSignature sig,
113113
}
114114

115115
// FIXME: Retrieve the conformance from the solution itself.
116-
return TypeChecker::conformsToProtocol(replacement, protoType,
117-
getConstraintSystem().DC->getParentModule());
116+
return getConstraintSystem().DC->getParentModule()->checkConformance(
117+
replacement, protoType);
118118
};
119119

120120
return SubstitutionMap::get(sig,
@@ -565,7 +565,7 @@ namespace {
565565
// the protocol requirement with Self == the concrete type, and SILGen
566566
// (or later) can devirtualize as appropriate.
567567
auto conformance =
568-
TypeChecker::conformsToProtocol(baseTy, proto, dc->getParentModule());
568+
dc->getParentModule()->checkConformance(baseTy, proto);
569569
if (conformance.isConcrete()) {
570570
if (auto witness = conformance.getConcrete()->getWitnessDecl(decl)) {
571571
bool isMemberOperator = witness->getDeclContext()->isTypeContext();
@@ -2459,9 +2459,7 @@ namespace {
24592459

24602460
// Try to find the conformance of the value type to _BridgedToObjectiveC.
24612461
auto bridgedToObjectiveCConformance
2462-
= TypeChecker::conformsToProtocol(valueType,
2463-
bridgedProto,
2464-
dc->getParentModule());
2462+
= dc->getParentModule()->checkConformance(valueType, bridgedProto);
24652463

24662464
FuncDecl *fn = nullptr;
24672465

@@ -2722,7 +2720,7 @@ namespace {
27222720
ProtocolDecl *protocol = TypeChecker::getProtocol(
27232721
ctx, expr->getLoc(), KnownProtocolKind::ExpressibleByStringLiteral);
27242722

2725-
if (!TypeChecker::conformsToProtocol(type, protocol, dc->getParentModule())) {
2723+
if (!dc->getParentModule()->checkConformance(type, protocol)) {
27262724
// If the type does not conform to ExpressibleByStringLiteral, it should
27272725
// be ExpressibleByExtendedGraphemeClusterLiteral.
27282726
protocol = TypeChecker::getProtocol(
@@ -2731,7 +2729,7 @@ namespace {
27312729
isStringLiteral = false;
27322730
isGraphemeClusterLiteral = true;
27332731
}
2734-
if (!TypeChecker::conformsToProtocol(type, protocol, dc->getParentModule())) {
2732+
if (!dc->getParentModule()->checkConformance(type, protocol)) {
27352733
// ... or it should be ExpressibleByUnicodeScalarLiteral.
27362734
protocol = TypeChecker::getProtocol(
27372735
cs.getASTContext(), expr->getLoc(),
@@ -2846,7 +2844,7 @@ namespace {
28462844
assert(proto && "Missing string interpolation protocol?");
28472845

28482846
auto conformance =
2849-
TypeChecker::conformsToProtocol(type, proto, dc->getParentModule());
2847+
dc->getParentModule()->checkConformance(type, proto);
28502848
assert(conformance && "string interpolation type conforms to protocol");
28512849

28522850
DeclName constrName(ctx, DeclBaseName::createConstructor(), argLabels);
@@ -2987,8 +2985,7 @@ namespace {
29872985
auto proto = TypeChecker::getLiteralProtocol(ctx, expr);
29882986
assert(proto && "Missing object literal protocol?");
29892987
auto conformance =
2990-
TypeChecker::conformsToProtocol(conformingType, proto,
2991-
dc->getParentModule());
2988+
dc->getParentModule()->checkConformance(conformingType, proto);
29922989
assert(conformance && "object literal type conforms to protocol");
29932990

29942991
auto constrName = TypeChecker::getObjectLiteralConstructorName(ctx, expr);
@@ -3686,8 +3683,7 @@ namespace {
36863683
assert(arrayProto && "type-checked array literal w/o protocol?!");
36873684

36883685
auto conformance =
3689-
TypeChecker::conformsToProtocol(arrayTy, arrayProto,
3690-
dc->getParentModule());
3686+
dc->getParentModule()->checkConformance(arrayTy, arrayProto);
36913687
assert(conformance && "Type does not conform to protocol?");
36923688

36933689
DeclName name(ctx, DeclBaseName::createConstructor(),
@@ -3733,8 +3729,7 @@ namespace {
37333729
KnownProtocolKind::ExpressibleByDictionaryLiteral);
37343730

37353731
auto conformance =
3736-
TypeChecker::conformsToProtocol(dictionaryTy, dictionaryProto,
3737-
dc->getParentModule());
3732+
dc->getParentModule()->checkConformance(dictionaryTy, dictionaryProto);
37383733
if (conformance.isInvalid())
37393734
return nullptr;
37403735

@@ -5345,8 +5340,7 @@ namespace {
53455340
// verified by the solver, we just need to get it again
53465341
// with all of the generic parameters resolved.
53475342
auto hashableConformance =
5348-
TypeChecker::conformsToProtocol(indexType, hashable,
5349-
dc->getParentModule());
5343+
dc->getParentModule()->checkConformance(indexType, hashable);
53505344
assert(hashableConformance);
53515345

53525346
conformances.push_back(hashableConformance);
@@ -6905,8 +6899,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
69056899
// Find the conformance of the source type to Hashable.
69066900
auto hashable = ctx.getProtocol(KnownProtocolKind::Hashable);
69076901
auto conformance =
6908-
TypeChecker::conformsToProtocol(
6909-
cs.getType(expr), hashable, dc->getParentModule());
6902+
dc->getParentModule()->checkConformance(
6903+
cs.getType(expr), hashable);
69106904
assert(conformance && "must conform to Hashable");
69116905

69126906
return cs.cacheType(
@@ -7692,8 +7686,8 @@ Expr *ExprRewriter::convertLiteralInPlace(
76927686
// Check whether this literal type conforms to the builtin protocol. If so,
76937687
// initialize via the builtin protocol.
76947688
if (builtinProtocol) {
7695-
auto builtinConformance = TypeChecker::conformsToProtocol(
7696-
type, builtinProtocol, dc->getParentModule());
7689+
auto builtinConformance = dc->getParentModule()->checkConformance(
7690+
type, builtinProtocol);
76977691
if (builtinConformance) {
76987692
// Find the witness that we'll use to initialize the type via a builtin
76997693
// literal.
@@ -7716,8 +7710,7 @@ Expr *ExprRewriter::convertLiteralInPlace(
77167710

77177711
// This literal type must conform to the (non-builtin) protocol.
77187712
assert(protocol && "requirements should have stopped recursion");
7719-
auto conformance = TypeChecker::conformsToProtocol(type, protocol,
7720-
dc->getParentModule());
7713+
auto conformance = dc->getParentModule()->checkConformance(type, protocol);
77217714
assert(conformance && "must conform to literal protocol");
77227715

77237716
// Dig out the literal type and perform a builtin literal conversion to it.
@@ -7841,8 +7834,7 @@ std::pair<Expr *, ArgumentList *> ExprRewriter::buildDynamicCallable(
78417834
auto dictLitProto =
78427835
ctx.getProtocol(KnownProtocolKind::ExpressibleByDictionaryLiteral);
78437836
auto conformance =
7844-
TypeChecker::conformsToProtocol(argumentType, dictLitProto,
7845-
dc->getParentModule());
7837+
dc->getParentModule()->checkConformance(argumentType, dictLitProto);
78467838
auto keyType = conformance.getTypeWitnessByName(argumentType, ctx.Id_Key);
78477839
auto valueType =
78487840
conformance.getTypeWitnessByName(argumentType, ctx.Id_Value);
@@ -9192,8 +9184,8 @@ static llvm::Optional<SequenceIterationInfo> applySolutionToForEachStmt(
91929184
parsedSequence, LocatorPathElt::ContextualType(CTP_ForEachSequence));
91939185
type = Type(solution.OpenedExistentialTypes[contextualLoc]);
91949186
}
9195-
auto sequenceConformance = TypeChecker::conformsToProtocol(
9196-
type, sequenceProto, dc->getParentModule());
9187+
auto sequenceConformance = dc->getParentModule()->checkConformance(
9188+
type, sequenceProto);
91979189
assert(!sequenceConformance.isInvalid() &&
91989190
"Couldn't find sequence conformance");
91999191
stmt->setSequenceConformance(sequenceConformance);

0 commit comments

Comments
 (0)