Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ee09160

Browse files
committedSep 2, 2023
document ABI compatibility
1 parent 585bb5e commit ee09160

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed
 

‎library/core/src/primitive_docs.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -1501,7 +1501,7 @@ mod prim_ref {}
15011501
///
15021502
/// ### Casting to and from integers
15031503
///
1504-
/// You cast function pointers directly to integers:
1504+
/// You can cast function pointers directly to integers:
15051505
///
15061506
/// ```rust
15071507
/// let fnptr: fn(i32) -> i32 = |x| x+2;
@@ -1527,6 +1527,39 @@ mod prim_ref {}
15271527
/// Note that all of this is not portable to platforms where function pointers and data pointers
15281528
/// have different sizes.
15291529
///
1530+
/// ### ABI compatibility
1531+
///
1532+
/// Generally, when a function is declared with one signature and called via a function pointer
1533+
/// with a different signature, the two signatures must be *ABI-compatible* or else this call is
1534+
/// Undefined Behavior. ABI compatibility is a lot stricter than merely having the same
1535+
/// representation in memory; for example, even if `i32` and `f32` have the same size and alignment,
1536+
/// they might be passed in different registers and hence not be ABI-compatible.
1537+
///
1538+
/// For two signatures to be considered *ABI-compatible*, they must declare the same `extern` ABI
1539+
/// string, must take the same number of arguments, and the individual argument types and the return
1540+
/// types must be ABI-compatible.
1541+
/// The relation of when two types are ABI-compatible is defined as follows:
1542+
///
1543+
/// - Every type is ABI-compatible with itself.
1544+
/// - If `<T as Pointee>::Metadata == ()`, then `*const T`, `*mut T`, `&T`, `&mut T`, `Box<T>`,
1545+
/// `NonNull<T>` are all ABI-compatible with each other.
1546+
/// - Any two `fn()` types with the same `extern` ABI string are ABI-compatible with each other.
1547+
/// - Any two 1-ZST types (types with size 0 and alignment 1) are ABI-compatible.
1548+
/// - A `repr(transparent)` type `T` that has no private fields and is not `#[non_exhaustive]` is
1549+
/// ABI-compatible with its unique non-1-ZST field (if there is such a field).
1550+
/// - `i32` is ABI-compatible with `NonZeroI32`, and similar for all other integer types with their
1551+
/// matching `NonZero*` type.
1552+
/// - If `T` is guaranteed to be subject to the [null pointer
1553+
/// optimization](option/index.html#representation), then `T` and `Option<T>` are ABI-compatible.
1554+
/// - If `T1` and `T2` are ABI-compatible, then two `repr(C)` types that only differ because one
1555+
/// field type was changed from `T1` to `T2` are ABI-compatible.
1556+
/// - ABI-compatibility is symmetric and transitive.
1557+
///
1558+
/// Noteworthy cases of types *not* being ABI-compatible are `bool` vs `u8`, and `i32` vs `u32`: on
1559+
/// some targets, the calling conventions for these types differ in terms of what they guarantee for
1560+
/// the remaining bits in the register that are not used by the value. `i32` vs `f32` has already
1561+
/// been mentioned above.
1562+
///
15301563
/// ### Trait implementations
15311564
///
15321565
/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic

‎library/std/src/primitive_docs.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -1501,7 +1501,7 @@ mod prim_ref {}
15011501
///
15021502
/// ### Casting to and from integers
15031503
///
1504-
/// You cast function pointers directly to integers:
1504+
/// You can cast function pointers directly to integers:
15051505
///
15061506
/// ```rust
15071507
/// let fnptr: fn(i32) -> i32 = |x| x+2;
@@ -1527,6 +1527,39 @@ mod prim_ref {}
15271527
/// Note that all of this is not portable to platforms where function pointers and data pointers
15281528
/// have different sizes.
15291529
///
1530+
/// ### ABI compatibility
1531+
///
1532+
/// Generally, when a function is declared with one signature and called via a function pointer
1533+
/// with a different signature, the two signatures must be *ABI-compatible* or else this call is
1534+
/// Undefined Behavior. ABI compatibility is a lot stricter than merely having the same
1535+
/// representation in memory; for example, even if `i32` and `f32` have the same size and alignment,
1536+
/// they might be passed in different registers and hence not be ABI-compatible.
1537+
///
1538+
/// For two signatures to be considered *ABI-compatible*, they must declare the same `extern` ABI
1539+
/// string, must take the same number of arguments, and the individual argument types and the return
1540+
/// types must be ABI-compatible.
1541+
/// The relation of when two types are ABI-compatible is defined as follows:
1542+
///
1543+
/// - Every type is ABI-compatible with itself.
1544+
/// - If `<T as Pointee>::Metadata == ()`, then `*const T`, `*mut T`, `&T`, `&mut T`, `Box<T>`,
1545+
/// `NonNull<T>` are all ABI-compatible with each other.
1546+
/// - Any two `fn()` types with the same `extern` ABI string are ABI-compatible with each other.
1547+
/// - Any two 1-ZST types (types with size 0 and alignment 1) are ABI-compatible.
1548+
/// - A `repr(transparent)` type `T` that has no private fields and is not `#[non_exhaustive]` is
1549+
/// ABI-compatible with its unique non-1-ZST field (if there is such a field).
1550+
/// - `i32` is ABI-compatible with `NonZeroI32`, and similar for all other integer types with their
1551+
/// matching `NonZero*` type.
1552+
/// - If `T` is guaranteed to be subject to the [null pointer
1553+
/// optimization](option/index.html#representation), then `T` and `Option<T>` are ABI-compatible.
1554+
/// - If `T1` and `T2` are ABI-compatible, then two `repr(C)` types that only differ because one
1555+
/// field type was changed from `T1` to `T2` are ABI-compatible.
1556+
/// - ABI-compatibility is symmetric and transitive.
1557+
///
1558+
/// Noteworthy cases of types *not* being ABI-compatible are `bool` vs `u8`, and `i32` vs `u32`: on
1559+
/// some targets, the calling conventions for these types differ in terms of what they guarantee for
1560+
/// the remaining bits in the register that are not used by the value. `i32` vs `f32` has already
1561+
/// been mentioned above.
1562+
///
15301563
/// ### Trait implementations
15311564
///
15321565
/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic

0 commit comments

Comments
 (0)
Failed to load comments.