@@ -1640,13 +1640,16 @@ ConformanceAccessScope ConformanceAccessScopeRequest::evaluate(
1640
1640
return std::make_pair (result, witnessesMustBeUsableFromInline);
1641
1641
}
1642
1642
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) {
1646
1647
*isSetter = false ;
1647
1648
1649
+ auto *proto = cast<ProtocolDecl>(requirement->getDeclContext ());
1650
+
1648
1651
auto requiredAccessScope = evaluateOrDefault (
1649
- Context .evaluator , ConformanceAccessScopeRequest{DC, Proto },
1652
+ dc-> getASTContext () .evaluator , ConformanceAccessScopeRequest{dc, proto },
1650
1653
std::make_pair (AccessScope::getPublic (), false ));
1651
1654
1652
1655
auto actualScopeToCheck = requiredAccessScope.first ;
@@ -1662,7 +1665,7 @@ bool WitnessChecker::checkWitnessAccess(ValueDecl *requirement,
1662
1665
// allow us to see it anywhere, because any other client could also add
1663
1666
// their own `@testable import`.
1664
1667
// Same with @_private(sourceFile:) import.
1665
- if (auto parentFile = dyn_cast<SourceFile>(DC-> getModuleScopeContext () )) {
1668
+ if (auto parentFile = dc-> getParentSourceFile ( )) {
1666
1669
const ModuleDecl *witnessModule = witness->getModuleContext ();
1667
1670
if (parentFile->getParentModule () != witnessModule &&
1668
1671
parentFile->hasTestableOrPrivateImport (witness->getFormalAccess (),
@@ -1677,7 +1680,7 @@ bool WitnessChecker::checkWitnessAccess(ValueDecl *requirement,
1677
1680
}
1678
1681
1679
1682
if (auto *requirementASD = dyn_cast<AbstractStorageDecl>(requirement)) {
1680
- if (requirementASD->isSettable (DC )) {
1683
+ if (requirementASD->isSettable (dc )) {
1681
1684
*isSetter = true ;
1682
1685
1683
1686
auto witnessASD = cast<AbstractStorageDecl>(witness);
@@ -1711,7 +1714,7 @@ RequirementCheck WitnessChecker::checkWitness(ValueDecl *requirement,
1711
1714
std::make_pair (AccessScope::getPublic (), false ));
1712
1715
1713
1716
bool isSetter = false ;
1714
- if (checkWitnessAccess (requirement, match.Witness , &isSetter)) {
1717
+ if (checkWitnessAccess (DC, requirement, match.Witness , &isSetter)) {
1715
1718
CheckKind kind = (isSetter
1716
1719
? CheckKind::AccessOfSetter
1717
1720
: CheckKind::Access);
@@ -3296,18 +3299,21 @@ ConformanceChecker::checkActorIsolation(ValueDecl *requirement,
3296
3299
return llvm::None;
3297
3300
}
3298
3301
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
+
3303
3309
// Objective-C's type-erased generics don't allow the type arguments
3304
3310
// to be extracted from an instance (or a metatype), so we cannot refer to
3305
3311
// the type parameters from an associated type. Check that here.
3306
- auto &ctx = assocType ->getASTContext ();
3312
+ auto &ctx = dc ->getASTContext ();
3307
3313
if (!ctx.LangOpts .EnableObjCInterop && type->hasError ())
3308
3314
return false ;
3309
3315
3310
- auto classDecl = DC ->getSelfClassDecl ();
3316
+ auto classDecl = dc ->getSelfClassDecl ();
3311
3317
if (!classDecl) return false ;
3312
3318
3313
3319
if (!classDecl->isTypeErasedGenericClass ()) return false ;
@@ -3328,10 +3334,10 @@ bool ConformanceChecker::checkObjCTypeErasedGenerics(
3328
3334
});
3329
3335
3330
3336
// Diagnose the problem.
3331
- SourceLoc diagLoc = getLocForDiagnosingWitness (Conformance , typeDecl);
3337
+ SourceLoc diagLoc = getLocForDiagnosingWitness (conformance , typeDecl);
3332
3338
ctx.Diags .diagnose (diagLoc, diag::type_witness_objc_generic_parameter,
3333
3339
type, genericParam, !genericParam.isNull (), assocType,
3334
- Proto );
3340
+ proto );
3335
3341
emitDeclaredHereIfNeeded (ctx.Diags , diagLoc, typeDecl);
3336
3342
3337
3343
return true ;
@@ -4660,14 +4666,19 @@ static void diagnoseInvariantSelfRequirement(
4660
4666
.warnUntilSwiftVersion (6 );
4661
4667
}
4662
4668
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 ;
4666
4677
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 ());
4669
4680
auto substitutions = SubstitutionMap::getProtocolSubstitutions (
4670
- proto, substitutingType, ProtocolConformanceRef (Conformance ));
4681
+ proto, substitutingType, ProtocolConformanceRef (conformance ));
4671
4682
4672
4683
auto reqSig = proto->getRequirementSignature ().getRequirements ();
4673
4684
@@ -4677,10 +4688,12 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4677
4688
// an error, we can handle it as part of the above checkGenericArguments()
4678
4689
// call by passing in a superclass-bound archetype for the 'self' type
4679
4690
// instead of the concrete class type itself.
4680
- if (auto *classDecl = DC ->getSelfClassDecl ()) {
4691
+ if (auto *classDecl = dc ->getSelfClassDecl ()) {
4681
4692
if (!classDecl->isSemanticallyFinal ()) {
4682
4693
if (auto req = hasInvariantSelfRequirement (proto, reqSig)) {
4683
- diagnoseInvariantSelfRequirement (Loc, Adoptee, proto, *req, diags);
4694
+ diagnoseInvariantSelfRequirement (conformance->getLoc (),
4695
+ dc->getSelfInterfaceType (),
4696
+ proto, *req, diags);
4684
4697
}
4685
4698
}
4686
4699
}
@@ -4696,60 +4709,57 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4696
4709
case CheckRequirementsResult::SubstitutionFailure:
4697
4710
// Diagnose the failure generically.
4698
4711
// FIXME: Would be nice to give some more context here!
4699
- if (!Conformance ->isInvalid ()) {
4712
+ if (!conformance ->isInvalid ()) {
4700
4713
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) {
4704
4716
TypeChecker::diagnoseRequirementFailure (
4705
- result.getRequirementFailureInfo (), Loc, Loc,
4717
+ result.getRequirementFailureInfo (),
4718
+ conformance->getLoc (), conformance->getLoc (),
4706
4719
proto->getDeclaredInterfaceType (),
4707
4720
{proto->getSelfInterfaceType ()->castTo <GenericTypeParamType>()},
4708
4721
QuerySubstitutionMap{substitutions}, module );
4709
4722
});
4710
4723
}
4711
4724
4712
- Conformance ->setInvalid ();
4725
+ conformance ->setInvalid ();
4713
4726
}
4714
4727
return ;
4715
4728
}
4716
4729
4717
4730
// Now check that our associated conformances are at least as visible as
4718
4731
// the conformance itself.
4719
- auto where = ExportContext::forConformance (DC , proto);
4732
+ auto where = ExportContext::forConformance (dc , proto);
4720
4733
if (where.isImplicit ())
4721
4734
return ;
4722
4735
4723
- Conformance ->forEachTypeWitness ([&](AssociatedTypeDecl *assocType,
4736
+ conformance ->forEachTypeWitness ([&](AssociatedTypeDecl *assocType,
4724
4737
Type type, TypeDecl *typeDecl) -> bool {
4725
- checkObjCTypeErasedGenerics (assocType, type, typeDecl);
4738
+ checkObjCTypeErasedGenerics (conformance, assocType, type, typeDecl);
4726
4739
4727
4740
if (typeDecl && !typeDecl->isImplicit ()) {
4728
4741
auto requiredAccessScope = evaluateOrDefault (
4729
- Context .evaluator , ConformanceAccessScopeRequest{DC, Proto },
4742
+ ctx .evaluator , ConformanceAccessScopeRequest{dc, proto },
4730
4743
std::make_pair (AccessScope::getPublic (), false ));
4731
4744
4732
4745
// Check access.
4733
4746
bool isSetter = false ;
4734
- if (checkWitnessAccess (assocType, typeDecl, &isSetter)) {
4747
+ if (checkWitnessAccess (dc, assocType, typeDecl, &isSetter)) {
4735
4748
assert (!isSetter);
4736
4749
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](
4742
4752
NormalProtocolConformance *conformance) {
4743
4753
AccessLevel requiredAccess =
4744
4754
requiredAccessScope.first .requiredAccessForDiagnostics ();
4745
4755
auto proto = conformance->getProtocol ();
4746
- auto protoAccessScope = proto->getFormalAccessScope (DC );
4756
+ auto protoAccessScope = proto->getFormalAccessScope (dc );
4747
4757
bool protoForcesAccess =
4748
4758
requiredAccessScope.first .hasEqualDeclContextWith (protoAccessScope);
4749
4759
auto diagKind = protoForcesAccess
4750
4760
? diag::type_witness_not_accessible_proto
4751
4761
: diag::type_witness_not_accessible_type;
4752
- auto &diags = DC ->getASTContext ().Diags ;
4762
+ auto &diags = dc ->getASTContext ().Diags ;
4753
4763
diags.diagnose (getLocForDiagnosingWitness (conformance, typeDecl),
4754
4764
diagKind, typeDecl, requiredAccess, proto);
4755
4765
diagnoseWitnessFixAccessLevel (diags, typeDecl, requiredAccess);
@@ -4758,10 +4768,10 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4758
4768
4759
4769
if (requiredAccessScope.second ) {
4760
4770
bool witnessIsUsableFromInline = typeDecl->getFormalAccessScope (
4761
- DC , /* usableFromInlineAsPublic*/ true ).isPublic ();
4771
+ dc , /* usableFromInlineAsPublic*/ true ).isPublic ();
4762
4772
if (!witnessIsUsableFromInline)
4763
- getASTContext () .addDelayedConformanceDiag (Conformance , false ,
4764
- DiagnoseUsableFromInline (typeDecl));
4773
+ ctx .addDelayedConformanceDiag (conformance , false ,
4774
+ DiagnoseUsableFromInline (typeDecl));
4765
4775
}
4766
4776
}
4767
4777
@@ -4774,14 +4784,14 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4774
4784
return false ;
4775
4785
});
4776
4786
4777
- Conformance ->forEachAssociatedConformance (
4787
+ conformance ->forEachAssociatedConformance (
4778
4788
[&](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,
4785
4795
depTy, replacementTy);
4786
4796
}
4787
4797
@@ -5050,7 +5060,7 @@ void ConformanceChecker::checkConformance() {
5050
5060
evaluator::SideEffect ());
5051
5061
5052
5062
// Check the requirements from the requirement signature.
5053
- ensureRequirementsAreSatisfied ();
5063
+ ensureRequirementsAreSatisfied (getASTContext (), Conformance );
5054
5064
5055
5065
// Check non-type requirements.
5056
5066
resolveValueWitnesses ();
0 commit comments