@@ -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);
@@ -3303,18 +3306,21 @@ ConformanceChecker::checkActorIsolation(ValueDecl *requirement,
3303
3306
return llvm::None;
3304
3307
}
3305
3308
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
+
3310
3316
// Objective-C's type-erased generics don't allow the type arguments
3311
3317
// to be extracted from an instance (or a metatype), so we cannot refer to
3312
3318
// the type parameters from an associated type. Check that here.
3313
- auto &ctx = assocType ->getASTContext ();
3319
+ auto &ctx = dc ->getASTContext ();
3314
3320
if (!ctx.LangOpts .EnableObjCInterop && type->hasError ())
3315
3321
return false ;
3316
3322
3317
- auto classDecl = DC ->getSelfClassDecl ();
3323
+ auto classDecl = dc ->getSelfClassDecl ();
3318
3324
if (!classDecl) return false ;
3319
3325
3320
3326
if (!classDecl->isTypeErasedGenericClass ()) return false ;
@@ -3335,10 +3341,10 @@ bool ConformanceChecker::checkObjCTypeErasedGenerics(
3335
3341
});
3336
3342
3337
3343
// Diagnose the problem.
3338
- SourceLoc diagLoc = getLocForDiagnosingWitness (Conformance , typeDecl);
3344
+ SourceLoc diagLoc = getLocForDiagnosingWitness (conformance , typeDecl);
3339
3345
ctx.Diags .diagnose (diagLoc, diag::type_witness_objc_generic_parameter,
3340
3346
type, genericParam, !genericParam.isNull (), assocType,
3341
- Proto );
3347
+ proto );
3342
3348
emitDeclaredHereIfNeeded (ctx.Diags , diagLoc, typeDecl);
3343
3349
3344
3350
return true ;
@@ -4667,14 +4673,19 @@ static void diagnoseInvariantSelfRequirement(
4667
4673
.warnUntilSwiftVersion (6 );
4668
4674
}
4669
4675
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 ;
4673
4684
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 ());
4676
4687
auto substitutions = SubstitutionMap::getProtocolSubstitutions (
4677
- proto, substitutingType, ProtocolConformanceRef (Conformance ));
4688
+ proto, substitutingType, ProtocolConformanceRef (conformance ));
4678
4689
4679
4690
auto reqSig = proto->getRequirementSignature ().getRequirements ();
4680
4691
@@ -4684,10 +4695,12 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4684
4695
// an error, we can handle it as part of the above checkGenericArguments()
4685
4696
// call by passing in a superclass-bound archetype for the 'self' type
4686
4697
// instead of the concrete class type itself.
4687
- if (auto *classDecl = DC ->getSelfClassDecl ()) {
4698
+ if (auto *classDecl = dc ->getSelfClassDecl ()) {
4688
4699
if (!classDecl->isSemanticallyFinal ()) {
4689
4700
if (auto req = hasInvariantSelfRequirement (proto, reqSig)) {
4690
- diagnoseInvariantSelfRequirement (Loc, Adoptee, proto, *req, diags);
4701
+ diagnoseInvariantSelfRequirement (conformance->getLoc (),
4702
+ dc->getSelfInterfaceType (),
4703
+ proto, *req, diags);
4691
4704
}
4692
4705
}
4693
4706
}
@@ -4703,60 +4716,57 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4703
4716
case CheckRequirementsResult::SubstitutionFailure:
4704
4717
// Diagnose the failure generically.
4705
4718
// FIXME: Would be nice to give some more context here!
4706
- if (!Conformance ->isInvalid ()) {
4719
+ if (!conformance ->isInvalid ()) {
4707
4720
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) {
4711
4723
TypeChecker::diagnoseRequirementFailure (
4712
- result.getRequirementFailureInfo (), Loc, Loc,
4724
+ result.getRequirementFailureInfo (),
4725
+ conformance->getLoc (), conformance->getLoc (),
4713
4726
proto->getDeclaredInterfaceType (),
4714
4727
{proto->getSelfInterfaceType ()->castTo <GenericTypeParamType>()},
4715
4728
QuerySubstitutionMap{substitutions}, module );
4716
4729
});
4717
4730
}
4718
4731
4719
- Conformance ->setInvalid ();
4732
+ conformance ->setInvalid ();
4720
4733
}
4721
4734
return ;
4722
4735
}
4723
4736
4724
4737
// Now check that our associated conformances are at least as visible as
4725
4738
// the conformance itself.
4726
- auto where = ExportContext::forConformance (DC , proto);
4739
+ auto where = ExportContext::forConformance (dc , proto);
4727
4740
if (where.isImplicit ())
4728
4741
return ;
4729
4742
4730
- Conformance ->forEachTypeWitness ([&](AssociatedTypeDecl *assocType,
4743
+ conformance ->forEachTypeWitness ([&](AssociatedTypeDecl *assocType,
4731
4744
Type type, TypeDecl *typeDecl) -> bool {
4732
- checkObjCTypeErasedGenerics (assocType, type, typeDecl);
4745
+ checkObjCTypeErasedGenerics (conformance, assocType, type, typeDecl);
4733
4746
4734
4747
if (typeDecl && !typeDecl->isImplicit ()) {
4735
4748
auto requiredAccessScope = evaluateOrDefault (
4736
- Context .evaluator , ConformanceAccessScopeRequest{DC, Proto },
4749
+ ctx .evaluator , ConformanceAccessScopeRequest{dc, proto },
4737
4750
std::make_pair (AccessScope::getPublic (), false ));
4738
4751
4739
4752
// Check access.
4740
4753
bool isSetter = false ;
4741
- if (checkWitnessAccess (assocType, typeDecl, &isSetter)) {
4754
+ if (checkWitnessAccess (dc, assocType, typeDecl, &isSetter)) {
4742
4755
assert (!isSetter);
4743
4756
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](
4749
4759
NormalProtocolConformance *conformance) {
4750
4760
AccessLevel requiredAccess =
4751
4761
requiredAccessScope.first .requiredAccessForDiagnostics ();
4752
4762
auto proto = conformance->getProtocol ();
4753
- auto protoAccessScope = proto->getFormalAccessScope (DC );
4763
+ auto protoAccessScope = proto->getFormalAccessScope (dc );
4754
4764
bool protoForcesAccess =
4755
4765
requiredAccessScope.first .hasEqualDeclContextWith (protoAccessScope);
4756
4766
auto diagKind = protoForcesAccess
4757
4767
? diag::type_witness_not_accessible_proto
4758
4768
: diag::type_witness_not_accessible_type;
4759
- auto &diags = DC ->getASTContext ().Diags ;
4769
+ auto &diags = dc ->getASTContext ().Diags ;
4760
4770
diags.diagnose (getLocForDiagnosingWitness (conformance, typeDecl),
4761
4771
diagKind, typeDecl, requiredAccess, proto);
4762
4772
diagnoseWitnessFixAccessLevel (diags, typeDecl, requiredAccess);
@@ -4765,10 +4775,10 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4765
4775
4766
4776
if (requiredAccessScope.second ) {
4767
4777
bool witnessIsUsableFromInline = typeDecl->getFormalAccessScope (
4768
- DC , /* usableFromInlineAsPublic*/ true ).isPublic ();
4778
+ dc , /* usableFromInlineAsPublic*/ true ).isPublic ();
4769
4779
if (!witnessIsUsableFromInline)
4770
- getASTContext () .addDelayedConformanceDiag (Conformance , false ,
4771
- DiagnoseUsableFromInline (typeDecl));
4780
+ ctx .addDelayedConformanceDiag (conformance , false ,
4781
+ DiagnoseUsableFromInline (typeDecl));
4772
4782
}
4773
4783
}
4774
4784
@@ -4781,14 +4791,14 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4781
4791
return false ;
4782
4792
});
4783
4793
4784
- Conformance ->forEachAssociatedConformance (
4794
+ conformance ->forEachAssociatedConformance (
4785
4795
[&](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,
4792
4802
depTy, replacementTy);
4793
4803
}
4794
4804
@@ -5057,7 +5067,7 @@ void ConformanceChecker::checkConformance() {
5057
5067
evaluator::SideEffect ());
5058
5068
5059
5069
// Check the requirements from the requirement signature.
5060
- ensureRequirementsAreSatisfied ();
5070
+ ensureRequirementsAreSatisfied (getASTContext (), Conformance );
5061
5071
5062
5072
// Check non-type requirements.
5063
5073
resolveValueWitnesses ();
0 commit comments