Add the module-format machinery that lets a Swift library record the
physical layout of hidden types (currently limited to C types imported via internal bridging header).
into binary modules, so downstream consumers can pull the layouts of these hidden types without
loading the internal dependency.
To test this, this change also added a frontend action to print hidden types' layouts
from both the module under compilation and all the modules being imported.
When hiding dependencies in embedded mode there are special rules for
classes. Classes properties can safely reference the hidden
dependencies, however code referencing these properties must be marked
`@export(interface)`.
We previously added a check to report implicit code without the requited
`@export(interface)`. However explicit references from user written code
wasn't fully checked, only explicit references to the imported type or
the type's services would be reported, not references to the property
itself.
We patch that hole here by introducing new requirements and a new layer
of check specific to class properies in embedded mode.
---
Class properties referencing a hidden dependency must be marked
`@_implementationOnly`. This adds on top of the requirement for the
class itself to have an explicit `@export(interface) deinit`.
This allows to report references from user written code using existing
diagnostics.
Even without library-evolution, we allow references to hidden
dependencies from class properties as long as the class is not marked
open. In embedded, references from functions are only accepted when
marked `@export(interface)` as it can't be inlined in clients.
Combine both requirements to protect the implicitly generated destructor
as well. Add a requirement for classes with such a property to
explicitly declare a `@export(interface)` deinit. Otherwise that deinit
may be inlined in clients and cause a deserialization failure.
rdar://170855491
This one is specific. Allow extensions to define public members to
package types implicitly exporting their memory layout when imported
non-publicly.
Enabling exportability checks for non-library-evolution by default as a
warning triggered marking such types as implicitly exported to clients.
This in turn enabled erroring on the extensions in clients when imported
non-publicly. This error would be source breaking and shouldn't be
required in such a context. We may even consider lifting this
restriction entierly, even for public types imported non-public.
Centralize the logic downgrading diagnostics to warning for newly
introduced exportability checks along with the one silencing the errors.
Update client sites to the new API and to uniformly apply the downgrade
to warning behavior.
Diagnostics about typealiases and conformances are now properly
downgraded to warnings if not opt-in.
Always enable checking for references to `@_implementationOnly` imports
even without library-evolution enabled but downgrade errors to warnings
by default. Clients should enable them as errors by adopting
`CheckImplementationOnly`.
Some access control holes were unconditionally downgraded to warnings, and
others were conditional on Swift 6 language mode. Let's hang them off an
upcoming feature instead.
In non-library-evolution mode, gated behind the CheckImplementationOnly
feature flag, report references to structs marked with
`@_implementationOnly` from a fragile context. Preventing references
from inlinable functions and structs not marked `@_implementationOnly`.
Embedded mode use only binary swiftmodules for distribution, SPI will
always be visible. We can allow implicitly always-emit-into-client
function bodies from the embedded mode to references SPIs.
rdar://163519075
Access-level on imports don't hide the dependency in
non-library-evolution mode. We can allow implicitly
always-emit-into-client function bodies from embedded mode
to references the dependencies.
rdar://163519185
Replace the `here` part of the generic exportability diagnostic for
variables with: `in a property declaration marked public or in a
'@frozen' or '@usableFromInline' context`.
The full diagnostic now looks like:
```
error: cannot use struct 'ImportedType' in a property declaration marked
public or in a '@frozen' or '@usableFromInline' context;
'HiddenDependency' has been imported as implementation-only
```
This should be improved further to support implicitly exported memory
layouts in non-library-evolution and embedded.
Update logic finding the import to point in diagnostics to avoid relying
on the implicit import of the top-level module when importing a clang
submodule. A recent change avoids duplicating the implicit imports and
broke the old logic.
rdar://162151660
Consider functions in embedded mode to be fragile unless marked with
`@_neverEmitIntoClient`. Basically treating them as if they were
`@_alwaysEmitIntoClient` by default. A fragile function cannot reference
restricted imports such as `@_implementationOnly`, `internal import`,
etc.
We consider them as fragile only for type-checking, at the SIL level
they remain treated as normal functions like before. This allows the
later optimization to work as expected. We may want to likely align both
ends of the compiler once this is properly supported in sema.
This is enabled only in embedded. Fragile functions in library-evolution
are marked with attributes and are already checked. We do not need this
is non-embedded non-library-evolution as CMO handles inlining and
already takes into consideration `@_implementationOnly` imports.
Note: We'll need a similar check for memory layouts exposed to clients.
We can still see compiler crashes and miscompiles in this scenario. This
will apply to both embedded and non-library-evolution modes. That will
likely need to extend the `@_neverEmitIntoClient` attribute and may
require a staged deployment.
rdar://161365361
Declarations that are unavailable at runtime because of an `@available`
attribute referencing a custom domain that was imported `@_spiOnly` should be
hidden from public swiftinterface files in `-library-level=api` modules. For
remaining declarations that do get printed in the public swiftinterface, skip
printing any `@available` attribute that refers to the domains from those
`@_spiOnly` dependencies. This allows API developers to control declaration
visibility using availability defined by another module.
Resolves rdar://156512028.
This allows diagnostics to be more precise and will also support logic that
allows for special cases for `@available` attributes in exportability checking.
Also fixes a bug where the exportability of `@available` attributes attached to
extensions were diagnosed twice for slightly differing reasons.
To reduce code duplication, implement a convenience version of
`swift::recordRequiredImportAccessLevelForDecl()` that handles the common case
of recording required import access for a reference to a `ValueDecl`.
NFC.
The migration to `MemberImportVisibility` can be performed mechanically by
adding missing import declarations, so offer automatic migration for the
feature.
Resolves rdar://151931597.
Previously, the constraint solver would first attempt member lookup that
excluded members from transitively imported modules. If there were no viable
candidates, it would perform a second lookup that included the previously
excluded members, treating any candidates as unviable. This meant that if the
member reference did resolve to one of the unviable candidates the resulting
AST would be broken, which could cause unwanted knock-on diagnostics.
Now, members from transitively imported modules are always returned in the set
of viable candidates. However, scoring will always prioritize candidates from
directly imported modules over members from transitive imports. This solves the
ambiguities that `MemberImportVisibility` is designed to prevent. If the only
viable candidates are from transitively imported modules, though, then the
reference will be resolved successfully and diagnosed later in
`MiscDiagnostics.cpp`. The resulting AST will not contain any errors, which
ensures that necessary access levels can be computed correctly for the imports
suggested by `MemberImportVisibility` fix-its.
Resolves rdar://126637855.
When `MemberImportVisibility` is enabled, if the import that would bring a
member declaration into scope is missing it is diagnosed as an error. The
existing resilience diagnostics that would also diagnose the same problem in
contexts that are visible in the module interface are therefore superflous with
the feature enabled.
In anticipation of adding a new kind of missing import record to `SourceFile`,
clarify the purpose of the existing "missing imports" record with more specific
naming and documentation.
In anticipation of reusing minimum access level information for diagnostics
related to the `MemberImportVisibility` feature, refactor the way the type
checker tracks the modules which must be imported publicly. Recording minimum
access levels is no longer restricted to modules that are already imported in a
source file since `MemberImportVisibility` diagnostics will need this
information when emitting fix-its for modules that are not already imported.
Unblocks rdar://126637855.