We are proposing a new marker protocol to identify types that can be trivially copied, moved, and destroyed. This supports @glessard’s recent StorageView pitch and fills a long-standing gap in our ability to write certain sorts of performant low-level code.
Introduction
We propose a new marker protocol BitwiseCopyable
that can be conformed to by types that can be moved or copied with direct calls to memcpy
and which require no special destroy operation[^1].
When compiling generic code with such constraints, the compiler can emit these efficient operations directly, only requiring minimal overhead to look up the size of the value at runtime.
Alternatively, developers can use this constraint to selectively provide high-performance variations of specific operations, such as bulk copying of a container.
Motivation
Swift can compile generic code into an unspecialized form in which the compiled function receives a value and type information about that value.
Basic operations are implemented by the compiler as calls to a table of "value witness functions."
This approach is flexible, but can represent significant overhead.
For example, using this approach to copy a buffer with a large number of Int
values requires a function call for each value.
Constraining the types in generic functions to BitwiseCopyable
allows the compiler (and in some cases, the developer) to instead use highly efficient direct memory operations in such cases.
The standard library already contains many examples of functions that could benefit from such a concept, and more are being proposed:
The UnsafeMutablePointer.initialize(to:count:)
function introduced in SE-0370 could use a bulk memory copy whenever it statically knew that its argument was BitwiseCopyable
.
The proposal for StorageView
includes the ability to copy items to or from potentially-unaligned storage, which requires that it be safe to use bulk memory operations:
public func loadUnaligned<T: BitwiseCopyable>(
fromByteOffset: Int = 0, as: T.Type
) -> T
public func loadUnaligned<T: BitwiseCopyable>(
from index: Index, as: T.Type
) -> T
Proposed solution
We add a new protocol BitwiseCopyable
to the standard library:
@_marker public protocol BitwiseCopyable {}
Many basic types in the standard library will conformed to this protocol.
Developer's own types may be conformed to the protocol, as well.
The compiler will check any such conformance and emit a diagnostic if the type contains elements that are not BitwiseCopyable
.
Furthermore, when building a module, the compiler will infer conformance to BitwiseCopyable
for any non-resilient struct or enum defined within the module whose stored members are all BitwiseCopyable
.
Developers cannot conform types defined in other modules to the protocol.
The full proposal can be found here:
BitwiseCopyable