From 464c37a5bb9df5e267da6952eb900693b26c9a14 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 6 Jun 2025 17:29:12 -0700 Subject: [PATCH] AST: Add a warning group for @_implementationOnly deprecation diagnostics. This allows developers to control the level of these diagnostics. Resolves rdar://152735425. --- include/swift/AST/DiagnosticGroups.def | 1 + include/swift/AST/DiagnosticsSema.def | 6 +++-- .../Sema/implementation-only-deprecated.swift | 6 +++++ ...ation-only-import-from-non-resilient.swift | 2 ++ .../implementation-only-deprecated.md | 23 +++++++++++++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 userdocs/diagnostics/implementation-only-deprecated.md diff --git a/include/swift/AST/DiagnosticGroups.def b/include/swift/AST/DiagnosticGroups.def index 9a84cef6fccc0..84c68535c5ad9 100644 --- a/include/swift/AST/DiagnosticGroups.def +++ b/include/swift/AST/DiagnosticGroups.def @@ -48,6 +48,7 @@ GROUP(DynamicCallable, "dynamic-callable-requirements") GROUP(ErrorInFutureSwiftVersion, "error-in-future-swift-version") GROUP(ExistentialAny, "existential-any") GROUP(ExistentialMemberAccess, "existential-member-access-limitations") +GROUP(ImplementationOnlyDeprecated, "implementation-only-deprecated") GROUP(IsolatedConformances, "isolated-conformances") GROUP(MemberImportVisibility, "member-import-visibility") GROUP(MissingModuleOnKnownPaths, "missing-module-on-known-paths") diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 02889d855de7f..51bf678def39e 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1220,11 +1220,13 @@ ERROR(module_not_compiled_with_library_evolution,none, "module %0 was not compiled with library evolution support; " "using it means binary compatibility for %1 can't be guaranteed", (Identifier, Identifier)) -WARNING(implementation_only_requires_library_evolution,none, +GROUPED_WARNING(implementation_only_requires_library_evolution, + ImplementationOnlyDeprecated,none, "using '@_implementationOnly' without enabling library evolution " "for %0 may lead to instability during execution", (Identifier)) -WARNING(implementation_only_deprecated,none, +GROUPED_WARNING(implementation_only_deprecated, + ImplementationOnlyDeprecated,none, "'@_implementationOnly' is deprecated, use 'internal import' instead", ()) diff --git a/test/Sema/implementation-only-deprecated.swift b/test/Sema/implementation-only-deprecated.swift index e60d58c3eef8f..6fe92f81f1387 100644 --- a/test/Sema/implementation-only-deprecated.swift +++ b/test/Sema/implementation-only-deprecated.swift @@ -11,6 +11,12 @@ // RUN: -enable-library-evolution -swift-version 5 \ // RUN: -enable-upcoming-feature InternalImportsByDefault \ // RUN: -verify +// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \ +// RUN: -enable-library-evolution -swift-version 5 \ +// RUN: -enable-upcoming-feature InternalImportsByDefault \ +// RUN: -warnings-as-errors -Wwarning ImplementationOnlyDeprecated \ +// RUN: -verify + // REQUIRES: swift_feature_InternalImportsByDefault diff --git a/test/Sema/implementation-only-import-from-non-resilient.swift b/test/Sema/implementation-only-import-from-non-resilient.swift index e8561c6097592..9962eaa61be1d 100644 --- a/test/Sema/implementation-only-import-from-non-resilient.swift +++ b/test/Sema/implementation-only-import-from-non-resilient.swift @@ -9,6 +9,8 @@ /// Build a client with and without library-evolution. // RUN: %target-swift-frontend -typecheck %t/client-non-resilient.swift -I %t -verify +// RUN: %target-swift-frontend -typecheck %t/client-non-resilient.swift -I %t -verify \ +// RUN: -warnings-as-errors -Wwarning ImplementationOnlyDeprecated // RUN: %target-swift-frontend -typecheck %t/client-resilient.swift -I %t -verify \ // RUN: -enable-library-evolution -swift-version 5 diff --git a/userdocs/diagnostics/implementation-only-deprecated.md b/userdocs/diagnostics/implementation-only-deprecated.md new file mode 100644 index 0000000000000..d93c65c771f1e --- /dev/null +++ b/userdocs/diagnostics/implementation-only-deprecated.md @@ -0,0 +1,23 @@ +# Deprecated implementation-only imports (ImplementationOnlyDeprecated) + +Warnings that identify `import` declarations with the `@_implementationOnly` attribute. + +## Overview + +When applied to `import` declarations, the compiler-internal attribute `@_implementationOnly` attempts prevents declarations from the imported module from being exposed in the ABI or public interface of the dependent module. This attribute became deprecated when support for access levels on `import` declarations was introduced with [SE-0409]. + +One reason `@_implementationOnly import` is deprecated is that it is unsafe when used in modules that are built _without_ [library evolution] enabled. For example, suppose the following code were part of a library named `Foo`: + +```swift +// Library `Foo` +@_implementationOnly import ImplementationDetail + +public struct Bar { + internal var x: Baz // defined in ImplementationDetail +} +``` + +If `Foo` is not compiled with library evolution, then the memory layout of values of `Bar` must be known at compile time in clients of `Foo`. However, the `@_implementationOnly import` of `ImplementationDetail` prevents clients from being able to look up `Baz` which is a type that contributes to the layout of `Foo`. As a result, the layout of `Foo` will be miscalculated resulting in undefined behavior. + +[SE-0409]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md +[library evolution]: https://www.swift.org/blog/library-evolution/