It should no longer be necessary to provide an `@_alwaysEmitIntoClient` version
of `_diagnoseUnavailableCodeReached()`. This workaround was originally added to
provide compatibility with projects that were misconfigured to compile against
a newer stdlib but link against an older one.
Resolves rdar://119892482.
This change introduces a new compilation target platform to the Swift compiler - visionOS.
- Changes to the compiler build infrastrucuture to support building compiler-adjacent artifacts and test suites for the new target.
- Addition of the new platform kind definition.
- Support for the new platform in language constructs such as compile-time availability annotations or runtime OS version queries.
- Utilities to read out Darwin platform SDK info containing platform mapping data.
- Utilities to support re-mapping availability annotations from iOS to visionOS (e.g. 'updateIntroducedPlatformForFallback', 'updateDeprecatedPlatformForFallback', 'updateObsoletedPlatformForFallback').
- Additional tests exercising platform-specific availability handling and availability re-mapping fallback code-path.
- Changes to existing test suite to accomodate the new platform.
The `_diagnoseUnavailableCodeReached()` function was introduced in the Swift
5.9 standard library and employs `@backDeployed` to support compilation of
binaries that target OS releases aligned with earlier Swift releases.
Unfortunately, though, this backdeployment strategy doesn't work well for some
unusual build environments. Specifically, in some configurations code may be
built with a compiler from a recent Swift toolchain and then linked against the
dylibs in an older toolchain. When linking against the older dylibs, the
`_diagnoseUnavailableCodeReached()` function does not exist but the
`@backDeployed` thunks emitted into the binary reference that function and
therefore linking fails.
The idea of building with one toolchain and then linking to the dylibs in a
different, older toolchain is extremely dubious. However, it exists and for now
we need to support it. This PR introduces an alternative
`_diagnoseUnavailableCodeReached()` function that is annotated with
`@_alwaysEmitIntoClient`. Calls to the AEIC variant are now emitted by the
compiler when the deployment target is before Swift 5.9.
Once these unusual build environments upgrade and start linking against a Swift
5.9 toolchain or later we can revert all of this.
Resolves rdar://119046537
This isn't a "complete" port of the standard library for embedded Swift, but
something that should serve as a starting point for further iterations on the
stdlib.
- General CMake logic for building a library as ".swiftmodule only" (ONLY_SWIFTMODULE).
- CMake logic in stdlib/public/core/CMakeLists.txt to start building the embedded stdlib for a handful of hardcoded target triples.
- Lots of annotations throughout the standard library to make types, functions, protocols unavailable in embedded Swift (@_unavailableInEmbedded).
- Mainly this is about stdlib functionality that relies on existentials, type erasure, metatypes, reflection, string interpolations.
- We rely on function body removal of unavailable functions to eliminate the actual problematic SIL code (existentials).
- Many .swift files are not included in the compilation of embedded stdlib at all, to simplify the scope of the annotations.
- EmbeddedStubs.swift is used to stub out (as unavailable and fatalError'd) the missing functionality.
When `-unavailable-decl-optimization=stub` is specified, insert a call to
`_diagnoseUnavailableCodeReached()` at the beginning of the function to cause
it to trap if executed at run time.
Part of rdar://107388493
It is sometimes desirable to always perform (relatively cheap) runtime checks in the stdlib, even in configurations where we’d otherwise elide them.
Add a build-time option to the standard library (`SWIFT_STDLIB_ENABLE_DEBUG_PRECONDITIONS_IN_RELEASE`) to make `_debugPrecondition` work like `_precondition`, i.e., to enable it even in ReleaseAssert configurations.
This option will keep additional checks in the following places, even in release mode:
- Range checking in the subscript operations of all unsafe buffer pointer types.
- Nil checking in `Optional.unsafelyUnwrapped`
- Additional argument validation in `Unsafe[Mutable][Raw]Pointer`’s initialization/assignment/move/deinitialization/binding methods
- Protection against initializing `Unsafe[Mutable][Raw]Pointer` with invalid data. (Negative count, nil pointer for non-empty buffer, etc)
- Checks against index overflow in `Unsafe[Mutable]BufferPointer`’s index manipulation methods
- Checks against backward ranges in `Range(uncheckedBounds:)`, `ClosedRange(uncheckedBounds:)`
- Dynamic isa check in `unsafeDowncast(_:to:)`
- Additional [cheap] checks to catch invalid Sequence/Collection implementations in `Array.init<S:Sequence>(_:)` and elsewhere
- Checks against `Character` containing multiple grapheme clusters
- More index validation in `EmptyCollection`
(Additional cases will get added as the stdlib evolves.)
The option is disabled by default — so `_debugPrecondition`s continue to be disabled in optimized builds, even after this change lands, unless someone specifically builds a stdlib that enables them.
rdar://89118585
For using the improved condfail messages in the stdlib, we need a function, like precondition(), just taking a StaticString instead of a String for the message.
The existing (underscored) _precondition is a perfect fit for this, except that it's not printing the location info in debug builds.
This change makes _precondition() equivalent to precondition, just taking a StaticString as argument.
The other alternative would be to add another variant of precondition, just taking a StaticString. But we already have so many failure functions in Assert.swift, so adapting an existing one seems to be a better solution.
This effectively undos a change from 5 years ago which intentionally removed the location info from _precondition (rdar://problem/16958193). But this was at a time where swift was not open source yet. So I think today it's okay to always add location information, even if it's from inside the stdlib. It can be even very useful for expert users for looking up the location the stdlib source.
For using the improved condfail messages in the stdlib, we need a function, like precondition(), just taking a StaticString instead of a String for the message.
The existing (underscored) _precondition is a perfect fit for this, except that it's not printing the location info in debug builds.
This change makes _precondition() equivalent to precondition, just taking a StaticString as argument.
The other alternative would be to add another variant of precondition, just taking a StaticString. But we already have so many failure functions in Assert.swift, so adapting an existing one seems to be a better solution.
This effectively undos a change from 5 years ago which intentionally removed the location info from _precondition (rdar://problem/16958193). But this was at a time where swift was not open source yet. So I think today it's okay to always add location information, even if it's from inside the stdlib. It can be even very useful for expert users for looking up the location the stdlib source.
* [SILOptimizer] Don't diagnose infinite recursion if a branch terminates the program
This patch augments the infinite recursion checker to not warn if a
branch terminates, but still warns if a branch calls into something with
@_semantics("programtermination_point"). This way, calling fatalError
doesn't disqualify you for the diagnostic, but calling exit does.
This also removes the warning workaround in the standard library, and
annotates the internal _assertionFailure functions as
programtermination_points, so they get this treatment too.
* Fix formatting in SILInstructions.cpp
* Re-add missing test
This patch augments the infinite recursion checker to not warn if a
branch terminates, but still warns if a branch calls into something with
`@_semantics("arc.programtermination_point")`. This way, calling `fatalError`
doesn't disqualify you for the diagnostic, but calling `exit` does.
This also removes the warning workaround in the standard library, and
annotates the internal _assertionFailure functions as
`programtermination_point`s, so they get this treatment too.
Introduce an inner function that breaks the infinite recursion check, silencing this warning:
```
swift/stdlib/public/core/AssertCommon.swift:166:15: warning: all paths through this function will call itself
internal func _fatalErrorMessage(
^
```
* Removing FIXME from methods also marked always/never
* Unavailable/deprecated things don't need inlining
* Trivial implementations
* Enum namespaces
* Unsafe performance of opaque/raw pointer
* Dump doesn't need to be fast
* Error paths shouldn't require inlining
* Consistency with surrounding code
* Lazy performance needs specialization
Builds on 36eae9d4f6 to emit a message instead of just trapping
when a switch over a non-frozen enum ends up not matching anything.
If the enum is known to be an @objc enum, the message is
unexpected enum case 'MyEnum(rawValue: -42)'
and if it's anything else (a Swift enum, a tuple containing enums,
whatever), it's a more opaque
unexpected enum case while switching on value of type 'MyEnum'
The reason for this is to avoid calling String(describing:) or
String(reflecting:) an arbitrary value when the enum might conform to
CustomStringConvertible and therefore /itself/ have a switch that's
going to fall off the end. By handling plain @objc enums (using a
bitcast), we've at least covered the 90% case.
rdar://problem/37728359
* Unify the capitalization across all user-visible error messages (fatal errors, assertion failures, precondition failures) produced by the runtime, standard library and the compiler.
* Update some more tests to the new expectations.