Sema: Warn on resilient uses of @_implementationOnly as deprecated

Report uses of `@_implementationOnly` in resilient modules as deprecated.
With a fixit to replace it with `internal` or delete it when imports
are internal by default.

Uses of `@_implementationOnly` in non-resilient modules is already reported
as being unsafe.
This commit is contained in:
Alexis Laferrière
2024-04-21 10:47:09 -07:00
parent f4d73275cb
commit ff797cfd66
4 changed files with 65 additions and 9 deletions

View File

@@ -586,8 +586,10 @@ UnboundImport::UnboundImport(ImportDecl *ID)
if (ID->getAttrs().hasAttribute<TestableAttr>())
import.options |= ImportFlags::Testable;
if (ID->getAttrs().hasAttribute<ImplementationOnlyAttr>())
if (auto attr = ID->getAttrs().getAttribute<ImplementationOnlyAttr>()) {
import.options |= ImportFlags::ImplementationOnly;
import.implementationOnlyRange = attr->Range;
}
import.accessLevel = ID->getAccessLevel();
if (auto attr = ID->getAttrs().getAttribute<AccessControlAttr>()) {
@@ -811,7 +813,21 @@ void UnboundImport::validateResilience(NullablePtr<ModuleDecl> topLevelModule,
// We exempt some imports using @_implementationOnly in a safe way from
// packages that cannot be resilient.
if (import.options.contains(ImportFlags::ImplementationOnly) &&
!SF.getParentModule()->isResilient() && topLevelModule &&
import.implementationOnlyRange.isValid()) {
if (SF.getParentModule()->isResilient()) {
// Encourage replacing `@_implementationOnly` with `internal import`.
if (ctx.LangOpts.hasFeature(Feature::InternalImportsByDefault)) {
auto inFlight =
ctx.Diags.diagnose(import.importLoc,
diag::implementation_only_deprecated_implicit);
inFlight.fixItRemove(import.implementationOnlyRange);
} else {
auto inFlight =
ctx.Diags.diagnose(import.importLoc,
diag::implementation_only_deprecated_explicit);
inFlight.fixItReplace(import.implementationOnlyRange, "internal");
}
} else if ( // Non-resilient
!(((targetName.str() == "CCryptoBoringSSL" ||
targetName.str() == "CCryptoBoringSSLShims") &&
(importerName.str() == "Crypto" ||
@@ -820,11 +836,13 @@ void UnboundImport::validateResilience(NullablePtr<ModuleDecl> topLevelModule,
((targetName.str() == "CNIOBoringSSL" ||
targetName.str() == "CNIOBoringSSLShims") &&
importerName.str() == "NIOSSL"))) {
ctx.Diags.diagnose(import.importLoc,
diag::implementation_only_requires_library_evolution,
importerName);
ctx.Diags.diagnose(import.importLoc,
diag::implementation_only_requires_library_evolution,
importerName);
}
}
// Report public imports of non-resilient modules from a resilient module.
if (import.options.contains(ImportFlags::ImplementationOnly) ||
import.accessLevel < AccessLevel::Public)
return;