When the stdlib says not to check, it’s a good idea to actually not have any checking, so that we leave existing code paths unchanged. (And because we do trust that the stdlib is responsible about such things.)
`Slice` does not technically guarantee that its indices are valid in its base, so these initializers accidentally allowed the creation of obviously out-of-bounds buffers.
Unchecked APIs must still perform checks in debug builds to ensure that invariants aren’t violated.
(I.e., these aren’t a license to perform invalid operations — they just let us get rid of the checks when we know for sure they are unnecessary.)
Every other Unsafe(Mutable)BufferPointer precondition in this file is debug-mode only.
This information is already part of the documentation for this function, and it's really hard to get rid of these branches and traps otherwise.
* Partially revert Float16 availability changes
Specifically, when building for macOS/x86_64, use the old availability annotation instead of marking Float16 unconditionally unavailable to give downstream clients a window to adjust their own annotations.
While the existing _forEachField in ReflectionMirror.swift
already gives the offsets and types for each field, this isn't
enough information to construct a keypath for that field in
order to modify it.
For reference, this should be sufficent to implement the features
described here: (https://forums.swift.org/t/storedpropertyiterable/19218/62)
purely at runtime without any derived conformances for many types.
Note: Since there isn't enough reflection information for
`.mutatingGetSet` fields, this means that we're not able to support
reflecting certain types of fields (functions, nonfinal class fields,
etc). Whether this is an error or not is controlled by the `.ignoreUnknown`
option.
UnsafeRawBufferPointer was not made self-slicing, but is instead sliced
by Slice<UnsafeRawBufferPointer>. When working with
UnsafeRawBufferPointer objects it is quite common to want to transform
back into the underlying collection, which is why the
UnsafeRawBufferPointer provides a constructor from its subsequence:
UnsafeRawBufferPointer.init(rebasing:).
Unfortunately for an initializer on this extremely low-level type, this
initializer is surprisingly expensive. When disassembled on Linux it
emits 7 separate traps and 11 branches. This relative heft means this
method often gets outlined, which is a shame, as several of the branches
could often be eliminated due to checks elsewhere in functions where
this initializer is used.
Almost all of these branches and almost all of the traps are
unnecessary. We can remove them by noting that it is impossible to
construct a Slice whose endIndex is earlier than its startIndex. All
Slice inits are constructed with bounds expressed as Range, and Range
enforces ordering on its endpoints.
For this reason, we can do unchecked arithmetic on the start and end
index of the slice, and remove 5 traps in one fell swoop. This greatly
cheapens the cost of the initializer, improving its odds of being
inlined and having even more of its branches optimised away.
For what it's worth, I also considered trying to remove the last two
preconditions. Unfortunately I concluded I couldn't confidently do that.
I wanted to remove them based on the premise that a valid Slice must
have indices that were in-bounds for its parent Collection, and so we
could safely assume that if the parent base address was nil the count
would have to be zero, and that adding start index to the base address
would definitely not overflow. However, the existence of the
Slice.init(base:bounds:) constructor led me to be a bit suspicions of
removing those checks. Given that
UnsafeRawBufferPointer.init(start:count:) enforces those invariants, I
decided it was safest for us to continue to do that.
Due to an unstable (and undesirable) calling convention in the LLVM layer for x86, I had previously marked Float16 unconditionally unavailable on macOS. My hope was that Intel would stabilize the calling convention and we could make it available on both macOS platforms at the same time. Unfortunately, that hasn't happened, and we want to make the type available for macOS/arm users.
So, I am making the availability mirror Float80--the type will be unavailable for macOS on x86_64, and available on all other platforms (the other x86 platforms don't have a binary-stability guarantee to worry about). This isn't ideal. In particular, if/when the calling conventions for Float16 stabilize in LLVM, we would want to make the type available, but it would then have _different_ availability for different architectures of macOS, which the current availability system is not well-equipped to handle (it's possible, but not very ergonomic). Nonetheless, this seems like the best option.
The good news is that because the full API is already built in Swift (and simply marked unavailable), we can simply add macOS 11.0 availability for these API and it will work.
The mutating collection subscript for discontiguous slices assigns to the wrong group
of indices. This fixes the behavior and adds test coverage.
rdar://problem/70690643
Call through to swift_setAtReferenceWritableKeyPath in that case. This fixes an assertion failure (or worse) when upcasting a ReferenceWritableKeyPath and then using subscript(keyPath:) to write a value with it.
rdar://problem/70609888
This is only relevant for assert builds of the library.
Fixes an undefined symbol error if an executable, compiled with an assert build of the stdlib, is back deployed on a platform which does not support lazy symbol binding.
rdar://problem/71201102
Don't complain if the empty array buffer singleton is set to mutable.
This can happen if reserveCapacity is called with a 0-capacity for an empty array.
In this case the resulting array is still the empty array singleton.
For the compiler, it's safe to treat the empty array singleton as "mutable", because there is never anything written to an array with zero capacity:
all mutating array operations do any form of capacity/size > 0 check in addition to the uniqueness check.
Unfortunately the empty array singleton sometimes needs such special handling with is not obvious (not to say hacky).
This wrong check only fired in very specific optimization scenarios, where the inliner and the COW optimizations must play together in a certain way.
I could not find an isolated test case for this problem.
rdar://problem/71107908
to check for improperly nested '@_semantic' functions.
Add a missing @_semantics("array.init") in ArraySlice found by the
diagnostic.
Distinguish between array.init and array.init.empty.
Categorize the types of semantic functions by how they affect the
inliner and pass pipeline, and centralize this logic in
PerformanceInlinerUtils. The ultimate goal is to prevent inlining of
"Fundamental" @_semantics calls and @_effects calls until the late
pipeline where we can safely discard semantics. However, that requires
significant pipeline changes.
In the meantime, this change prevents the situation from getting worse
and makes the intention clear. However, it has no significant effect
on the pass pipeline and inliner.
Due to a couple of unfortunate circumstances, appending an NSArray instance to an Array instance does not actually append any elements.
The cause is https://github.com/apple/swift/pull/29220, which accidentally optimized away the actual loop that appends the elements in this particular case. (And only this particular case, which is why this wasn’t detected by the test suite.)
When the argument to `Array.append(contentsOf:)` is of type NSArray, the `newElements is [Element]` expression is compiled into a runtime check that returns true, eliminating the subsequent loop over the remaining items of the iterator. Sadly, NSArray.underestimatedCount` currently returns 0, so the earlier _copyContents call is a noop, so no elements get added to `self` at all.
Turning the `is` test into a direct equality check between the metatype instances resolves the issue.