Swift tends to emit unnecessary checks and traps when iterating unsafe
raw buffer pointers. These traps are confirming that the position
pointer isn't nil, but this check is redundant with the bounds check
that is already present. We can safely remove it.
We trust the internal implementation of the stdlib to not cause any unintentional buffer overflows.
In such cases we can use the "unprotected" address-to-pointer conversions.
This avoids inserting stack protections where it's not needed.
Those functions work the same way as their "unprotected" counterparts, except that they don't trigger stack protection for the pointers.
* `_withUnprotectedUnsafeMutablePointer`
* `_withUnprotectedUnsafePointer`
* `_withUnprotectedUnsafeBytes` (two times)
- preserve previous version for ABI and source stability.
- add new version without alignment restriction.
- add explicit POD type enforcement in new version.
Here, as in UnsafeMutableRawPointer.storeBytes(of:toByteOffset:as:)
"as" is an argument label and "type" is the parameter.
Because the function body doesn't use this -- it's just for type
information -- changing its name from "as" to "type" doesn't have
any impact there.
- The previous implementation trapped when the source buffer was empty. That behaviour is both not documented and unnecessary. If the source buffer is empty, its length is necessarily shorter or equal than the length of the destination.
- The updated version simply returns when the source buffer is empty.
To send them across actors, they need to be wrapped in an '@unchecked
Sendable' type. Typically such a wrapper type would be be responsible
for ensuring its uniqueness or immutability.
Inferring Sendability for arbitrary types that contain Unsafe*Pointers
would introduce race conditions without warning or any explicit
acknoledgement from the programmer that the pointer is in fact unique.
We have already done the hard work of unwrapping the optionals
that represent the first and last pointer, and calling `self.count` does it all over again. Use the distance between the unwrapped pointers instead.
This patch removes as much checked math as I was able to find from the
unsafe buffer pointers types. In particular, I removed two kinds of
checked math:
1. Checked math that was provably unable to trap due to prior operations
done in the same function, or in a function that must have been
called before the current one. For example, in
index(_:offsetBy:limitedBy:), when we do the final index addition we
have already validated that it must be in-bounds. Therefore, it
cannot overflow.
2. Checked math that can only fail if the user is misusing the indices.
As previously discussed with Karoy and Andrew, the unsafe raw buffer
types are not obligated to crash if you misuse their indices, they
are free to invoke undefined behaviour. In these cases, I added
defensive overflow checks in debug mode.
The result of this change should be reductions in code size in almost
all usage sites of the raw buffer types.
Introduce checking of ConcurrentValue conformances:
- For structs, check that each stored property conforms to ConcurrentValue
- For enums, check that each associated value conforms to ConcurrentValue
- For classes, check that each stored property is immutable and conforms
to ConcurrentValue
Because all of the stored properties / associated values need to be
visible for this check to work, limit ConcurrentValue conformances to
be in the same source file as the type definition.
This checking can be disabled by conforming to a new marker protocol,
UnsafeConcurrentValue, that refines ConcurrentValue.
UnsafeConcurrentValue otherwise his no specific meaning. This allows
both "I know what I'm doing" for types that manage concurrent access
themselves as well as enabling retroactive conformance, both of which
are fundamentally unsafe but also quite necessary.
The bulk of this change ended up being to the standard library, because
all conformances of standard library types to the ConcurrentValue
protocol needed to be sunk down into the standard library so they
would benefit from the checking above. There were numerous little
mistakes in the initial pass through the stsandard library types that
have now been corrected.