Skip to content

Commit c359f7c

Browse files
committed
Sema: Pull ensureRequirementsAreSatisfied() out of ConformanceChecker
1 parent 0de682b commit c359f7c

File tree

2 files changed

+62
-65
lines changed

2 files changed

+62
-65
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 62 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,13 +1640,16 @@ ConformanceAccessScope ConformanceAccessScopeRequest::evaluate(
16401640
return std::make_pair(result, witnessesMustBeUsableFromInline);
16411641
}
16421642

1643-
bool WitnessChecker::checkWitnessAccess(ValueDecl *requirement,
1644-
ValueDecl *witness,
1645-
bool *isSetter) {
1643+
static bool checkWitnessAccess(DeclContext *dc,
1644+
ValueDecl *requirement,
1645+
ValueDecl *witness,
1646+
bool *isSetter) {
16461647
*isSetter = false;
16471648

1649+
auto *proto = cast<ProtocolDecl>(requirement->getDeclContext());
1650+
16481651
auto requiredAccessScope = evaluateOrDefault(
1649-
Context.evaluator, ConformanceAccessScopeRequest{DC, Proto},
1652+
dc->getASTContext().evaluator, ConformanceAccessScopeRequest{dc, proto},
16501653
std::make_pair(AccessScope::getPublic(), false));
16511654

16521655
auto actualScopeToCheck = requiredAccessScope.first;
@@ -1662,7 +1665,7 @@ bool WitnessChecker::checkWitnessAccess(ValueDecl *requirement,
16621665
// allow us to see it anywhere, because any other client could also add
16631666
// their own `@testable import`.
16641667
// Same with @_private(sourceFile:) import.
1665-
if (auto parentFile = dyn_cast<SourceFile>(DC->getModuleScopeContext())) {
1668+
if (auto parentFile = dc->getParentSourceFile()) {
16661669
const ModuleDecl *witnessModule = witness->getModuleContext();
16671670
if (parentFile->getParentModule() != witnessModule &&
16681671
parentFile->hasTestableOrPrivateImport(witness->getFormalAccess(),
@@ -1677,7 +1680,7 @@ bool WitnessChecker::checkWitnessAccess(ValueDecl *requirement,
16771680
}
16781681

16791682
if (auto *requirementASD = dyn_cast<AbstractStorageDecl>(requirement)) {
1680-
if (requirementASD->isSettable(DC)) {
1683+
if (requirementASD->isSettable(dc)) {
16811684
*isSetter = true;
16821685

16831686
auto witnessASD = cast<AbstractStorageDecl>(witness);
@@ -1711,7 +1714,7 @@ RequirementCheck WitnessChecker::checkWitness(ValueDecl *requirement,
17111714
std::make_pair(AccessScope::getPublic(), false));
17121715

17131716
bool isSetter = false;
1714-
if (checkWitnessAccess(requirement, match.Witness, &isSetter)) {
1717+
if (checkWitnessAccess(DC, requirement, match.Witness, &isSetter)) {
17151718
CheckKind kind = (isSetter
17161719
? CheckKind::AccessOfSetter
17171720
: CheckKind::Access);
@@ -3296,18 +3299,21 @@ ConformanceChecker::checkActorIsolation(ValueDecl *requirement,
32963299
return llvm::None;
32973300
}
32983301

3299-
bool ConformanceChecker::checkObjCTypeErasedGenerics(
3300-
AssociatedTypeDecl *assocType,
3301-
Type type,
3302-
TypeDecl *typeDecl) {
3302+
/// Check for ill-formed uses of Objective-C generics in a type witness.
3303+
static bool checkObjCTypeErasedGenerics(NormalProtocolConformance *conformance,
3304+
AssociatedTypeDecl *assocType,
3305+
Type type, TypeDecl *typeDecl) {
3306+
auto *dc = conformance->getDeclContext();
3307+
auto *proto = conformance->getProtocol();
3308+
33033309
// Objective-C's type-erased generics don't allow the type arguments
33043310
// to be extracted from an instance (or a metatype), so we cannot refer to
33053311
// the type parameters from an associated type. Check that here.
3306-
auto &ctx = assocType->getASTContext();
3312+
auto &ctx = dc->getASTContext();
33073313
if (!ctx.LangOpts.EnableObjCInterop && type->hasError())
33083314
return false;
33093315

3310-
auto classDecl = DC->getSelfClassDecl();
3316+
auto classDecl = dc->getSelfClassDecl();
33113317
if (!classDecl) return false;
33123318

33133319
if (!classDecl->isTypeErasedGenericClass()) return false;
@@ -3328,10 +3334,10 @@ bool ConformanceChecker::checkObjCTypeErasedGenerics(
33283334
});
33293335

33303336
// Diagnose the problem.
3331-
SourceLoc diagLoc = getLocForDiagnosingWitness(Conformance, typeDecl);
3337+
SourceLoc diagLoc = getLocForDiagnosingWitness(conformance, typeDecl);
33323338
ctx.Diags.diagnose(diagLoc, diag::type_witness_objc_generic_parameter,
33333339
type, genericParam, !genericParam.isNull(), assocType,
3334-
Proto);
3340+
proto);
33353341
emitDeclaredHereIfNeeded(ctx.Diags, diagLoc, typeDecl);
33363342

33373343
return true;
@@ -4660,14 +4666,19 @@ static void diagnoseInvariantSelfRequirement(
46604666
.warnUntilSwiftVersion(6);
46614667
}
46624668

4663-
void ConformanceChecker::ensureRequirementsAreSatisfied() {
4664-
auto proto = Conformance->getProtocol();
4665-
auto &diags = proto->getASTContext().Diags;
4669+
/// Check whether the type witnesses satisfy the protocol's requirement
4670+
/// signature. Also checks access level of type witnesses and availiability
4671+
/// of associated conformances.
4672+
static void ensureRequirementsAreSatisfied(ASTContext &ctx,
4673+
NormalProtocolConformance *conformance) {
4674+
auto *dc = conformance->getDeclContext();
4675+
auto proto = conformance->getProtocol();
4676+
auto &diags = ctx.Diags;
46664677

4667-
auto *const module = DC->getParentModule();
4668-
auto substitutingType = DC->mapTypeIntoContext(Conformance->getType());
4678+
auto *const module = dc->getParentModule();
4679+
auto substitutingType = dc->mapTypeIntoContext(conformance->getType());
46694680
auto substitutions = SubstitutionMap::getProtocolSubstitutions(
4670-
proto, substitutingType, ProtocolConformanceRef(Conformance));
4681+
proto, substitutingType, ProtocolConformanceRef(conformance));
46714682

46724683
auto reqSig = proto->getRequirementSignature().getRequirements();
46734684

@@ -4677,10 +4688,12 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
46774688
// an error, we can handle it as part of the above checkGenericArguments()
46784689
// call by passing in a superclass-bound archetype for the 'self' type
46794690
// instead of the concrete class type itself.
4680-
if (auto *classDecl = DC->getSelfClassDecl()) {
4691+
if (auto *classDecl = dc->getSelfClassDecl()) {
46814692
if (!classDecl->isSemanticallyFinal()) {
46824693
if (auto req = hasInvariantSelfRequirement(proto, reqSig)) {
4683-
diagnoseInvariantSelfRequirement(Loc, Adoptee, proto, *req, diags);
4694+
diagnoseInvariantSelfRequirement(conformance->getLoc(),
4695+
dc->getSelfInterfaceType(),
4696+
proto, *req, diags);
46844697
}
46854698
}
46864699
}
@@ -4696,60 +4709,57 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
46964709
case CheckRequirementsResult::SubstitutionFailure:
46974710
// Diagnose the failure generically.
46984711
// FIXME: Would be nice to give some more context here!
4699-
if (!Conformance->isInvalid()) {
4712+
if (!conformance->isInvalid()) {
47004713
if (result.getKind() == CheckRequirementsResult::RequirementFailure) {
4701-
auto Loc = this->Loc;
4702-
getASTContext().addDelayedConformanceDiag(Conformance, /*isError=*/true,
4703-
[Loc, result, proto, substitutions, module](NormalProtocolConformance *conformance) {
4714+
ctx.addDelayedConformanceDiag(conformance, /*isError=*/true,
4715+
[result, proto, substitutions, module](NormalProtocolConformance *conformance) {
47044716
TypeChecker::diagnoseRequirementFailure(
4705-
result.getRequirementFailureInfo(), Loc, Loc,
4717+
result.getRequirementFailureInfo(),
4718+
conformance->getLoc(), conformance->getLoc(),
47064719
proto->getDeclaredInterfaceType(),
47074720
{proto->getSelfInterfaceType()->castTo<GenericTypeParamType>()},
47084721
QuerySubstitutionMap{substitutions}, module);
47094722
});
47104723
}
47114724

4712-
Conformance->setInvalid();
4725+
conformance->setInvalid();
47134726
}
47144727
return;
47154728
}
47164729

47174730
// Now check that our associated conformances are at least as visible as
47184731
// the conformance itself.
4719-
auto where = ExportContext::forConformance(DC, proto);
4732+
auto where = ExportContext::forConformance(dc, proto);
47204733
if (where.isImplicit())
47214734
return;
47224735

4723-
Conformance->forEachTypeWitness([&](AssociatedTypeDecl *assocType,
4736+
conformance->forEachTypeWitness([&](AssociatedTypeDecl *assocType,
47244737
Type type, TypeDecl *typeDecl) -> bool {
4725-
checkObjCTypeErasedGenerics(assocType, type, typeDecl);
4738+
checkObjCTypeErasedGenerics(conformance, assocType, type, typeDecl);
47264739

47274740
if (typeDecl && !typeDecl->isImplicit()) {
47284741
auto requiredAccessScope = evaluateOrDefault(
4729-
Context.evaluator, ConformanceAccessScopeRequest{DC, Proto},
4742+
ctx.evaluator, ConformanceAccessScopeRequest{dc, proto},
47304743
std::make_pair(AccessScope::getPublic(), false));
47314744

47324745
// Check access.
47334746
bool isSetter = false;
4734-
if (checkWitnessAccess(assocType, typeDecl, &isSetter)) {
4747+
if (checkWitnessAccess(dc, assocType, typeDecl, &isSetter)) {
47354748
assert(!isSetter);
47364749

4737-
// Note: you must not capture 'this' in the below closure.
4738-
auto *DC = this->DC;
4739-
4740-
getASTContext().addDelayedConformanceDiag(Conformance, false,
4741-
[DC, requiredAccessScope, typeDecl](
4750+
ctx.addDelayedConformanceDiag(conformance, false,
4751+
[dc, requiredAccessScope, typeDecl](
47424752
NormalProtocolConformance *conformance) {
47434753
AccessLevel requiredAccess =
47444754
requiredAccessScope.first.requiredAccessForDiagnostics();
47454755
auto proto = conformance->getProtocol();
4746-
auto protoAccessScope = proto->getFormalAccessScope(DC);
4756+
auto protoAccessScope = proto->getFormalAccessScope(dc);
47474757
bool protoForcesAccess =
47484758
requiredAccessScope.first.hasEqualDeclContextWith(protoAccessScope);
47494759
auto diagKind = protoForcesAccess
47504760
? diag::type_witness_not_accessible_proto
47514761
: diag::type_witness_not_accessible_type;
4752-
auto &diags = DC->getASTContext().Diags;
4762+
auto &diags = dc->getASTContext().Diags;
47534763
diags.diagnose(getLocForDiagnosingWitness(conformance, typeDecl),
47544764
diagKind, typeDecl, requiredAccess, proto);
47554765
diagnoseWitnessFixAccessLevel(diags, typeDecl, requiredAccess);
@@ -4758,10 +4768,10 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
47584768

47594769
if (requiredAccessScope.second) {
47604770
bool witnessIsUsableFromInline = typeDecl->getFormalAccessScope(
4761-
DC, /*usableFromInlineAsPublic*/true).isPublic();
4771+
dc, /*usableFromInlineAsPublic*/true).isPublic();
47624772
if (!witnessIsUsableFromInline)
4763-
getASTContext().addDelayedConformanceDiag(Conformance, false,
4764-
DiagnoseUsableFromInline(typeDecl));
4773+
ctx.addDelayedConformanceDiag(conformance, false,
4774+
DiagnoseUsableFromInline(typeDecl));
47654775
}
47664776
}
47674777

@@ -4774,14 +4784,14 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
47744784
return false;
47754785
});
47764786

4777-
Conformance->forEachAssociatedConformance(
4787+
conformance->forEachAssociatedConformance(
47784788
[&](Type depTy, ProtocolDecl *proto, unsigned index) {
4779-
auto conformance = Conformance->getAssociatedConformance(depTy, proto);
4780-
if (conformance.isConcrete()) {
4781-
auto *concrete = conformance.getConcrete();
4782-
auto replacementTy = DC->mapTypeIntoContext(concrete->getType());
4783-
diagnoseConformanceAvailability(Conformance->getLoc(),
4784-
conformance, where,
4789+
auto assocConf = conformance->getAssociatedConformance(depTy, proto);
4790+
if (assocConf.isConcrete()) {
4791+
auto *concrete = assocConf.getConcrete();
4792+
auto replacementTy = dc->mapTypeIntoContext(concrete->getType());
4793+
diagnoseConformanceAvailability(conformance->getLoc(),
4794+
assocConf, where,
47854795
depTy, replacementTy);
47864796
}
47874797

@@ -5050,7 +5060,7 @@ void ConformanceChecker::checkConformance() {
50505060
evaluator::SideEffect());
50515061

50525062
// Check the requirements from the requirement signature.
5053-
ensureRequirementsAreSatisfied();
5063+
ensureRequirementsAreSatisfied(getASTContext(), Conformance);
50545064

50555065
// Check non-type requirements.
50565066
resolveValueWitnesses();

lib/Sema/TypeCheckProtocol.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,6 @@ class WitnessChecker {
9494
unsigned &bestIdx,
9595
bool &doNotDiagnoseMatches);
9696

97-
bool checkWitnessAccess(ValueDecl *requirement,
98-
ValueDecl *witness,
99-
bool *isSetter);
100-
10197
bool checkWitnessAvailability(ValueDecl *requirement,
10298
ValueDecl *witness,
10399
AvailabilityContext *requirementInfo);
@@ -135,11 +131,6 @@ class ConformanceChecker : public WitnessChecker {
135131
/// Record that the given requirement has no valid witness.
136132
void recordInvalidWitness(ValueDecl *requirement);
137133

138-
/// Check for ill-formed uses of Objective-C generics in a type witness.
139-
bool checkObjCTypeErasedGenerics(AssociatedTypeDecl *assocType,
140-
Type type,
141-
TypeDecl *typeDecl);
142-
143134
/// Check that the witness and requirement have compatible actor contexts.
144135
///
145136
/// \returns the isolation that needs to be enforced to invoke the witness
@@ -167,10 +158,6 @@ class ConformanceChecker : public WitnessChecker {
167158
ResolveWitnessResult
168159
resolveWitnessTryingAllStrategies(ValueDecl *requirement);
169160

170-
/// Check whether all of the protocol's generic requirements are satisfied by
171-
/// the chosen type witnesses.
172-
void ensureRequirementsAreSatisfied();
173-
174161
ConformanceChecker(ASTContext &ctx, NormalProtocolConformance *conformance);
175162

176163
~ConformanceChecker();

0 commit comments

Comments
 (0)