Skip to content

Commit 5645539

Browse files
committed
Sema: Pull ensureRequirementsAreSatisfied() out of ConformanceChecker
1 parent 4b073b8 commit 5645539

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);
@@ -3303,18 +3306,21 @@ ConformanceChecker::checkActorIsolation(ValueDecl *requirement,
33033306
return llvm::None;
33043307
}
33053308

3306-
bool ConformanceChecker::checkObjCTypeErasedGenerics(
3307-
AssociatedTypeDecl *assocType,
3308-
Type type,
3309-
TypeDecl *typeDecl) {
3309+
/// Check for ill-formed uses of Objective-C generics in a type witness.
3310+
static bool checkObjCTypeErasedGenerics(NormalProtocolConformance *conformance,
3311+
AssociatedTypeDecl *assocType,
3312+
Type type, TypeDecl *typeDecl) {
3313+
auto *dc = conformance->getDeclContext();
3314+
auto *proto = conformance->getProtocol();
3315+
33103316
// Objective-C's type-erased generics don't allow the type arguments
33113317
// to be extracted from an instance (or a metatype), so we cannot refer to
33123318
// the type parameters from an associated type. Check that here.
3313-
auto &ctx = assocType->getASTContext();
3319+
auto &ctx = dc->getASTContext();
33143320
if (!ctx.LangOpts.EnableObjCInterop && type->hasError())
33153321
return false;
33163322

3317-
auto classDecl = DC->getSelfClassDecl();
3323+
auto classDecl = dc->getSelfClassDecl();
33183324
if (!classDecl) return false;
33193325

33203326
if (!classDecl->isTypeErasedGenericClass()) return false;
@@ -3335,10 +3341,10 @@ bool ConformanceChecker::checkObjCTypeErasedGenerics(
33353341
});
33363342

33373343
// Diagnose the problem.
3338-
SourceLoc diagLoc = getLocForDiagnosingWitness(Conformance, typeDecl);
3344+
SourceLoc diagLoc = getLocForDiagnosingWitness(conformance, typeDecl);
33393345
ctx.Diags.diagnose(diagLoc, diag::type_witness_objc_generic_parameter,
33403346
type, genericParam, !genericParam.isNull(), assocType,
3341-
Proto);
3347+
proto);
33423348
emitDeclaredHereIfNeeded(ctx.Diags, diagLoc, typeDecl);
33433349

33443350
return true;
@@ -4667,14 +4673,19 @@ static void diagnoseInvariantSelfRequirement(
46674673
.warnUntilSwiftVersion(6);
46684674
}
46694675

