Skip to content

Commit 9a73306

Browse files
authored
Merge pull request #73203 from xymus/access-level-import-diags-6.0
[6.0] Sema: Improve warnings and notes related to access-level on imports
2 parents 60b453c + 8f4b1be commit 9a73306

26 files changed

+326
-57
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,9 @@ WARNING(implementation_only_requires_library_evolution,none,
11641164
"using '@_implementationOnly' without enabling library evolution "
11651165
"for %0 may lead to instability during execution",
11661166
(Identifier))
1167+
WARNING(implementation_only_deprecated,none,
1168+
"'@_implementationOnly' is deprecated, use 'internal import' instead",
1169+
())
11671170

11681171
ERROR(module_allowable_client_violation,none,
11691172
"module %0 doesn't allow importation from module %1",
@@ -2501,6 +2504,11 @@ NOTE(decl_import_via_here,none,
25012504
"'%select{private|fileprivate|internal|package|%ERROR|%ERROR}1' "
25022505
"from %2 here",
25032506
(const Decl *, AccessLevel, const ModuleDecl*))
2507+
NOTE(decl_import_via_local,none,
2508+
"%kind0 is imported by this file as "
2509+
"'%select{private|fileprivate|internal|package|%ERROR|%ERROR}1' "
2510+
"from %2",
2511+
(const Decl *, AccessLevel, const ModuleDecl*))
25042512

25052513
// Opaque return types
25062514
ERROR(opaque_type_invalid_constraint,none,
@@ -3678,6 +3686,10 @@ ERROR(inconsistent_implicit_access_level_on_import,none,
36783686
"ambiguous implicit access level for import of %0; it is imported as "
36793687
"'%select{private|fileprivate|internal|package|public|%error}1' elsewhere",
36803688
(Identifier, AccessLevel))
3689+
NOTE(inconsistent_implicit_access_level_on_import_silence,none,
3690+
"silence these warnings by adopting the upcoming feature "
3691+
"'InternalImportsByDefault'",
3692+
())
36813693
NOTE(inconsistent_implicit_access_level_on_import_here,none,
36823694
"imported "
36833695
"'%select{private|fileprivate|internal|package|public|%error}0' here",

include/swift/AST/Import.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,17 +592,22 @@ struct AttributedImport {
592592
/// if the access level was implicit or explicit.
593593
SourceRange accessLevelRange;
594594

595+
/// Location of the `@_implementationOnly` attribute if set.
596+
SourceRange implementationOnlyRange;
597+
595598
AttributedImport(ModuleInfo module, SourceLoc importLoc = SourceLoc(),
596599
ImportOptions options = ImportOptions(),
597600
StringRef filename = {}, ArrayRef<Identifier> spiGroups = {},
598601
SourceRange preconcurrencyRange = {},
599602
std::optional<AccessLevel> docVisibility = std::nullopt,
600603
AccessLevel accessLevel = AccessLevel::Public,
601-
SourceRange accessLevelRange = SourceRange())
604+
SourceRange accessLevelRange = SourceRange(),
605+
SourceRange implementationOnlyRange = SourceRange())
602606
: module(module), importLoc(importLoc), options(options),
603607
sourceFileArg(filename), spiGroups(spiGroups),
604608
preconcurrencyRange(preconcurrencyRange), docVisibility(docVisibility),
605-
accessLevel(accessLevel), accessLevelRange(accessLevelRange) {
609+
accessLevel(accessLevel), accessLevelRange(accessLevelRange),
610+
implementationOnlyRange(implementationOnlyRange) {
606611
assert(!(options.contains(ImportFlags::Exported) &&
607612
options.contains(ImportFlags::ImplementationOnly)) ||
608613
options.contains(ImportFlags::Reserved));
@@ -613,7 +618,8 @@ struct AttributedImport {
613618
: AttributedImport(module, other.importLoc, other.options,
614619
other.sourceFileArg, other.spiGroups,
615620
other.preconcurrencyRange, other.docVisibility,
616-
other.accessLevel, other.accessLevelRange) { }
621+
other.accessLevel, other.accessLevelRange,
622+
other.implementationOnlyRange) { }
617623

618624
friend bool operator==(const AttributedImport<ModuleInfo> &lhs,
619625
const AttributedImport<ModuleInfo> &rhs) {
@@ -623,7 +629,8 @@ struct AttributedImport {
623629
lhs.spiGroups == rhs.spiGroups &&
624630
lhs.docVisibility == rhs.docVisibility &&
625631
lhs.accessLevel == rhs.accessLevel &&
626-
lhs.accessLevelRange == rhs.accessLevelRange;
632+
lhs.accessLevelRange == rhs.accessLevelRange &&
633+
lhs.implementationOnlyRange == rhs.implementationOnlyRange;
627634
}
628635

629636
AttributedImport<ImportedModule> getLoaded(ModuleDecl *loadedModule) const {

lib/Sema/ImportResolution.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,10 @@ UnboundImport::UnboundImport(ImportDecl *ID)
577577
if (ID->getAttrs().hasAttribute<TestableAttr>())
578578
import.options |= ImportFlags::Testable;
579579

580-
if (ID->getAttrs().hasAttribute<ImplementationOnlyAttr>())
580+
if (auto attr = ID->getAttrs().getAttribute<ImplementationOnlyAttr>()) {
581581
import.options |= ImportFlags::ImplementationOnly;
582+
import.implementationOnlyRange = attr->Range;
583+
}
582584

583585
import.accessLevel = ID->getAccessLevel();
584586
if (auto attr = ID->getAttrs().getAttribute<AccessControlAttr>()) {
@@ -802,7 +804,14 @@ void UnboundImport::validateResilience(NullablePtr<ModuleDecl> topLevelModule,
802804
// We exempt some imports using @_implementationOnly in a safe way from
803805
// packages that cannot be resilient.
804806
if (import.options.contains(ImportFlags::ImplementationOnly) &&
805-
!SF.getParentModule()->isResilient() && topLevelModule &&
807+
import.implementationOnlyRange.isValid()) {
808+
if (SF.getParentModule()->isResilient()) {
809+
// Encourage replacing `@_implementationOnly` with `internal import`.
810+
auto inFlight =
811+
ctx.Diags.diagnose(import.importLoc,
812+
diag::implementation_only_deprecated);
813+
inFlight.fixItReplace(import.implementationOnlyRange, "internal");
814+
} else if ( // Non-resilient
806815
!(((targetName.str() == "CCryptoBoringSSL" ||
807816
targetName.str() == "CCryptoBoringSSLShims") &&
808817
(importerName.str() == "Crypto" ||
@@ -811,11 +820,13 @@ void UnboundImport::validateResilience(NullablePtr<ModuleDecl> topLevelModule,
811820
((targetName.str() == "CNIOBoringSSL" ||
812821
targetName.str() == "CNIOBoringSSLShims") &&
813822
importerName.str() == "NIOSSL"))) {
814-
ctx.Diags.diagnose(import.importLoc,
815-
diag::implementation_only_requires_library_evolution,
816-
importerName);
823+
ctx.Diags.diagnose(import.importLoc,
824+
diag::implementation_only_requires_library_evolution,
825+
importerName);
826+
}
817827
}
818828

829+
// Report public imports of non-resilient modules from a resilient module.
819830
if (import.options.contains(ImportFlags::ImplementationOnly) ||
820831
import.accessLevel < AccessLevel::Public)
821832
return;
@@ -1066,11 +1077,16 @@ CheckInconsistentAccessLevelOnImport::evaluate(
10661077
auto &diags = mod->getDiags();
10671078
{
10681079
InFlightDiagnostic error =
1069-
diags.diagnose(implicitImport, diag::inconsistent_implicit_access_level_on_import,
1070-
implicitImport->getModule()->getName(), otherAccessLevel);
1080+
diags.diagnose(implicitImport,
1081+
diag::inconsistent_implicit_access_level_on_import,
1082+
implicitImport->getModule()->getName(),
1083+
otherAccessLevel);
10711084
error.fixItInsert(implicitImport->getStartLoc(),
10721085
diag::inconsistent_implicit_access_level_on_import_fixit,
10731086
otherAccessLevel);
1087+
error.flush();
1088+
diags.diagnose(implicitImport,
1089+
diag::inconsistent_implicit_access_level_on_import_silence);
10741090
}
10751091

10761092
SourceLoc accessLevelLoc = otherImport->getStartLoc();

0 commit comments

Comments
 (0)