Skip to content

Commit

Permalink
the call ABI does not have to be fully equal; explicilty discuss inco…
Browse files Browse the repository at this point in the history
…mpleteness
  • Loading branch information
RalfJung committed Sep 3, 2023
1 parent b1a7983 commit 81dadf6
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 22 deletions.
29 changes: 18 additions & 11 deletions library/core/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1529,16 +1529,20 @@ mod prim_ref {}
///
/// ### 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
/// 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:
/// For two signatures to be considered *ABI-compatible*, they must use a compatible call ABI (as
/// declared via `extern "ABI"`), must take the same number of arguments, and the individual
/// argument types and the return types must be ABI-compatible.
///
/// The call ABIs are guaranteed to be compatible if they are the same, or if the caller ABI is
/// `$X-unwind` and the callee ABI is `$X`.
///
/// The following types are guaranteed to be ABI-compatible:
///
/// - Every type is ABI-compatible with itself.
/// - If `<T as Pointee>::Metadata == ()`, then `*const T`, `*mut T`, `&T`, `&mut T`, `Box<T>`,
Expand All @@ -1555,17 +1559,20 @@ mod prim_ref {}
/// 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.
/// More signatures can be ABI-compatible on specific targets, but that should not be relied upon
/// since it is not portable and not a stable guarantee.
///
/// Noteworthy cases of types *not* being ABI-compatible in general 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.
///
/// Note that these rules describe when two completely known types are ABI-compatible. When
/// considering ABI compatibility of a type declared in another crate (including the standard
/// library), consider that any type that has a private field or the `#[non_exhaustive]` attribute
/// may change its layout as a non-breaking update unless documented otherwise -- so for instance,
/// even if such a type is a 1-ZST or `repr(transparent)` right now, this might change with any
/// library version change.
/// library version bump.
///
/// ### Trait implementations
///
Expand Down
29 changes: 18 additions & 11 deletions library/std/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1529,16 +1529,20 @@ mod prim_ref {}
///
/// ### 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
/// 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:
/// For two signatures to be considered *ABI-compatible*, they must use a compatible call ABI (as
/// declared via `extern "ABI"`), must take the same number of arguments, and the individual
/// argument types and the return types must be ABI-compatible.
///
/// The call ABIs are guaranteed to be compatible if they are the same, or if the caller ABI is
/// `$X-unwind` and the callee ABI is `$X`.
///
/// The following types are guaranteed to be ABI-compatible:
///
/// - Every type is ABI-compatible with itself.
/// - If `<T as Pointee>::Metadata == ()`, then `*const T`, `*mut T`, `&T`, `&mut T`, `Box<T>`,
Expand All @@ -1555,17 +1559,20 @@ mod prim_ref {}
/// 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.
/// More signatures can be ABI-compatible on specific targets, but that should not be relied upon
/// since it is not portable and not a stable guarantee.
///
/// Noteworthy cases of types *not* being ABI-compatible in general 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.
///
/// Note that these rules describe when two completely known types are ABI-compatible. When
/// considering ABI compatibility of a type declared in another crate (including the standard
/// library), consider that any type that has a private field or the `#[non_exhaustive]` attribute
/// may change its layout as a non-breaking update unless documented otherwise -- so for instance,
/// even if such a type is a 1-ZST or `repr(transparent)` right now, this might change with any
/// library version change.
/// library version bump.
///
/// ### Trait implementations
///
Expand Down

0 comments on commit 81dadf6

Please sign in to comment.