@@ -1605,48 +1605,51 @@ bool WitnessChecker::findBestWitness(
1605
1605
return isReallyBest;
1606
1606
}
1607
1607
1608
- AccessScope WitnessChecker::getRequiredAccessScope () {
1609
- if (RequiredAccessScopeAndUsableFromInline.has_value ())
1610
- return RequiredAccessScopeAndUsableFromInline.value ().first ;
1611
-
1612
- AccessScope result = Proto->getFormalAccessScope (DC);
1613
-
1608
+ ConformanceAccessScope ConformanceAccessScopeRequest::evaluate (
1609
+ Evaluator &evaluator, DeclContext *dc, ProtocolDecl *proto) const {
1610
+ AccessScope result = proto->getFormalAccessScope (dc);
1614
1611
bool witnessesMustBeUsableFromInline = false ;
1615
- if (Adoptee) {
1616
- const NominalTypeDecl *adoptingNominal = DC->getSelfNominalTypeDecl ();
1617
1612
1613
+ auto *nominal = dc->getSelfNominalTypeDecl ();
1614
+
1615
+ // We're either looking at a concrete conformance, or the default witness
1616
+ // table for a resilient protocol.
1617
+ if (!isa<ProtocolDecl>(nominal)) {
1618
1618
// Compute the intersection of the conforming type's access scope
1619
1619
// and the protocol's access scope.
1620
1620
auto scopeIntersection =
1621
- result.intersectWith (adoptingNominal ->getFormalAccessScope (DC ));
1621
+ result.intersectWith (nominal ->getFormalAccessScope (dc ));
1622
1622
assert (scopeIntersection.has_value ());
1623
1623
result = scopeIntersection.value ();
1624
1624
1625
1625
if (!result.isPublic ()) {
1626
1626
witnessesMustBeUsableFromInline =
1627
- Proto ->getFormalAccessScope (
1628
- DC , /* usableFromInlineAsPublic*/ true ).isPublic () &&
1629
- adoptingNominal ->getFormalAccessScope (
1630
- DC , /* usableFromInlineAsPublic*/ true ).isPublic ();
1627
+ proto ->getFormalAccessScope (
1628
+ dc , /* usableFromInlineAsPublic*/ true ).isPublic () &&
1629
+ nominal ->getFormalAccessScope (
1630
+ dc , /* usableFromInlineAsPublic*/ true ).isPublic ();
1631
1631
}
1632
1632
} else {
1633
1633
if (!result.isPublic ()) {
1634
1634
witnessesMustBeUsableFromInline =
1635
- Proto ->getFormalAccessScope (
1636
- DC , /* usableFromInlineAsPublic*/ true ).isPublic ();
1635
+ proto ->getFormalAccessScope (
1636
+ dc , /* usableFromInlineAsPublic*/ true ).isPublic ();
1637
1637
}
1638
1638
}
1639
1639
1640
- RequiredAccessScopeAndUsableFromInline =
1641
- std::make_pair (result, witnessesMustBeUsableFromInline);
1642
- return result;
1640
+ return std::make_pair (result, witnessesMustBeUsableFromInline);
1643
1641
}
1644
1642
1645
1643
bool WitnessChecker::checkWitnessAccess (ValueDecl *requirement,
1646
1644
ValueDecl *witness,
1647
1645
bool *isSetter) {
1648
1646
*isSetter = false ;
1649
- AccessScope actualScopeToCheck = getRequiredAccessScope ();
1647
+
1648
+ auto requiredAccessScope = evaluateOrDefault (
1649
+ Context.evaluator , ConformanceAccessScopeRequest{DC, Proto},
1650
+ std::make_pair (AccessScope::getPublic (), false ));
1651
+
1652
+ auto actualScopeToCheck = requiredAccessScope.first ;
1650
1653
1651
1654
// Setting the 'forConformance' flag means that we admit witnesses in
1652
1655
// protocol extensions that we can see, but are not necessarily as
@@ -1669,7 +1672,7 @@ bool WitnessChecker::checkWitnessAccess(ValueDecl *requirement,
1669
1672
}
1670
1673
}
1671
1674
1672
- if (actualScopeToCheck.hasEqualDeclContextWith (getRequiredAccessScope () ))
1675
+ if (actualScopeToCheck.hasEqualDeclContextWith (requiredAccessScope. first ))
1673
1676
return true ;
1674
1677
}
1675
1678
@@ -1703,15 +1706,20 @@ RequirementCheck WitnessChecker::checkWitness(ValueDecl *requirement,
1703
1706
if (!match.OptionalAdjustments .empty ())
1704
1707
return CheckKind::OptionalityConflict;
1705
1708
1709
+ auto requiredAccessScope = evaluateOrDefault (
1710
+ Context.evaluator , ConformanceAccessScopeRequest{DC, Proto},
1711
+ std::make_pair (AccessScope::getPublic (), false ));
1712
+
1706
1713
bool isSetter = false ;
1707
1714
if (checkWitnessAccess (requirement, match.Witness , &isSetter)) {
1708
1715
CheckKind kind = (isSetter
1709
1716
? CheckKind::AccessOfSetter
1710
1717
: CheckKind::Access);
1711
- return RequirementCheck (kind, getRequiredAccessScope ());
1718
+
1719
+ return RequirementCheck (kind, requiredAccessScope.first );
1712
1720
}
1713
1721
1714
- if (isUsableFromInlineRequired () ) {
1722
+ if (requiredAccessScope. second ) {
1715
1723
bool witnessIsUsableFromInline = match.Witness ->getFormalAccessScope (
1716
1724
DC, /* usableFromInlineAsPublic*/ true ).isPublic ();
1717
1725
if (!witnessIsUsableFromInline)
@@ -4655,24 +4663,27 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4655
4663
checkObjCTypeErasedGenerics (assocType, type, typeDecl);
4656
4664
4657
4665
if (typeDecl && !typeDecl->isImplicit ()) {
4666
+ auto requiredAccessScope = evaluateOrDefault (
4667
+ Context.evaluator , ConformanceAccessScopeRequest{DC, Proto},
4668
+ std::make_pair (AccessScope::getPublic (), false ));
4669
+
4658
4670
// Check access.
4659
4671
bool isSetter = false ;
4660
4672
if (checkWitnessAccess (assocType, typeDecl, &isSetter)) {
4661
4673
assert (!isSetter);
4662
4674
4663
4675
// Note: you must not capture 'this' in the below closure.
4664
- const DeclContext *DC = this ->DC ;
4665
- auto requiredAccessScope = getRequiredAccessScope ();
4676
+ auto *DC = this ->DC ;
4666
4677
4667
4678
getASTContext ().addDelayedConformanceDiag (Conformance, false ,
4668
4679
[DC, requiredAccessScope, typeDecl](
4669
4680
NormalProtocolConformance *conformance) {
4670
4681
AccessLevel requiredAccess =
4671
- requiredAccessScope.requiredAccessForDiagnostics ();
4682
+ requiredAccessScope.first . requiredAccessForDiagnostics ();
4672
4683
auto proto = conformance->getProtocol ();
4673
4684
auto protoAccessScope = proto->getFormalAccessScope (DC);
4674
4685
bool protoForcesAccess =
4675
- requiredAccessScope.hasEqualDeclContextWith (protoAccessScope);
4686
+ requiredAccessScope.first . hasEqualDeclContextWith (protoAccessScope);
4676
4687
auto diagKind = protoForcesAccess
4677
4688
? diag::type_witness_not_accessible_proto
4678
4689
: diag::type_witness_not_accessible_type;
@@ -4683,7 +4694,7 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
4683
4694
});
4684
4695
}
4685
4696
4686
- if (isUsableFromInlineRequired () ) {
4697
+ if (requiredAccessScope. second ) {
4687
4698
bool witnessIsUsableFromInline = typeDecl->getFormalAccessScope (
4688
4699
DC, /* usableFromInlineAsPublic*/ true ).isPublic ();
4689
4700
if (!witnessIsUsableFromInline)
0 commit comments