@@ -1605,48 +1605,51 @@ bool WitnessChecker::findBestWitness(
16051605 return isReallyBest;
16061606}
16071607
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);
16141611 bool witnessesMustBeUsableFromInline = false ;
1615- if (Adoptee) {
1616- const NominalTypeDecl *adoptingNominal = DC->getSelfNominalTypeDecl ();
16171612
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)) {
16181618 // Compute the intersection of the conforming type's access scope
16191619 // and the protocol's access scope.
16201620 auto scopeIntersection =
1621- result.intersectWith (adoptingNominal ->getFormalAccessScope (DC ));
1621+ result.intersectWith (nominal ->getFormalAccessScope (dc ));
16221622 assert (scopeIntersection.has_value ());
16231623 result = scopeIntersection.value ();
16241624
16251625 if (!result.isPublic ()) {
16261626 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 ();
16311631 }
16321632 } else {
16331633 if (!result.isPublic ()) {
16341634 witnessesMustBeUsableFromInline =
1635- Proto ->getFormalAccessScope (
1636- DC , /* usableFromInlineAsPublic*/ true ).isPublic ();
1635+ proto ->getFormalAccessScope (
1636+ dc , /* usableFromInlineAsPublic*/ true ).isPublic ();
16371637 }
16381638 }
16391639
1640- RequiredAccessScopeAndUsableFromInline =
1641- std::make_pair (result, witnessesMustBeUsableFromInline);
1642- return result;
1640+ return std::make_pair (result, witnessesMustBeUsableFromInline);
16431641}
16441642
16451643bool WitnessChecker::checkWitnessAccess (ValueDecl *requirement,
16461644 ValueDecl *witness,
16471645 bool *isSetter) {
16481646 *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 ;
16501653
16511654 // Setting the 'forConformance' flag means that we admit witnesses in
16521655 // protocol extensions that we can see, but are not necessarily as
@@ -1669,7 +1672,7 @@ bool WitnessChecker::checkWitnessAccess(ValueDecl *requirement,
16691672 }
16701673 }
16711674
1672- if (actualScopeToCheck.hasEqualDeclContextWith (getRequiredAccessScope () ))
1675+ if (actualScopeToCheck.hasEqualDeclContextWith (requiredAccessScope. first ))
16731676 return true ;
16741677 }
16751678
@@ -1703,15 +1706,20 @@ RequirementCheck WitnessChecker::checkWitness(ValueDecl *requirement,
17031706 if (!match.OptionalAdjustments .empty ())
17041707 return CheckKind::OptionalityConflict;
17051708
1709+ auto requiredAccessScope = evaluateOrDefault (
1710+ Context.evaluator , ConformanceAccessScopeRequest{DC, Proto},
1711+ std::make_pair (AccessScope::getPublic (), false ));
1712+
17061713 bool isSetter = false ;
17071714 if (checkWitnessAccess (requirement, match.Witness , &isSetter)) {
17081715 CheckKind kind = (isSetter
17091716 ? CheckKind::AccessOfSetter
17101717 : CheckKind::Access);
1711- return RequirementCheck (kind, getRequiredAccessScope ());
1718+
1719+ return RequirementCheck (kind, requiredAccessScope.first );
17121720 }
17131721
1714- if (isUsableFromInlineRequired () ) {
1722+ if (requiredAccessScope. second ) {
17151723 bool witnessIsUsableFromInline = match.Witness ->getFormalAccessScope (
17161724 DC, /* usableFromInlineAsPublic*/ true ).isPublic ();
17171725 if (!witnessIsUsableFromInline)
@@ -4655,24 +4663,27 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
46554663 checkObjCTypeErasedGenerics (assocType, type, typeDecl);
46564664
46574665 if (typeDecl && !typeDecl->isImplicit ()) {
4666+ auto requiredAccessScope = evaluateOrDefault (
4667+ Context.evaluator , ConformanceAccessScopeRequest{DC, Proto},
4668+ std::make_pair (AccessScope::getPublic (), false ));
4669+
46584670 // Check access.
46594671 bool isSetter = false ;
46604672 if (checkWitnessAccess (assocType, typeDecl, &isSetter)) {
46614673 assert (!isSetter);
46624674
46634675 // 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 ;
46664677
46674678 getASTContext ().addDelayedConformanceDiag (Conformance, false ,
46684679 [DC, requiredAccessScope, typeDecl](
46694680 NormalProtocolConformance *conformance) {
46704681 AccessLevel requiredAccess =
4671- requiredAccessScope.requiredAccessForDiagnostics ();
4682+ requiredAccessScope.first . requiredAccessForDiagnostics ();
46724683 auto proto = conformance->getProtocol ();
46734684 auto protoAccessScope = proto->getFormalAccessScope (DC);
46744685 bool protoForcesAccess =
4675- requiredAccessScope.hasEqualDeclContextWith (protoAccessScope);
4686+ requiredAccessScope.first . hasEqualDeclContextWith (protoAccessScope);
46764687 auto diagKind = protoForcesAccess
46774688 ? diag::type_witness_not_accessible_proto
46784689 : diag::type_witness_not_accessible_type;
@@ -4683,7 +4694,7 @@ void ConformanceChecker::ensureRequirementsAreSatisfied() {
46834694 });
46844695 }
46854696
4686- if (isUsableFromInlineRequired () ) {
4697+ if (requiredAccessScope. second ) {
46874698 bool witnessIsUsableFromInline = typeDecl->getFormalAccessScope (
46884699 DC, /* usableFromInlineAsPublic*/ true ).isPublic ();
46894700 if (!witnessIsUsableFromInline)
0 commit comments