4670-
void ConformanceChecker::ensureRequirementsAreSatisfied() {
4671-
auto proto = Conformance->getProtocol();
4672-
auto &diags = proto->getASTContext().Diags;
4676+
/// Check whether the type witnesses satisfy the protocol's requirement
4677+
/// signature. Also checks access level of type witnesses and availiability
4678+
/// of associated conformances.
4679+
static void ensureRequirementsAreSatisfied(ASTContext &ctx,
4680+
NormalProtocolConformance *conformance) {
4681+
auto *dc = conformance->getDeclContext();
4682+
auto proto = conformance->getProtocol();
4683+
auto &diags = ctx.Diags;
46734684

4674-
auto *const module = DC->getParentModule();
4675-
auto substitutingType = DC->mapTypeIntoContext(Conformance->getType());
4685+
auto *const module = dc->getParentModule();
4686+
auto substitutingType = dc->mapTypeIntoContext(conformance->getType());
46764687
auto substitutions = SubstitutionMap::getProtocolSubstitutions(
4677-
proto, substitutingType, ProtocolConformanceRef(Conformance));
4688+
proto, substitutingType, ProtocolConformanceRef(conformance));
46784689

46794690
auto reqSig = proto->getRequirementSignature().getRequirements();
46804691

@@ -4684,10 +4695,12 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
46844695
// an error, we can handle it as part of the above checkGenericArguments()
46854696
// call by passing in a superclass-bound archetype for the 'self' type
46864697
// instead of the concrete class type itself.
4687-
if (auto *classDecl = DC->getSelfClassDecl()) {
4698+
if (auto *classDecl = dc->getSelfClassDecl()) {
46884699
if (!classDecl->isSemanticallyFinal()) {
46894700
if (auto req = hasInvariantSelfRequirement(proto, reqSig)) {
4690-
diagnoseInvariantSelfRequirement(Loc, Adoptee, proto, *req, diags);
4701+
diagnoseInvariantSelfRequirement(conformance->getLoc(),
4702+
dc->getSelfInterfaceType(),
4703+
proto, *req, diags);
46914704
}
46924705
}
46934706
}
@@ -4703,60 +4716,57 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
47034716
case CheckRequirementsResult::SubstitutionFailure:
47044717
// Diagnose the failure generically.
47054718
// FIXME: Would be nice to give some more context here!
4706-
if (!Conformance->isInvalid()) {
4719+
if (!conformance->isInvalid()) {
47074720
if (result.getKind() == CheckRequirementsResult::RequirementFailure) {
4708-
auto Loc = this->Loc;
4709-
getASTContext().addDelayedConformanceDiag(Conformance, /*isError=*/true,
4710-
[Loc, result, proto, substitutions, module](NormalProtocolConformance *conformance) {
4721+
ctx.addDelayedConformanceDiag(conformance, /*isError=*/true,
4722+
[result, proto, substitutions, module](NormalProtocolConformance *conformance) {
47114723
TypeChecker::diagnoseRequirementFailure(
4712-
result.getRequirementFailureInfo(), Loc, Loc,
4724+
result.getRequirementFailureInfo(),
4725+
conformance->getLoc(), conformance->getLoc(),
47134726
proto->getDeclaredInterfaceType(),
47144727
{proto->getSelfInterfaceType()->castTo<GenericTypeParamType>()},
47154728
QuerySubstitutionMap{substitutions}, module);
47164729
});
47174730
}
47184731

4719-
Conformance->setInvalid();
4732+
conformance->setInvalid();
47204733
}
47214734
return;
47224735
}
47234736

47244737
// Now check that our associated conformances are at least as visible as
47254738
// the conformance itself.
4726-
auto where = ExportContext::forConformance(DC, proto);
4739+
auto where = ExportContext::forConformance(dc, proto);
47274740
if (where.isImplicit())
47284741
return;
47294742

4730-
Conformance->forEachTypeWitness([&](AssociatedTypeDecl *assocType,
4743+
conformance->forEachTypeWitness([&](AssociatedTypeDecl *assocType,
47314744
Type type, TypeDecl *typeDecl) -> bool {
4732-
checkObjCTypeErasedGenerics(assocType, type, typeDecl);
4745+
checkObjCTypeErasedGenerics(conformance, assocType, type, typeDecl);
47334746

47344747
if (typeDecl && !typeDecl->isImplicit()) {
47354748
auto requiredAccessScope = evaluateOrDefault(
4736-
Context.evaluator, ConformanceAccessScopeRequest{DC, Proto},
4749+
ctx.evaluator, ConformanceAccessScopeRequest{dc, proto},
47374750
std::make_pair(AccessScope::getPublic(), false));
47384751

47394752
// Check access.
47404753
bool isSetter = false;
4741-
if (checkWitnessAccess(assocType, typeDecl, &isSetter)) {
4754+
if (checkWitnessAccess(dc, assocType, typeDecl, &isSetter)) {
47424755
assert(!isSetter);
47434756

4744-
// Note: you must not capture 'this' in the below closure.
4745-
auto *DC = this->DC;
4746-
4747-
getASTContext().addDelayedConformanceDiag(Conformance, false,
4748-
[DC, requiredAccessScope, typeDecl](
4757+
ctx.addDelayedConformanceDiag(conformance, false,
4758+
[dc, requiredAccessScope, typeDecl](
47494759
NormalProtocolConformance *conformance) {
47504760
AccessLevel requiredAccess =
47514761
requiredAccessScope.first.requiredAccessForDiagnostics();
47524762
auto proto = conformance->getProtocol();
4753-
auto protoAccessScope = proto->getFormalAccessScope(DC);
4763+
auto protoAccessScope = proto->getFormalAccessScope(dc);
47544764
bool protoForcesAccess =
47554765
requiredAccessScope.first.hasEqualDeclContextWith(protoAccessScope);
47564766
auto diagKind = protoForcesAccess
47574767
? diag::type_witness_not_accessible_proto
47584768
: diag::type_witness_not_accessible_type;
4759-
auto &diags = DC->getASTContext().Diags;
4769+
auto &diags = dc->getASTContext().Diags;
47604770
diags.diagnose(getLocForDiagnosingWitness(conformance, typeDecl),
47614771
diagKind, typeDecl, requiredAccess, proto);
47624772
diagnoseWitnessFixAccessLevel(diags, typeDecl, requiredAccess);
@@ -4765,10 +4775,10 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
47654775

47664776
if (requiredAccessScope.second) {
47674777
bool witnessIsUsableFromInline = typeDecl->getFormalAccessScope(
4768-
DC, /*usableFromInlineAsPublic*/true).isPublic();
4778+
dc, /*usableFromInlineAsPublic*/true).isPublic();
47694779
if (!witnessIsUsableFromInline)
4770-
getASTContext().addDelayedConformanceDiag(Conformance, false,
4771-
DiagnoseUsableFromInline(typeDecl));
4780+
ctx.addDelayedConformanceDiag(conformance, false,
4781+
DiagnoseUsableFromInline(typeDecl));
47724782
}
47734783
}
47744784

@@ -4781,14 +4791,14 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
47814791
return false;
47824792
});
47834793

4784-
Conformance->forEachAssociatedConformance(
4794+
conformance->forEachAssociatedConformance(
47854795
[&](Type depTy, ProtocolDecl *proto, unsigned index) {
4786-
auto conformance = Conformance->getAssociatedConformance(depTy, proto);
4787-
if (conformance.isConcrete()) {
4788-
auto *concrete = conformance.getConcrete();
4789-
auto replacementTy = DC->mapTypeIntoContext(concrete->getType());
4790-
diagnoseConformanceAvailability(Conformance->getLoc(),
4791-
conformance, where,
4796+
auto assocConf = conformance->getAssociatedConformance(depTy, proto);
4797+
if (assocConf.isConcrete()) {
4798+
auto *concrete = assocConf.getConcrete();
4799+
auto replacementTy = dc->mapTypeIntoContext(concrete->getType());
4800+
diagnoseConformanceAvailability(conformance->getLoc(),
4801+
assocConf, where,
47924802
depTy, replacementTy);
47934803
}
47944804

@@ -5057,7 +5067,7 @@ void ConformanceChecker::checkConformance() {
50575067
evaluator::SideEffect());
50585068

50595069
// Check the requirements from the requirement signature.
5060-
ensureRequirementsAreSatisfied();
5070+
ensureRequirementsAreSatisfied(getASTContext(), Conformance);
50615071

50625072
// Check non-type requirements.
50635073
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)