Skip to content

Commit 38fbe1d

Browse files
committed
[Sema] Preserve information about access level on imports
1 parent 0889565 commit 38fbe1d

File tree

4 files changed

+57
-7
lines changed

4 files changed

+57
-7
lines changed

include/swift/AST/Decl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,12 @@ class ImportDecl final : public Decl,
13951395
/// the decls it references. Otherwise, returns an empty array.
13961396
ArrayRef<ValueDecl *> getDecls() const;
13971397

1398+
/// Access level of this import, either explicitly declared or implicit.
1399+
AccessLevel getAccessLevel() const;
1400+
1401+
/// Is the access level of this import implicit, aka a default import?
1402+
bool isAccessLevelImplicit() const;
1403+
13981404
const clang::Module *getClangModule() const {
13991405
return getClangNode().getClangModule();
14001406
}

include/swift/AST/Import.h

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -584,14 +584,24 @@ struct AttributedImport {
584584
/// attribute, this is the given access level.
585585
Optional<AccessLevel> docVisibility;
586586

587+
/// Access level limiting how imported types can be exported.
588+
AccessLevel accessLevel;
589+
590+
/// Location of the attribute that defined \c accessLevel. Also indicates
591+
/// if the access level was implicit or explicit.
592+
SourceLoc accessLevelLoc;
593+
587594
AttributedImport(ModuleInfo module, SourceLoc importLoc = SourceLoc(),
588595
ImportOptions options = ImportOptions(),
589596
StringRef filename = {}, ArrayRef<Identifier> spiGroups = {},
590597
SourceRange preconcurrencyRange = {},
591-
Optional<AccessLevel> docVisibility = None)
598+
Optional<AccessLevel> docVisibility = None,
599+
AccessLevel accessLevel = AccessLevel::Public,
600+
SourceLoc accessLevelLoc = SourceLoc())
592601
: module(module), importLoc(importLoc), options(options),
593602
sourceFileArg(filename), spiGroups(spiGroups),
594-
preconcurrencyRange(preconcurrencyRange), docVisibility(docVisibility) {
603+
preconcurrencyRange(preconcurrencyRange), docVisibility(docVisibility),
604+
accessLevel(accessLevel), accessLevelLoc(accessLevelLoc) {
595605
assert(!(options.contains(ImportFlags::Exported) &&
596606
options.contains(ImportFlags::ImplementationOnly)) ||
597607
options.contains(ImportFlags::Reserved));
@@ -601,15 +611,18 @@ struct AttributedImport {
601611
AttributedImport(ModuleInfo module, AttributedImport<OtherModuleInfo> other)
602612
: AttributedImport(module, other.importLoc, other.options,
603613
other.sourceFileArg, other.spiGroups,
604-
other.preconcurrencyRange, other.docVisibility) { }
614+
other.preconcurrencyRange, other.docVisibility,
615+
other.accessLevel, other.accessLevelLoc) { }
605616

606617
friend bool operator==(const AttributedImport<ModuleInfo> &lhs,
607618
const AttributedImport<ModuleInfo> &rhs) {
608619
return lhs.module == rhs.module &&
609620
lhs.options.toRaw() == rhs.options.toRaw() &&
610621
lhs.sourceFileArg == rhs.sourceFileArg &&
611622
lhs.spiGroups == rhs.spiGroups &&
612-
lhs.docVisibility == rhs.docVisibility;
623+
lhs.docVisibility == rhs.docVisibility &&
624+
lhs.accessLevel == rhs.accessLevel &&
625+
lhs.accessLevelLoc == rhs.accessLevelLoc;
613626
}
614627

615628
AttributedImport<ImportedModule> getLoaded(ModuleDecl *loadedModule) const {
@@ -761,14 +774,16 @@ struct DenseMapInfo<swift::AttributedImport<ModuleInfo>> {
761774
SourceLocDMI::getEmptyKey(),
762775
ImportOptionsDMI::getEmptyKey(),
763776
StringRefDMI::getEmptyKey(),
764-
{}, {}, None);
777+
{}, {}, None,
778+
swift::AccessLevel::Public, {});
765779
}
766780
static inline AttributedImport getTombstoneKey() {
767781
return AttributedImport(ModuleInfoDMI::getTombstoneKey(),
768782
SourceLocDMI::getEmptyKey(),
769783
ImportOptionsDMI::getTombstoneKey(),
770784
StringRefDMI::getTombstoneKey(),
771-
{}, {}, None);
785+
{}, {}, None,
786+
swift::AccessLevel::Public, {});
772787
}
773788
static inline unsigned getHashValue(const AttributedImport &import) {
774789
return detail::combineHashValue(
@@ -783,7 +798,9 @@ struct DenseMapInfo<swift::AttributedImport<ModuleInfo>> {
783798
ImportOptionsDMI::isEqual(a.options, b.options) &&
784799
StringRefDMI::isEqual(a.sourceFileArg, b.sourceFileArg) &&
785800
a.spiGroups == b.spiGroups &&
786-
a.docVisibility == b.docVisibility;
801+
a.docVisibility == b.docVisibility &&
802+
a.accessLevel == b.accessLevel &&
803+
a.accessLevelLoc == b.accessLevelLoc;
787804
}
788805
};
789806
}

lib/AST/Decl.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,28 @@ ArrayRef<ValueDecl *> ImportDecl::getDecls() const {
13431343
ScopedImportLookupRequest{mutableThis}, {});
13441344
}
13451345

1346+
AccessLevel ImportDecl::getAccessLevel() const {
1347+
if (auto attr = getAttrs().getAttribute<AccessControlAttr>()) {
1348+
return attr->getAccess();
1349+
}
1350+
1351+
auto &LangOpts = getASTContext().LangOpts;
1352+
if (LangOpts.isSwiftVersionAtLeast(6) &&
1353+
LangOpts.hasFeature(Feature::AccessLevelOnImport)) {
1354+
// Tentative Swift 6 mode where the default import is internal.
1355+
return AccessLevel::Internal;
1356+
} else {
1357+
return AccessLevel::Public;
1358+
}
1359+
}
1360+
1361+
bool ImportDecl::isAccessLevelImplicit() const {
1362+
if (auto attr = getAttrs().getAttribute<AccessControlAttr>()) {
1363+
return false;
1364+
}
1365+
return true;
1366+
}
1367+
13461368
void NominalTypeDecl::setConformanceLoader(LazyMemberLoader *lazyLoader,
13471369
uint64_t contextData) {
13481370
assert(!Bits.NominalTypeDecl.HasLazyConformances &&

lib/Sema/ImportResolution.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,11 @@ UnboundImport::UnboundImport(ImportDecl *ID)
543543
if (ID->getAttrs().hasAttribute<ImplementationOnlyAttr>())
544544
import.options |= ImportFlags::ImplementationOnly;
545545

546+
import.accessLevel = ID->getAccessLevel();
547+
if (auto attr = ID->getAttrs().getAttribute<AccessControlAttr>()) {
548+
import.accessLevelLoc = attr->getLocation();
549+
}
550+
546551
if (ID->getAttrs().hasAttribute<SPIOnlyAttr>())
547552
import.options |= ImportFlags::SPIOnly;
548553

0 commit comments

Comments
 (0)