Functions like `fatalError()` have overloads for Embedded Swift only that take
StaticString instead of String, since String is unavailable. Unfortunately,
many of these overloads create the opportunity for ambiguity in certain
contexts. The easiest way to avoid the ambiguities is to mark each of the
overloads taking `String` as `@_disfavoredOverload`. Another approach that
could work would be to remove the default arguments from the `String` variants
in Embedded Swift only, but that would create even more duplication of source
code so it doesn't seem worth it.
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.
- the previous docs for assertionFailure implies that it is a nonreturning function, which has always been wrong.
- the example usage previously given for assertionFailure was moved to preconditionFailure, where it is more appropriate.
Swift 5.7 added stronger index validation for `String`, so some illegal cases that previously triggered inconsistently diagnosed out of bounds accesses now result in reliable runtime errors. Similarly, attempts at applying an index originally vended by a UTF-8 string on a UTF-16 string now result in a reliable runtime error.
As is usually the case, new traps to the stdlib exposes code that contains previously undiagnosed / unreliably diagnosed coding issues.
Allow invalid code in binaries built with earlier versions of the stdlib to continue running with the 5.7 library by disabling some of the new traps based on the version of Swift the binary was built with.
In the case of an index encoding mismatch, allow transcoding of string storage regardless of the direction of the mismatch. (Previously we only allowed transcoding a UTF-8 string to UTF-16.)
rdar://93379333
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
The SIL generation for this builtin also changes: instead of generating the cond_fail instructions upfront, let the optimizer generate it, if the operand is a static string literal.
In worst case, if the second operand is not a static string literal, the Builtin.condfail is lowered at the end of the optimization pipeline with a default message: "unknown program error".
Inlinable and non-inlinable code can cause 5.1 code to intermix with
5.0 code on older OSes. Some (weak) invariants for 5.1 should only be
checked when the OS's code is 5.1 or later, which is the purpose of
_invariantCheck_5_1.
Applied to String.Index._isScalarAligned, which is a new bit
introduced in 5.1 from one of the reserved bits from 5.0. The bit is
set when the index is proven to be scalar aligned, and we want to
assert on this liberally in contexts where we expect it to be
so. However, older OSes might not set this bit when doing scalar
aligning, depending on exactly what got inlined where/when.
The SIL generation for this builtin also changes: instead of generating the cond_fail instructions upfront, let the optimizer generate it, if the operand is a static string literal.
In worst case, if the second operand is not a static string literal, the Builtin.condfail is lowered at the end of the optimization pipeline with a default message: "unknown program error".
LLVM r355981 changed various intrinsic functions, including expect,
to require immediate arguments. Swift's _branchHint function has an
expected value that is passed in as an argument, so that it cannot
use LLVM's expect intrinsic. The good news is that _branchHint is only
ever used with immediate arguments, so we can just move the intrinsic
into _fastPath and _slowPath and use those instead of _branchHint.
As was noted in the documentation, the _fastPath and _slowPath names are
confusing but we have passed the point where we can simply rename them.
We could add new names but would still need to keep the old ones around
for binary compatibility, and it is not clear that it is worth the
trouble. I have removed that note from the documentation.
* 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
* Make _sanityCheck internal
* Make _debugPrecondition internal
* Make Optional._unsafelyUnwrappedUnchecked internal.
* Make _precondition internal
* Switch Foundation _sanityChecks to assertions
* Update file check tests
* Remove one more _debugPrecondition
* Update Optimization-with-check tests
* 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.