mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #4579 from aleksgapp/sr-2209-access-scope
[SR-2209] Add real AccessScope type.
This commit is contained in:
@@ -3804,19 +3804,6 @@ void swift::performStmtDiagnostics(TypeChecker &TC, const Stmt *S) {
|
||||
// Utility functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
Accessibility
|
||||
swift::accessibilityFromScopeForDiagnostics(const DeclContext *accessScope) {
|
||||
if (!accessScope)
|
||||
return Accessibility::Public;
|
||||
if (isa<ModuleDecl>(accessScope))
|
||||
return Accessibility::Internal;
|
||||
if (accessScope->isModuleScopeContext()) {
|
||||
return Accessibility::FilePrivate;
|
||||
}
|
||||
return Accessibility::Private;
|
||||
}
|
||||
|
||||
void swift::fixItAccessibility(InFlightDiagnostic &diag, ValueDecl *VD,
|
||||
Accessibility desiredAccess, bool isForSetter) {
|
||||
StringRef fixItString;
|
||||
|
||||
@@ -32,13 +32,6 @@ namespace swift {
|
||||
class TypeChecker;
|
||||
class ValueDecl;
|
||||
|
||||
/// Returns the access level associated with \p accessScope, for diagnostic
|
||||
/// purposes.
|
||||
///
|
||||
/// \sa ValueDecl::getFormalAccessScope
|
||||
Accessibility
|
||||
accessibilityFromScopeForDiagnostics(const DeclContext *accessScope);
|
||||
|
||||
/// \brief Emit diagnostics for syntactic restrictions on a given expression.
|
||||
void performSyntacticExprDiagnostics(TypeChecker &TC, const Expr *E,
|
||||
const DeclContext *DC,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "TypeChecker.h"
|
||||
#include "GenericTypeResolver.h"
|
||||
#include "MiscDiagnostics.h"
|
||||
#include "swift/AST/AccessScope.h"
|
||||
#include "swift/AST/ArchetypeBuilder.h"
|
||||
#include "swift/AST/ASTPrinter.h"
|
||||
#include "swift/AST/ASTVisitor.h"
|
||||
@@ -1190,71 +1191,54 @@ class TypeAccessScopeChecker : private TypeWalker {
|
||||
using TypeAccessScopeCacheMap = TypeChecker::TypeAccessScopeCacheMap;
|
||||
TypeAccessScopeCacheMap &Cache;
|
||||
const SourceFile *File;
|
||||
SmallVector<intptr_t, 8> RawScopeStack;
|
||||
|
||||
static constexpr const intptr_t INVALID = -1;
|
||||
SmallVector<Optional<AccessScope>, 8> RawScopeStack;
|
||||
|
||||
explicit TypeAccessScopeChecker(TypeAccessScopeCacheMap &cache,
|
||||
const SourceFile *file)
|
||||
: Cache(cache), File(file) {
|
||||
// Always have something on the stack.
|
||||
RawScopeStack.push_back((intptr_t)INVALID);
|
||||
RawScopeStack.push_back(None);
|
||||
}
|
||||
|
||||
bool shouldVisitOriginalSubstitutedType() override { return true; }
|
||||
|
||||
static intptr_t intersectAccess(const intptr_t first, const intptr_t second) {
|
||||
if (first == INVALID || second == INVALID)
|
||||
return INVALID;
|
||||
if (!first)
|
||||
return second;
|
||||
if (!second)
|
||||
return first;
|
||||
if (first == second)
|
||||
return first;
|
||||
|
||||
auto firstDC = reinterpret_cast<const DeclContext *>(first);
|
||||
auto secondDC = reinterpret_cast<const DeclContext *>(second);
|
||||
if (firstDC->isChildContextOf(secondDC))
|
||||
return first;
|
||||
if (secondDC->isChildContextOf(firstDC))
|
||||
return second;
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
Action walkToTypePre(Type ty) override {
|
||||
// Assume failure until we post-visit this node.
|
||||
// This will be correct as long as we don't ever have self-referential
|
||||
// Types.
|
||||
auto cached = Cache.find(ty);
|
||||
if (cached != Cache.end()) {
|
||||
auto opaqueCached = reinterpret_cast<intptr_t>(cached->second);
|
||||
RawScopeStack.back() = intersectAccess(RawScopeStack.back(),opaqueCached);
|
||||
Optional<AccessScope> &last = RawScopeStack.back();
|
||||
if (last.hasValue())
|
||||
last = last.getValue().intersectWith(cached->second);
|
||||
return Action::SkipChildren;
|
||||
}
|
||||
|
||||
const DeclContext *DC;
|
||||
auto AS = AccessScope::getPublic();
|
||||
if (auto alias = dyn_cast<NameAliasType>(ty.getPointer()))
|
||||
DC = alias->getDecl()->getFormalAccessScope(File);
|
||||
AS = alias->getDecl()->getFormalAccessScope(File);
|
||||
else if (auto nominal = ty->getAnyNominal())
|
||||
DC = nominal->getFormalAccessScope(File);
|
||||
else
|
||||
DC = nullptr;
|
||||
RawScopeStack.push_back(reinterpret_cast<intptr_t>(DC));
|
||||
AS = nominal->getFormalAccessScope(File);
|
||||
RawScopeStack.push_back(AS);
|
||||
|
||||
return Action::Continue;
|
||||
}
|
||||
|
||||
Action walkToTypePost(Type ty) override {
|
||||
auto last = RawScopeStack.pop_back_val();
|
||||
if (last != INVALID)
|
||||
Cache[ty] = reinterpret_cast<const DeclContext *>(last);
|
||||
RawScopeStack.back() = intersectAccess(RawScopeStack.back(), last);
|
||||
Optional<AccessScope> last = RawScopeStack.pop_back_val();
|
||||
if (last.hasValue()) {
|
||||
Cache.insert(std::make_pair(ty, *last));
|
||||
|
||||
Optional<AccessScope> &prev = RawScopeStack.back();
|
||||
if (prev.hasValue())
|
||||
prev = prev.getValue().intersectWith(*last);
|
||||
}
|
||||
|
||||
return Action::Continue;
|
||||
}
|
||||
|
||||
public:
|
||||
static Optional<const DeclContext *>
|
||||
static Optional<AccessScope>
|
||||
getAccessScope(Type ty, const DeclContext *useDC,
|
||||
decltype(TypeChecker::TypeAccessScopeCache) &caches) {
|
||||
const SourceFile *file = useDC->getParentSourceFile();
|
||||
@@ -1291,17 +1275,17 @@ void TypeChecker::computeDefaultAccessibility(ExtensionDecl *ED) {
|
||||
auto getTypeAccess = [this, ED](const TypeLoc &TL) -> Accessibility {
|
||||
if (!TL.getType())
|
||||
return Accessibility::Public;
|
||||
auto scopeDC =
|
||||
auto accessScope =
|
||||
TypeAccessScopeChecker::getAccessScope(TL.getType(),
|
||||
ED->getDeclContext(),
|
||||
TypeAccessScopeCache);
|
||||
// This is an error case and will be diagnosed elsewhere.
|
||||
if (!scopeDC.hasValue())
|
||||
if (!accessScope.hasValue())
|
||||
return Accessibility::Public;
|
||||
|
||||
if (!scopeDC.getValue())
|
||||
if (accessScope->isPublic())
|
||||
return Accessibility::Public;
|
||||
if (isa<ModuleDecl>(scopeDC.getValue()))
|
||||
if (isa<ModuleDecl>(accessScope->getDeclContext()))
|
||||
return Accessibility::Internal;
|
||||
// Because extensions are always at top-level, they should never
|
||||
// reference declarations not at the top level. (And any such references
|
||||
@@ -1436,7 +1420,7 @@ void TypeChecker::computeAccessibility(ValueDecl *D) {
|
||||
namespace {
|
||||
|
||||
class TypeAccessScopeDiagnoser : private ASTWalker {
|
||||
const DeclContext *accessScope;
|
||||
AccessScope accessScope;
|
||||
const DeclContext *useDC;
|
||||
const ComponentIdentTypeRepr *offendingType = nullptr;
|
||||
|
||||
@@ -1465,15 +1449,16 @@ class TypeAccessScopeDiagnoser : private ASTWalker {
|
||||
return offendingType != nullptr;
|
||||
}
|
||||
|
||||
explicit TypeAccessScopeDiagnoser(const DeclContext *accessScope,
|
||||
explicit TypeAccessScopeDiagnoser(AccessScope accessScope,
|
||||
const DeclContext *useDC)
|
||||
: accessScope(accessScope), useDC(useDC) {}
|
||||
|
||||
public:
|
||||
static const TypeRepr *findTypeWithScope(TypeRepr *TR,
|
||||
const DeclContext *accessScope,
|
||||
AccessScope accessScope,
|
||||
const DeclContext *useDC) {
|
||||
assert(accessScope && "why would we need to find a public access scope?");
|
||||
assert(!accessScope.isPublic() &&
|
||||
"why would we need to find a public access scope?");
|
||||
TypeAccessScopeDiagnoser diagnoser(accessScope, useDC);
|
||||
TR->walk(diagnoser);
|
||||
return diagnoser.offendingType;
|
||||
@@ -1501,19 +1486,20 @@ enum class DowngradeToWarning: bool {
|
||||
/// part of the type that caused the problem could not be found. The DeclContext
|
||||
/// is never null.
|
||||
static void checkTypeAccessibilityImpl(
|
||||
TypeChecker &TC, TypeLoc TL, const DeclContext *contextAccessScope,
|
||||
TypeChecker &TC, TypeLoc TL, AccessScope contextAccessScope,
|
||||
const DeclContext *useDC,
|
||||
llvm::function_ref<void(const DeclContext *, const TypeRepr *)> diagnose) {
|
||||
llvm::function_ref<void(AccessScope, const TypeRepr *)> diagnose) {
|
||||
if (!TC.getLangOpts().EnableAccessControl)
|
||||
return;
|
||||
if (!TL.getType())
|
||||
return;
|
||||
// Don't spend time checking local declarations; this is always valid by the
|
||||
// time we get to this point.
|
||||
if (contextAccessScope && contextAccessScope->isLocalContext())
|
||||
if (!contextAccessScope.isPublic() &&
|
||||
contextAccessScope.getDeclContext()->isLocalContext())
|
||||
return;
|
||||
|
||||
Optional<const DeclContext *> typeAccessScope =
|
||||
auto typeAccessScope =
|
||||
TypeAccessScopeChecker::getAccessScope(TL.getType(), useDC,
|
||||
TC.TypeAccessScopeCache);
|
||||
|
||||
@@ -1523,10 +1509,10 @@ static void checkTypeAccessibilityImpl(
|
||||
if (!typeAccessScope.hasValue())
|
||||
return;
|
||||
|
||||
if (!*typeAccessScope || *typeAccessScope == contextAccessScope ||
|
||||
contextAccessScope->isChildContextOf(*typeAccessScope)) {
|
||||
if (typeAccessScope->isPublic() ||
|
||||
typeAccessScope->hasEqualDeclContextWith(contextAccessScope) ||
|
||||
contextAccessScope.isChildOf(*typeAccessScope))
|
||||
return;
|
||||
}
|
||||
|
||||
const TypeRepr *complainRepr = nullptr;
|
||||
if (TypeRepr *TR = TL.getTypeRepr()) {
|
||||
@@ -1547,15 +1533,16 @@ static void checkTypeAccessibilityImpl(
|
||||
/// early versions of Swift 3 not diagnosing certain access violations.
|
||||
static void checkTypeAccessibility(
|
||||
TypeChecker &TC, TypeLoc TL, const ValueDecl *context,
|
||||
llvm::function_ref<void(const DeclContext *, const TypeRepr *,
|
||||
llvm::function_ref<void(AccessScope, const TypeRepr *,
|
||||
DowngradeToWarning)> diagnose) {
|
||||
const DeclContext *contextAccessScope = context->getFormalAccessScope();
|
||||
AccessScope contextAccessScope = context->getFormalAccessScope();
|
||||
checkTypeAccessibilityImpl(TC, TL, contextAccessScope,
|
||||
context->getDeclContext(),
|
||||
[=](const DeclContext *requiredAccessScope,
|
||||
[=](AccessScope requiredAccessScope,
|
||||
const TypeRepr *offendingTR) {
|
||||
auto downgradeToWarning = DowngradeToWarning::No;
|
||||
if (contextAccessScope && !isa<ModuleDecl>(contextAccessScope)) {
|
||||
if (!contextAccessScope.isPublic() &&
|
||||
!isa<ModuleDecl>(contextAccessScope.getDeclContext())) {
|
||||
// Swift 3.0.0 mistakenly didn't diagnose any issues when the context
|
||||
// access scope represented a private or fileprivate level.
|
||||
downgradeToWarning = DowngradeToWarning::Yes;
|
||||
@@ -1587,7 +1574,7 @@ static void highlightOffendingType(TypeChecker &TC, InFlightDiagnostic &diag,
|
||||
static void checkGenericParamAccessibility(TypeChecker &TC,
|
||||
const GenericParamList *params,
|
||||
const Decl *owner,
|
||||
const DeclContext *accessScope,
|
||||
AccessScope accessScope,
|
||||
Accessibility contextAccess) {
|
||||
if (!params)
|
||||
return;
|
||||
@@ -1597,12 +1584,13 @@ static void checkGenericParamAccessibility(TypeChecker &TC,
|
||||
AEK_Parameter = 0,
|
||||
AEK_Requirement
|
||||
} accessibilityErrorKind;
|
||||
const DeclContext *minAccessScope = nullptr;
|
||||
auto minAccessScope = AccessScope::getPublic();
|
||||
const TypeRepr *complainRepr = nullptr;
|
||||
|
||||
// Swift 3.0.0 mistakenly didn't diagnose any issues when the context access
|
||||
// scope represented a private or fileprivate level.
|
||||
bool shouldDowngradeToWarning = accessScope && !isa<ModuleDecl>(accessScope);
|
||||
bool shouldDowngradeToWarning =
|
||||
!accessScope.isPublic() && !isa<ModuleDecl>(accessScope.getDeclContext());
|
||||
|
||||
for (auto param : *params) {
|
||||
if (param->getInherited().empty())
|
||||
@@ -1610,11 +1598,11 @@ static void checkGenericParamAccessibility(TypeChecker &TC,
|
||||
assert(param->getInherited().size() == 1);
|
||||
checkTypeAccessibilityImpl(TC, param->getInherited().front(), accessScope,
|
||||
owner->getDeclContext(),
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *thisComplainRepr) {
|
||||
if (!minAccessScope ||
|
||||
typeAccessScope->isChildContextOf(minAccessScope) ||
|
||||
(!complainRepr && typeAccessScope == minAccessScope)) {
|
||||
if (typeAccessScope.isChildOf(minAccessScope) ||
|
||||
(!complainRepr &&
|
||||
typeAccessScope.hasEqualDeclContextWith(minAccessScope))) {
|
||||
minAccessScope = typeAccessScope;
|
||||
complainRepr = thisComplainRepr;
|
||||
accessibilityErrorKind = AEK_Parameter;
|
||||
@@ -1623,11 +1611,11 @@ static void checkGenericParamAccessibility(TypeChecker &TC,
|
||||
}
|
||||
|
||||
for (auto &requirement : params->getRequirements()) {
|
||||
auto callback = [&](const DeclContext *typeAccessScope,
|
||||
auto callback = [&](AccessScope typeAccessScope,
|
||||
const TypeRepr *thisComplainRepr) {
|
||||
if (!minAccessScope ||
|
||||
typeAccessScope->isChildContextOf(minAccessScope) ||
|
||||
(!complainRepr && typeAccessScope == minAccessScope)) {
|
||||
if (typeAccessScope.isChildOf(minAccessScope) ||
|
||||
(!complainRepr &&
|
||||
typeAccessScope.hasEqualDeclContextWith(minAccessScope))) {
|
||||
minAccessScope = typeAccessScope;
|
||||
complainRepr = thisComplainRepr;
|
||||
accessibilityErrorKind = AEK_Requirement;
|
||||
@@ -1653,8 +1641,8 @@ static void checkGenericParamAccessibility(TypeChecker &TC,
|
||||
}
|
||||
}
|
||||
|
||||
if (minAccessScope) {
|
||||
auto minAccess = accessibilityFromScopeForDiagnostics(minAccessScope);
|
||||
if (!minAccessScope.isPublic()) {
|
||||
auto minAccess = minAccessScope.accessibilityForDiagnostics();
|
||||
|
||||
bool isExplicit =
|
||||
owner->getAttrs().hasAttribute<AccessibilityAttr>() ||
|
||||
@@ -1665,6 +1653,7 @@ static void checkGenericParamAccessibility(TypeChecker &TC,
|
||||
auto diag = TC.diagnose(owner, diagID,
|
||||
owner->getDescriptiveKind(), isExplicit,
|
||||
contextAccess, minAccess,
|
||||
isa<FileUnit>(owner->getDeclContext()),
|
||||
accessibilityErrorKind);
|
||||
highlightOffendingType(TC, diag, complainRepr);
|
||||
}
|
||||
@@ -1727,13 +1716,15 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
|
||||
checkTypeAccessibility(TC, TypeLoc::withoutLoc(theVar->getType()),
|
||||
theVar,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *complainRepr,
|
||||
DowngradeToWarning downgradeToWarning) {
|
||||
auto typeAccess =
|
||||
accessibilityFromScopeForDiagnostics(typeAccessScope);
|
||||
auto typeAccess = typeAccessScope.accessibilityForDiagnostics();
|
||||
bool isExplicit =
|
||||
theVar->getAttrs().hasAttribute<AccessibilityAttr>();
|
||||
auto theVarAccess = isExplicit
|
||||
? theVar->getFormalAccess()
|
||||
: typeAccessScope.requiredAccessibilityForDiagnostics();
|
||||
auto diagID = diag::pattern_type_access_inferred;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::pattern_type_access_inferred_warn;
|
||||
@@ -1741,7 +1732,8 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
theVar->isLet(),
|
||||
isTypeContext,
|
||||
isExplicit,
|
||||
theVar->getFormalAccess(),
|
||||
theVarAccess,
|
||||
isa<FileUnit>(theVar->getDeclContext()),
|
||||
typeAccess,
|
||||
theVar->getType());
|
||||
});
|
||||
@@ -1764,21 +1756,25 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
return;
|
||||
|
||||
checkTypeAccessibility(TC, TP->getTypeLoc(), anyVar,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *complainRepr,
|
||||
DowngradeToWarning downgradeToWarning) {
|
||||
auto typeAccess = accessibilityFromScopeForDiagnostics(typeAccessScope);
|
||||
auto typeAccess = typeAccessScope.accessibilityForDiagnostics();
|
||||
bool isExplicit =
|
||||
anyVar->getAttrs().hasAttribute<AccessibilityAttr>() ||
|
||||
anyVar->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
|
||||
auto diagID = diag::pattern_type_access;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::pattern_type_access_warn;
|
||||
auto anyVarAccess = isExplicit
|
||||
? anyVar->getFormalAccess()
|
||||
: typeAccessScope.requiredAccessibilityForDiagnostics();
|
||||
auto diag = TC.diagnose(P->getLoc(), diagID,
|
||||
anyVar->isLet(),
|
||||
isTypeContext,
|
||||
isExplicit,
|
||||
anyVar->getFormalAccess(),
|
||||
anyVarAccess,
|
||||
isa<FileUnit>(anyVar->getDeclContext()),
|
||||
typeAccess);
|
||||
highlightOffendingType(TC, diag, complainRepr);
|
||||
});
|
||||
@@ -1790,17 +1786,17 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
auto TAD = cast<TypeAliasDecl>(D);
|
||||
|
||||
checkTypeAccessibility(TC, TAD->getUnderlyingTypeLoc(), TAD,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *complainRepr,
|
||||
DowngradeToWarning downgradeToWarning) {
|
||||
auto typeAccess = accessibilityFromScopeForDiagnostics(typeAccessScope);
|
||||
auto typeAccess = typeAccessScope.accessibilityForDiagnostics();
|
||||
bool isExplicit = TAD->getAttrs().hasAttribute<AccessibilityAttr>();
|
||||
auto diagID = diag::type_alias_underlying_type_access;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::type_alias_underlying_type_access_warn;
|
||||
auto diag = TC.diagnose(TAD, diagID,
|
||||
isExplicit, TAD->getFormalAccess(),
|
||||
typeAccess);
|
||||
typeAccess, isa<FileUnit>(TAD->getDeclContext()));
|
||||
highlightOffendingType(TC, diag, complainRepr);
|
||||
});
|
||||
|
||||
@@ -1815,7 +1811,7 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
AEK_DefaultDefinition = 0,
|
||||
AEK_Requirement
|
||||
} accessibilityErrorKind;
|
||||
const DeclContext *minAccessScope = nullptr;
|
||||
auto minAccessScope = AccessScope::getPublic();
|
||||
const TypeRepr *complainRepr = nullptr;
|
||||
auto downgradeToWarning = DowngradeToWarning::No;
|
||||
|
||||
@@ -1823,12 +1819,12 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
assocType->getInherited().end(),
|
||||
[&](TypeLoc requirement) {
|
||||
checkTypeAccessibility(TC, requirement, assocType,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *thisComplainRepr,
|
||||
DowngradeToWarning downgradeDiag) {
|
||||
if (!minAccessScope ||
|
||||
typeAccessScope->isChildContextOf(minAccessScope) ||
|
||||
(!complainRepr && typeAccessScope == minAccessScope)) {
|
||||
if (typeAccessScope.isChildOf(minAccessScope) ||
|
||||
(!complainRepr &&
|
||||
typeAccessScope.hasEqualDeclContextWith(minAccessScope))) {
|
||||
minAccessScope = typeAccessScope;
|
||||
complainRepr = thisComplainRepr;
|
||||
accessibilityErrorKind = AEK_Requirement;
|
||||
@@ -1837,12 +1833,12 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
});
|
||||
});
|
||||
checkTypeAccessibility(TC, assocType->getDefaultDefinitionLoc(), assocType,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *thisComplainRepr,
|
||||
DowngradeToWarning downgradeDiag) {
|
||||
if (!minAccessScope ||
|
||||
typeAccessScope->isChildContextOf(minAccessScope) ||
|
||||
(!complainRepr && typeAccessScope == minAccessScope)) {
|
||||
if (typeAccessScope.isChildOf(minAccessScope) ||
|
||||
(!complainRepr &&
|
||||
typeAccessScope.hasEqualDeclContextWith(minAccessScope))) {
|
||||
minAccessScope = typeAccessScope;
|
||||
complainRepr = thisComplainRepr;
|
||||
accessibilityErrorKind = AEK_DefaultDefinition;
|
||||
@@ -1850,8 +1846,8 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
}
|
||||
});
|
||||
|
||||
if (minAccessScope) {
|
||||
auto minAccess = accessibilityFromScopeForDiagnostics(minAccessScope);
|
||||
if (!minAccessScope.isPublic()) {
|
||||
auto minAccess = minAccessScope.accessibilityForDiagnostics();
|
||||
auto diagID = diag::associated_type_access;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::associated_type_access_warn;
|
||||
@@ -1880,17 +1876,17 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
if (rawTypeLocIter == ED->getInherited().end())
|
||||
return;
|
||||
checkTypeAccessibility(TC, *rawTypeLocIter, ED,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *complainRepr,
|
||||
DowngradeToWarning downgradeToWarning) {
|
||||
auto typeAccess = accessibilityFromScopeForDiagnostics(typeAccessScope);
|
||||
auto typeAccess = typeAccessScope.accessibilityForDiagnostics();
|
||||
bool isExplicit = ED->getAttrs().hasAttribute<AccessibilityAttr>();
|
||||
auto diagID = diag::enum_raw_type_access;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::enum_raw_type_access_warn;
|
||||
auto diag = TC.diagnose(ED, diagID,
|
||||
isExplicit, ED->getFormalAccess(),
|
||||
typeAccess);
|
||||
auto diag = TC.diagnose(ED, diagID, isExplicit,
|
||||
ED->getFormalAccess(), typeAccess,
|
||||
isa<FileUnit>(ED->getDeclContext()));
|
||||
highlightOffendingType(TC, diag, complainRepr);
|
||||
});
|
||||
}
|
||||
@@ -1921,17 +1917,17 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
if (superclassLocIter == CD->getInherited().end())
|
||||
return;
|
||||
checkTypeAccessibility(TC, *superclassLocIter, CD,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *complainRepr,
|
||||
DowngradeToWarning downgradeToWarning) {
|
||||
auto typeAccess = accessibilityFromScopeForDiagnostics(typeAccessScope);
|
||||
auto typeAccess = typeAccessScope.accessibilityForDiagnostics();
|
||||
bool isExplicit = CD->getAttrs().hasAttribute<AccessibilityAttr>();
|
||||
auto diagID = diag::class_super_access;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::class_super_access_warn;
|
||||
auto diag = TC.diagnose(CD, diagID,
|
||||
isExplicit, CD->getFormalAccess(),
|
||||
typeAccess);
|
||||
auto diag = TC.diagnose(CD, diagID, isExplicit, CD->getFormalAccess(),
|
||||
typeAccess,
|
||||
isa<FileUnit>(CD->getDeclContext()));
|
||||
highlightOffendingType(TC, diag, complainRepr);
|
||||
});
|
||||
}
|
||||
@@ -1942,7 +1938,7 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
case DeclKind::Protocol: {
|
||||
auto proto = cast<ProtocolDecl>(D);
|
||||
|
||||
const DeclContext *minAccessScope = nullptr;
|
||||
auto minAccessScope = AccessScope::getPublic();
|
||||
const TypeRepr *complainRepr = nullptr;
|
||||
auto downgradeToWarning = DowngradeToWarning::No;
|
||||
|
||||
@@ -1950,12 +1946,12 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
proto->getInherited().end(),
|
||||
[&](TypeLoc requirement) {
|
||||
checkTypeAccessibility(TC, requirement, proto,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *thisComplainRepr,
|
||||
DowngradeToWarning downgradeDiag) {
|
||||
if (!minAccessScope ||
|
||||
typeAccessScope->isChildContextOf(minAccessScope) ||
|
||||
(!complainRepr && typeAccessScope == minAccessScope)) {
|
||||
if (typeAccessScope.isChildOf(minAccessScope) ||
|
||||
(!complainRepr &&
|
||||
typeAccessScope.hasEqualDeclContextWith(minAccessScope))) {
|
||||
minAccessScope = typeAccessScope;
|
||||
complainRepr = thisComplainRepr;
|
||||
downgradeToWarning = downgradeDiag;
|
||||
@@ -1963,14 +1959,15 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
});
|
||||
});
|
||||
|
||||
if (minAccessScope) {
|
||||
auto minAccess = accessibilityFromScopeForDiagnostics(minAccessScope);
|
||||
if (!minAccessScope.isPublic()) {
|
||||
auto minAccess = minAccessScope.accessibilityForDiagnostics();
|
||||
bool isExplicit = proto->getAttrs().hasAttribute<AccessibilityAttr>();
|
||||
auto diagID = diag::protocol_refine_access;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::protocol_refine_access_warn;
|
||||
auto diag = TC.diagnose(proto, diagID,
|
||||
isExplicit, proto->getFormalAccess(), minAccess);
|
||||
isExplicit, proto->getFormalAccess(), minAccess,
|
||||
isa<FileUnit>(proto->getDeclContext()));
|
||||
highlightOffendingType(TC, diag, complainRepr);
|
||||
}
|
||||
return;
|
||||
@@ -1979,19 +1976,19 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
case DeclKind::Subscript: {
|
||||
auto SD = cast<SubscriptDecl>(D);
|
||||
|
||||
const DeclContext *minAccessScope = nullptr;
|
||||
auto minAccessScope = AccessScope::getPublic();
|
||||
const TypeRepr *complainRepr = nullptr;
|
||||
auto downgradeToWarning = DowngradeToWarning::No;
|
||||
bool problemIsElement = false;
|
||||
|
||||
for (auto &P : *SD->getIndices()) {
|
||||
checkTypeAccessibility(TC, P->getTypeLoc(), SD,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *thisComplainRepr,
|
||||
DowngradeToWarning downgradeDiag) {
|
||||
if (!minAccessScope ||
|
||||
typeAccessScope->isChildContextOf(minAccessScope) ||
|
||||
(!complainRepr && typeAccessScope == minAccessScope)) {
|
||||
if (typeAccessScope.isChildOf(minAccessScope) ||
|
||||
(!complainRepr &&
|
||||
typeAccessScope.hasEqualDeclContextWith(minAccessScope))) {
|
||||
minAccessScope = typeAccessScope;
|
||||
complainRepr = thisComplainRepr;
|
||||
downgradeToWarning = downgradeDiag;
|
||||
@@ -2000,12 +1997,12 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
}
|
||||
|
||||
checkTypeAccessibility(TC, SD->getElementTypeLoc(), SD,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *thisComplainRepr,
|
||||
DowngradeToWarning downgradeDiag) {
|
||||
if (!minAccessScope ||
|
||||
typeAccessScope->isChildContextOf(minAccessScope) ||
|
||||
(!complainRepr && typeAccessScope == minAccessScope)) {
|
||||
if (typeAccessScope.isChildOf(minAccessScope) ||
|
||||
(!complainRepr &&
|
||||
typeAccessScope.hasEqualDeclContextWith(minAccessScope))) {
|
||||
minAccessScope = typeAccessScope;
|
||||
complainRepr = thisComplainRepr;
|
||||
downgradeToWarning = downgradeDiag;
|
||||
@@ -2013,17 +2010,20 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
}
|
||||
});
|
||||
|
||||
if (minAccessScope) {
|
||||
auto minAccess = accessibilityFromScopeForDiagnostics(minAccessScope);
|
||||
if (!minAccessScope.isPublic()) {
|
||||
auto minAccess = minAccessScope.accessibilityForDiagnostics();
|
||||
bool isExplicit =
|
||||
SD->getAttrs().hasAttribute<AccessibilityAttr>() ||
|
||||
SD->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
|
||||
auto diagID = diag::subscript_type_access;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::subscript_type_access_warn;
|
||||
auto subscriptDeclAccess = isExplicit
|
||||
? SD->getFormalAccess()
|
||||
: minAccessScope.requiredAccessibilityForDiagnostics();
|
||||
auto diag = TC.diagnose(SD, diagID,
|
||||
isExplicit,
|
||||
SD->getFormalAccess(),
|
||||
subscriptDeclAccess,
|
||||
minAccess,
|
||||
problemIsElement);
|
||||
highlightOffendingType(TC, diag, complainRepr);
|
||||
@@ -2048,19 +2048,19 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
FK_Initializer
|
||||
};
|
||||
|
||||
const DeclContext *minAccessScope = nullptr;
|
||||
auto minAccessScope = AccessScope::getPublic();
|
||||
const TypeRepr *complainRepr = nullptr;
|
||||
auto downgradeToWarning = DowngradeToWarning::No;
|
||||
|
||||
for (auto *PL : fn->getParameterLists().slice(isTypeContext)) {
|
||||
for (auto &P : *PL) {
|
||||
checkTypeAccessibility(TC, P->getTypeLoc(), fn,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *thisComplainRepr,
|
||||
DowngradeToWarning downgradeDiag) {
|
||||
if (!minAccessScope ||
|
||||
typeAccessScope->isChildContextOf(minAccessScope) ||
|
||||
(!complainRepr && typeAccessScope == minAccessScope)) {
|
||||
if (typeAccessScope.isChildOf(minAccessScope) ||
|
||||
(!complainRepr &&
|
||||
typeAccessScope.hasEqualDeclContextWith(minAccessScope))) {
|
||||
minAccessScope = typeAccessScope;
|
||||
complainRepr = thisComplainRepr;
|
||||
downgradeToWarning = downgradeDiag;
|
||||
@@ -2072,12 +2072,12 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
bool problemIsResult = false;
|
||||
if (auto FD = dyn_cast<FuncDecl>(fn)) {
|
||||
checkTypeAccessibility(TC, FD->getBodyResultTypeLoc(), FD,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *thisComplainRepr,
|
||||
DowngradeToWarning downgradeDiag) {
|
||||
if (!minAccessScope ||
|
||||
typeAccessScope->isChildContextOf(minAccessScope) ||
|
||||
(!complainRepr && typeAccessScope == minAccessScope)) {
|
||||
if (typeAccessScope.isChildOf(minAccessScope) ||
|
||||
(!complainRepr &&
|
||||
typeAccessScope.hasEqualDeclContextWith(minAccessScope))) {
|
||||
minAccessScope = typeAccessScope;
|
||||
complainRepr = thisComplainRepr;
|
||||
downgradeToWarning = downgradeDiag;
|
||||
@@ -2086,20 +2086,26 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
});
|
||||
}
|
||||
|
||||
if (minAccessScope) {
|
||||
auto minAccess = accessibilityFromScopeForDiagnostics(minAccessScope);
|
||||
if (!minAccessScope.isPublic()) {
|
||||
auto minAccess = minAccessScope.accessibilityForDiagnostics();
|
||||
auto functionKind = isa<ConstructorDecl>(fn)
|
||||
? FK_Initializer
|
||||
: isTypeContext ? FK_Method : FK_Function;
|
||||
bool isExplicit =
|
||||
fn->getAttrs().hasAttribute<AccessibilityAttr>() ||
|
||||
D->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
|
||||
fn->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
|
||||
auto diagID = diag::function_type_access;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::function_type_access_warn;
|
||||
auto fnAccess = isExplicit
|
||||
? fn->getFormalAccess()
|
||||
: minAccessScope.requiredAccessibilityForDiagnostics();
|
||||
auto diag = TC.diagnose(fn, diagID,
|
||||
isExplicit,
|
||||
fn->getFormalAccess(),
|
||||
fnAccess,
|
||||
isa<FileUnit>(fn->getDeclContext()),
|
||||
minAccess,
|
||||
isa<ConstructorDecl>(fn) ? FK_Initializer :
|
||||
isTypeContext ? FK_Method : FK_Function,
|
||||
functionKind,
|
||||
problemIsResult);
|
||||
highlightOffendingType(TC, diag, complainRepr);
|
||||
}
|
||||
@@ -2112,10 +2118,10 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
|
||||
if (!EED->hasArgumentType())
|
||||
return;
|
||||
checkTypeAccessibility(TC, EED->getArgumentTypeLoc(), EED,
|
||||
[&](const DeclContext *typeAccessScope,
|
||||
[&](AccessScope typeAccessScope,
|
||||
const TypeRepr *complainRepr,
|
||||
DowngradeToWarning downgradeToWarning) {
|
||||
auto typeAccess = accessibilityFromScopeForDiagnostics(typeAccessScope);
|
||||
auto typeAccess = typeAccessScope.accessibilityForDiagnostics();
|
||||
auto diagID = diag::enum_case_access;
|
||||
if (downgradeToWarning == DowngradeToWarning::Yes)
|
||||
diagID = diag::enum_case_access_warn;
|
||||
@@ -5695,44 +5701,34 @@ public:
|
||||
|
||||
} else {
|
||||
auto matchAccessScope =
|
||||
matchDecl->getFormalAccessScope(decl->getDeclContext());
|
||||
const DeclContext *requiredAccessScope =
|
||||
classDecl->getFormalAccessScope(decl->getDeclContext());
|
||||
matchDecl->getFormalAccessScope(decl->getDeclContext());
|
||||
auto classAccessScope =
|
||||
classDecl->getFormalAccessScope(decl->getDeclContext());
|
||||
auto requiredAccessScope =
|
||||
matchAccessScope.intersectWith(classAccessScope);
|
||||
|
||||
// FIXME: This is the same operation as
|
||||
// TypeAccessScopeChecker::intersectAccess.
|
||||
if (!requiredAccessScope) {
|
||||
requiredAccessScope = matchAccessScope;
|
||||
} else if (matchAccessScope) {
|
||||
if (matchAccessScope->isChildContextOf(requiredAccessScope)) {
|
||||
requiredAccessScope = matchAccessScope;
|
||||
} else {
|
||||
assert(requiredAccessScope == matchAccessScope ||
|
||||
requiredAccessScope->isChildContextOf(matchAccessScope));
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldDiagnose = false;
|
||||
bool shouldDiagnoseSetter = false;
|
||||
if (!isa<ConstructorDecl>(decl)) {
|
||||
shouldDiagnose = !decl->isAccessibleFrom(requiredAccessScope);
|
||||
auto DC = requiredAccessScope->getDeclContext();
|
||||
shouldDiagnose = !decl->isAccessibleFrom(DC);
|
||||
|
||||
if (!shouldDiagnose && matchDecl->isSettable(decl->getDeclContext())){
|
||||
auto matchASD = cast<AbstractStorageDecl>(matchDecl);
|
||||
if (matchASD->isSetterAccessibleFrom(decl->getDeclContext())) {
|
||||
const auto *ASD = cast<AbstractStorageDecl>(decl);
|
||||
shouldDiagnoseSetter =
|
||||
ASD->isSettable(requiredAccessScope) &&
|
||||
!ASD->isSetterAccessibleFrom(requiredAccessScope);
|
||||
ASD->isSettable(DC) && !ASD->isSetterAccessibleFrom(DC);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldDiagnose || shouldDiagnoseSetter) {
|
||||
bool overriddenForcesAccess =
|
||||
(requiredAccessScope == matchAccessScope &&
|
||||
matchAccess != Accessibility::Open);
|
||||
(requiredAccessScope->hasEqualDeclContextWith(matchAccessScope) &&
|
||||
matchAccess != Accessibility::Open);
|
||||
Accessibility requiredAccess =
|
||||
accessibilityFromScopeForDiagnostics(requiredAccessScope);
|
||||
requiredAccessScope->requiredAccessibilityForDiagnostics();
|
||||
{
|
||||
auto diag = TC.diagnose(decl, diag::override_not_accessible,
|
||||
shouldDiagnoseSetter,
|
||||
@@ -6394,25 +6390,28 @@ public:
|
||||
if (!IsFirstPass) {
|
||||
TC.computeDefaultAccessibility(ED);
|
||||
if (auto *AA = ED->getAttrs().getAttribute<AccessibilityAttr>()) {
|
||||
const DeclContext *desiredAccessScope;
|
||||
switch (AA->getAccess()) {
|
||||
const auto access = AA->getAccess();
|
||||
AccessScope desiredAccessScope = AccessScope::getPublic();
|
||||
switch (access) {
|
||||
case Accessibility::Private:
|
||||
assert(ED->getDeclContext()->isModuleScopeContext() &&
|
||||
"non-top-level extensions make 'private' != 'fileprivate'");
|
||||
SWIFT_FALLTHROUGH;
|
||||
case Accessibility::FilePrivate:
|
||||
desiredAccessScope = ED->getModuleScopeContext();
|
||||
case Accessibility::FilePrivate: {
|
||||
const DeclContext *DC = ED->getModuleScopeContext();
|
||||
bool isPrivate = access == Accessibility::Private;
|
||||
desiredAccessScope = AccessScope(DC, isPrivate);
|
||||
break;
|
||||
}
|
||||
case Accessibility::Internal:
|
||||
desiredAccessScope = ED->getModuleContext();
|
||||
desiredAccessScope = AccessScope(ED->getModuleContext());
|
||||
break;
|
||||
case Accessibility::Public:
|
||||
case Accessibility::Open:
|
||||
desiredAccessScope = nullptr;
|
||||
break;
|
||||
}
|
||||
checkGenericParamAccessibility(TC, ED->getGenericParams(), ED,
|
||||
desiredAccessScope, AA->getAccess());
|
||||
desiredAccessScope, access);
|
||||
}
|
||||
TC.checkConformancesInContext(ED, ED);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "TypeChecker.h"
|
||||
#include "swift/Basic/SourceManager.h"
|
||||
#include "swift/Basic/StringExtras.h"
|
||||
#include "swift/AST/AccessScope.h"
|
||||
#include "swift/AST/ArchetypeBuilder.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/ASTPrinter.h"
|
||||
@@ -139,7 +140,7 @@ namespace {
|
||||
unsigned &bestIdx,
|
||||
bool &doNotDiagnoseMatches);
|
||||
|
||||
bool checkWitnessAccessibility(const DeclContext *&requiredAccessScope,
|
||||
bool checkWitnessAccessibility(AccessScope &requiredAccessScope,
|
||||
ValueDecl *requirement,
|
||||
ValueDecl *witness,
|
||||
bool *isSetter);
|
||||
@@ -148,7 +149,7 @@ namespace {
|
||||
ValueDecl *witness,
|
||||
AvailabilityContext *requirementInfo);
|
||||
|
||||
RequirementCheck checkWitness(const DeclContext *requiredAccessScope,
|
||||
RequirementCheck checkWitness(AccessScope requiredAccessScope,
|
||||
ValueDecl *requirement,
|
||||
RequirementMatch match);
|
||||
};
|
||||
@@ -466,22 +467,22 @@ namespace {
|
||||
|
||||
/// The required access scope, if the check failed due to the
|
||||
/// witness being less accessible than the requirement.
|
||||
const DeclContext *RequiredAccessScope;
|
||||
AccessScope RequiredAccessScope;
|
||||
|
||||
/// The required availability, if the check failed due to the
|
||||
/// witness being less available than the requirement.
|
||||
AvailabilityContext RequiredAvailability;
|
||||
|
||||
RequirementCheck(CheckKind kind)
|
||||
: Kind(kind), RequiredAccessScope(nullptr),
|
||||
: Kind(kind), RequiredAccessScope(AccessScope::getPublic()),
|
||||
RequiredAvailability(AvailabilityContext::alwaysAvailable()) { }
|
||||
|
||||
RequirementCheck(CheckKind kind, const DeclContext *requiredAccessScope)
|
||||
RequirementCheck(CheckKind kind, AccessScope requiredAccessScope)
|
||||
: Kind(kind), RequiredAccessScope(requiredAccessScope),
|
||||
RequiredAvailability(AvailabilityContext::alwaysAvailable()) { }
|
||||
|
||||
RequirementCheck(CheckKind kind, AvailabilityContext requiredAvailability)
|
||||
: Kind(kind), RequiredAccessScope(nullptr),
|
||||
: Kind(kind), RequiredAccessScope(AccessScope::getPublic()),
|
||||
RequiredAvailability(requiredAvailability) { }
|
||||
};
|
||||
}
|
||||
@@ -1427,29 +1428,20 @@ bool WitnessChecker::findBestWitness(
|
||||
}
|
||||
|
||||
bool WitnessChecker::
|
||||
checkWitnessAccessibility(const DeclContext *&requiredAccessScope,
|
||||
checkWitnessAccessibility(AccessScope &requiredAccessScope,
|
||||
ValueDecl *requirement,
|
||||
ValueDecl *witness,
|
||||
bool *isSetter) {
|
||||
*isSetter = false;
|
||||
|
||||
const DeclContext *protoAccessScope = Proto->getFormalAccessScope(DC);
|
||||
auto scopeIntersection =
|
||||
requiredAccessScope.intersectWith(Proto->getFormalAccessScope(DC));
|
||||
assert(scopeIntersection.hasValue());
|
||||
|
||||
// FIXME: This is the same operation as TypeCheckDecl.cpp's
|
||||
// TypeAccessScopeChecker::intersectAccess.
|
||||
if (!requiredAccessScope) {
|
||||
requiredAccessScope = protoAccessScope;
|
||||
} else if (protoAccessScope) {
|
||||
if (protoAccessScope->isChildContextOf(requiredAccessScope)) {
|
||||
requiredAccessScope = protoAccessScope;
|
||||
} else {
|
||||
assert(requiredAccessScope == protoAccessScope ||
|
||||
requiredAccessScope->isChildContextOf(protoAccessScope));
|
||||
}
|
||||
}
|
||||
requiredAccessScope = *scopeIntersection;
|
||||
|
||||
const DeclContext *actualScopeToCheck = requiredAccessScope;
|
||||
if (!witness->isAccessibleFrom(actualScopeToCheck)) {
|
||||
AccessScope actualScopeToCheck = requiredAccessScope;
|
||||
if (!witness->isAccessibleFrom(actualScopeToCheck.getDeclContext())) {
|
||||
// Special case: if we have `@testable import` of the witness's module,
|
||||
// allow the witness to match if it would have matched for just this file.
|
||||
// That is, if '@testable' allows us to see the witness here, it should
|
||||
@@ -1464,7 +1456,7 @@ checkWitnessAccessibility(const DeclContext *&requiredAccessScope,
|
||||
}
|
||||
}
|
||||
|
||||
if (actualScopeToCheck == requiredAccessScope)
|
||||
if (actualScopeToCheck.hasEqualDeclContextWith(requiredAccessScope))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1472,7 +1464,7 @@ checkWitnessAccessibility(const DeclContext *&requiredAccessScope,
|
||||
*isSetter = true;
|
||||
|
||||
auto ASD = cast<AbstractStorageDecl>(witness);
|
||||
if (!ASD->isSetterAccessibleFrom(actualScopeToCheck))
|
||||
if (!ASD->isSetterAccessibleFrom(actualScopeToCheck.getDeclContext()))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1489,7 +1481,7 @@ checkWitnessAvailability(ValueDecl *requirement,
|
||||
}
|
||||
|
||||
RequirementCheck WitnessChecker::
|
||||
checkWitness(const DeclContext *requiredAccessScope,
|
||||
checkWitness(AccessScope requiredAccessScope,
|
||||
ValueDecl *requirement,
|
||||
RequirementMatch match) {
|
||||
if (!match.OptionalAdjustments.empty())
|
||||
@@ -2199,7 +2191,7 @@ void ConformanceChecker::recordTypeWitness(AssociatedTypeDecl *assocType,
|
||||
|
||||
if (typeDecl) {
|
||||
// Check access.
|
||||
const DeclContext *requiredAccessScope =
|
||||
AccessScope requiredAccessScope =
|
||||
Adoptee->getAnyNominal()->getFormalAccessScope(DC);
|
||||
bool isSetter = false;
|
||||
if (checkWitnessAccessibility(requiredAccessScope, assocType, typeDecl,
|
||||
@@ -2212,10 +2204,11 @@ void ConformanceChecker::recordTypeWitness(AssociatedTypeDecl *assocType,
|
||||
[DC, typeDecl, requiredAccessScope, assocType](
|
||||
TypeChecker &tc, NormalProtocolConformance *conformance) {
|
||||
Accessibility requiredAccess =
|
||||
accessibilityFromScopeForDiagnostics(requiredAccessScope);
|
||||
requiredAccessScope.requiredAccessibilityForDiagnostics();
|
||||
auto proto = conformance->getProtocol();
|
||||
auto protoAccessScope = proto->getFormalAccessScope(DC);
|
||||
bool protoForcesAccess =
|
||||
(requiredAccessScope == proto->getFormalAccessScope(DC));
|
||||
requiredAccessScope.hasEqualDeclContextWith(protoAccessScope);
|
||||
auto diagKind = protoForcesAccess
|
||||
? diag::type_witness_not_accessible_proto
|
||||
: diag::type_witness_not_accessible_type;
|
||||
@@ -2486,7 +2479,7 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
|
||||
});
|
||||
}
|
||||
|
||||
const DeclContext *nominalAccessScope =
|
||||
AccessScope nominalAccessScope =
|
||||
Adoptee->getAnyNominal()->getFormalAccessScope(DC);
|
||||
auto check = checkWitness(nominalAccessScope, requirement, best);
|
||||
|
||||
@@ -2501,12 +2494,13 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
|
||||
diagnoseOrDefer(requirement, false,
|
||||
[DC, witness, check, requirement](
|
||||
TypeChecker &tc, NormalProtocolConformance *conformance) {
|
||||
auto requiredAccessScope = check.RequiredAccessScope;
|
||||
Accessibility requiredAccess =
|
||||
accessibilityFromScopeForDiagnostics(check.RequiredAccessScope);
|
||||
|
||||
requiredAccessScope.requiredAccessibilityForDiagnostics();
|
||||
auto proto = conformance->getProtocol();
|
||||
auto protoAccessScope = proto->getFormalAccessScope(DC);
|
||||
bool protoForcesAccess =
|
||||
(check.RequiredAccessScope == proto->getFormalAccessScope(DC));
|
||||
requiredAccessScope.hasEqualDeclContextWith(protoAccessScope);
|
||||
auto diagKind = protoForcesAccess
|
||||
? diag::witness_not_accessible_proto
|
||||
: diag::witness_not_accessible_type;
|
||||
@@ -2517,6 +2511,7 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
|
||||
witness->getFullName(),
|
||||
isSetter,
|
||||
requiredAccess,
|
||||
protoAccessScope.accessibilityForDiagnostics(),
|
||||
proto->getName());
|
||||
fixItAccessibility(diag, witness, requiredAccess, isSetter);
|
||||
});
|
||||
@@ -5451,7 +5446,7 @@ DefaultWitnessChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
|
||||
|
||||
// Perform the same checks as conformance witness matching, but silently
|
||||
// ignore the candidate instead of diagnosing anything.
|
||||
auto check = checkWitness(/*access: public*/nullptr, requirement, best);
|
||||
auto check = checkWitness(AccessScope::getPublic(), requirement, best);
|
||||
if (check.Kind != CheckKind::Success)
|
||||
return ResolveWitnessResult::ExplicitFailed;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define TYPECHECKING_H
|
||||
|
||||
#include "swift/Sema/TypeCheckRequest.h"
|
||||
#include "swift/AST/AccessScope.h"
|
||||
#include "swift/AST/AST.h"
|
||||
#include "swift/AST/AnyFunctionRef.h"
|
||||
#include "swift/AST/Availability.h"
|
||||
@@ -490,7 +491,7 @@ public:
|
||||
/// during type checking.
|
||||
llvm::SetVector<NominalTypeDecl *> ValidatedTypes;
|
||||
|
||||
using TypeAccessScopeCacheMap = llvm::DenseMap<Type, const DeclContext *>;
|
||||
using TypeAccessScopeCacheMap = llvm::DenseMap<Type, AccessScope>;
|
||||
|
||||
/// Caches the outermost scope where a particular type can be used, relative
|
||||
/// to a particular file.
|
||||
|
||||
Reference in New Issue
Block a user