Skip to content

Commit

Permalink
document ABI compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Sep 2, 2023
1 parent 585bb5e commit ee09160
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
35 changes: 34 additions & 1 deletion library/core/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1501,7 +1501,7 @@ mod prim_ref {}
///
/// ### Casting to and from integers
///
/// You cast function pointers directly to integers:
/// You can cast function pointers directly to integers:
///
/// ```rust
/// let fnptr: fn(i32) -> i32 = |x| x+2;
Expand All @@ -1527,6 +1527,39 @@ mod prim_ref {}
/// Note that all of this is not portable to platforms where function pointers and data pointers
/// have different sizes.
///
/// ### ABI compatibility
///
/// Generally, when a function is declared with one signature and called via a function pointer
/// with a different signature, the two signatures must be *ABI-compatible* or else this call is
/// Undefined Behavior. ABI compatibility is a lot stricter than merely having the same
/// representation in memory; for example, even if `i32` and `f32` have the same size and alignment,
/// they might be passed in different registers and hence not be ABI-compatible.
///
/// For two signatures to be considered *ABI-compatible*, they must declare the same `extern` ABI
/// string, must take the same number of arguments, and the individual argument types and the return
/// types must be ABI-compatible.
/// The relation of when two types are ABI-compatible is defined as follows:
///
/// - Every type is ABI-compatible with itself.
/// - If `<T as Pointee>::Metadata == ()`, then `*const T`, `*mut T`, `&T`, `&mut T`, `Box<T>`,
/// `NonNull<T>` are all ABI-compatible with each other.
/// - Any two `fn()` types with the same `extern` ABI string are ABI-compatible with each other.
/// - Any two 1-ZST types (types with size 0 and alignment 1) are ABI-compatible.
/// - A `repr(transparent)` type `T` that has no private fields and is not `#[non_exhaustive]` is
/// ABI-compatible with its unique non-1-ZST field (if there is such a field).
/// - `i32` is ABI-compatible with `NonZeroI32`, and similar for all other integer types with their
/// matching `NonZero*` type.
/// - If `T` is guaranteed to be subject to the [null pointer
/// optimization](option/index.html#representation), then `T` and `Option<T>` are ABI-compatible.
/// - If `T1` and `T2` are ABI-compatible, then two `repr(C)` types that only differ because one
/// field type was changed from `T1` to `T2` are ABI-compatible.
/// - ABI-compatibility is symmetric and transitive.
///
/// Noteworthy cases of types *not* being ABI-compatible are `bool` vs `u8`, and `i32` vs `u32`: on
/// some targets, the calling conventions for these types differ in terms of what they guarantee for
/// the remaining bits in the register that are not used by the value. `i32` vs `f32` has already
/// been mentioned above.
///
/// ### Trait implementations
///
/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic
Expand Down
35 changes: 34 additions & 1 deletion library/std/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1501,7 +1501,7 @@ mod prim_ref {}
///
/// ### Casting to and from integers
///
/// You cast function pointers directly to integers:
/// You can cast function pointers directly to integers:
///
/// ```rust
/// let fnptr: fn(i32) -> i32 = |x| x+2;
Expand All @@ -1527,6 +1527,39 @@ mod prim_ref {}
/// Note that all of this is not portable to platforms where function pointers and data pointers
/// have different sizes.
///
/// ### ABI compatibility
///
/// Generally, when a function is declared with one signature and called via a function pointer
/// with a different signature, the two signatures must be *ABI-compatible* or else this call is
/// Undefined Behavior. ABI compatibility is a lot stricter than merely having the same
/// representation in memory; for example, even if `i32` and `f32` have the same size and alignment,
/// they might be passed in different registers and hence not be ABI-compatible.
///
/// For two signatures to be considered *ABI-compatible*, they must declare the same `extern` ABI
/// string, must take the same number of arguments, and the individual argument types and the return
/// types must be ABI-compatible.
/// The relation of when two types are ABI-compatible is defined as follows:
///
/// - Every type is ABI-compatible with itself.
/// - If `<T as Pointee>::Metadata == ()`, then `*const T`, `*mut T`, `&T`, `&mut T`, `Box<T>`,
/// `NonNull<T>` are all ABI-compatible with each other.
/// - Any two `fn()` types with the same `extern` ABI string are ABI-compatible with each other.
/// - Any two 1-ZST types (types with size 0 and alignment 1) are ABI-compatible.
/// - A `repr(transparent)` type `T` that has no private fields and is not `#[non_exhaustive]` is
/// ABI-compatible with its unique non-1-ZST field (if there is such a field).
/// - `i32` is ABI-compatible with `NonZeroI32`, and similar for all other integer types with their
/// matching `NonZero*` type.
/// - If `T` is guaranteed to be subject to the [null pointer
/// optimization](option/index.html#representation), then `T` and `Option<T>` are ABI-compatible.
/// - If `T1` and `T2` are ABI-compatible, then two `repr(C)` types that only differ because one
/// field type was changed from `T1` to `T2` are ABI-compatible.
/// - ABI-compatibility is symmetric and transitive.
///
/// Noteworthy cases of types *not* being ABI-compatible are `bool` vs `u8`, and `i32` vs `u32`: on
/// some targets, the calling conventions for these types differ in terms of what they guarantee for
/// the remaining bits in the register that are not used by the value. `i32` vs `f32` has already
/// been mentioned above.
///
/// ### Trait implementations
///
/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic
Expand Down

0 comments on commit ee09160

Please sign in to comment.