@@ -1493,7 +1493,7 @@ mod prim_ref {}
1493
1493
///
1494
1494
/// ### Casting to and from integers
1495
1495
///
1496
- /// You cast function pointers directly to integers:
1496
+ /// You can cast function pointers directly to integers:
1497
1497
///
1498
1498
/// ```rust
1499
1499
/// let fnptr: fn(i32) -> i32 = |x| x+2;
@@ -1519,6 +1519,114 @@ mod prim_ref {}
1519
1519
/// Note that all of this is not portable to platforms where function pointers and data pointers
1520
1520
/// have different sizes.
1521
1521
///
1522
+ /// ### ABI compatibility
1523
+ ///
1524
+ /// Generally, when a function is declared with one signature and called via a function pointer with
1525
+ /// a different signature, the two signatures must be *ABI-compatible* or else calling the function
1526
+ /// via that function pointer is Undefined Behavior. ABI compatibility is a lot stricter than merely
1527
+ /// having the same memory layout; for example, even if `i32` and `f32` have the same size and
1528
+ /// alignment, they might be passed in different registers and hence not be ABI-compatible.
1529
+ ///
1530
+ /// ABI compatibility as a concern only arises in code that alters the type of function pointers,
1531
+ /// code that imports functions via `extern` blocks, and in code that combines `#[target_feature]`
1532
+ /// with `extern fn`. Altering the type of function pointers is wildly unsafe (as in, a lot more
1533
+ /// unsafe than even [`transmute_copy`][mem::transmute_copy]), and should only occur in the most
1534
+ /// exceptional circumstances. Most Rust code just imports functions via `use`. `#[target_feature]`
1535
+ /// is also used rarely. So, most likely you do not have to worry about ABI compatibility.
1536
+ ///
1537
+ /// But assuming such circumstances, what are the rules? For this section, we are only considering
1538
+ /// the ABI of direct Rust-to-Rust calls, not linking in general -- once functions are imported via
1539
+ /// `extern` blocks, there are more things to consider that we do not go into here.
1540
+ ///
1541
+ /// For two signatures to be considered *ABI-compatible*, they must use a compatible ABI string,
1542
+ /// must take the same number of arguments, the individual argument types and the return types must
1543
+ /// be ABI-compatible, and the target feature requirements must be met (see the subsection below for
1544
+ /// the last point). The ABI string is declared via `extern "ABI" fn(...) -> ...`; note that
1545
+ /// `fn name(...) -> ...` implicitly uses the `"Rust"` ABI string and `extern fn name(...) -> ...`
1546
+ /// implicitly uses the `"C"` ABI string.
1547
+ ///
1548
+ /// The ABI strings are guaranteed to be compatible if they are the same, or if the caller ABI
1549
+ /// string is `$X-unwind` and the callee ABI string is `$X`, where `$X` is one of the following:
1550
+ /// "C", "aapcs", "fastcall", "stdcall", "system", "sysv64", "thiscall", "vectorcall", "win64".
1551
+ ///
1552
+ /// The following types are guaranteed to be ABI-compatible:
1553
+ ///
1554
+ /// - `*const T`, `*mut T`, `&T`, `&mut T`, `Box<T>` (specifically, only `Box<T, Global>`), and
1555
+ /// `NonNull<T>` are all ABI-compatible with each other for all `T`. They are also ABI-compatible
1556
+ /// with each other for _different_ `T` if they have the same metadata type (`<T as
1557
+ /// Pointee>::Metadata`).
1558
+ /// - `usize` is ABI-compatible with the `uN` integer type of the same size, and likewise `isize` is
1559
+ /// ABI-compatible with the `iN` integer type of the same size.
1560
+ /// - Any two `fn` (function pointer) types are ABI-compatible with each other if they have the same
1561
+ /// ABI string or the ABI string only differs in a trailing `-unwind`, independent of the rest of
1562
+ /// their signature. (This means you can pass `fn()` to a function expecting `fn(i32)`, and the
1563
+ /// call will be valid ABI-wise. The callee receives the result of transmuting the function pointer
1564
+ /// from `fn()` to `fn(i32)`; that transmutation is itself a well-defined operation, it's just
1565
+ /// almost certainly UB to later call that function pointer.)
1566
+ /// - Any two types with size 0 and alignment 1 are ABI-compatible.
1567
+ /// - A `repr(transparent)` type `T` is ABI-compatible with its unique non-trivial field, i.e., the
1568
+ /// unique field that doesn't have size 0 and alignment 1 (if there is such a field).
1569
+ /// - `i32` is ABI-compatible with `NonZeroI32`, and similar for all other integer types with their
1570
+ /// matching `NonZero*` type.
1571
+ /// - If `T` is guaranteed to be subject to the [null pointer
1572
+ /// optimization](option/index.html#representation), then `T` and `Option<T>` are ABI-compatible.
1573
+ ///
1574
+ /// Furthermore, ABI compatibility satisfies the following general properties:
1575
+ ///
1576
+ /// - Every type is ABI-compatible with itself.
1577
+ /// - If `T1` and `T2` are ABI-compatible, then two `repr(C)` types that only differ because one
1578
+ /// field type was changed from `T1` to `T2` are ABI-compatible.
1579
+ /// - If `T1` and `T2` are ABI-compatible and `T2` and `T3` are ABI-compatible, then so are `T1` and
1580
+ /// `T3` (i.e., ABI-compatibility is transitive).
1581
+ /// - If `T1` and `T2` are ABI-compatible, then so are `T2` and `T1` (i.e., ABI-compatibility is
1582
+ /// symmetric).
1583
+ ///
1584
+ /// More signatures can be ABI-compatible on specific targets, but that should not be relied upon
1585
+ /// since it is not portable and not a stable guarantee.
1586
+ ///
1587
+ /// Noteworthy cases of types *not* being ABI-compatible in general are:
1588
+ /// * `bool` vs `u8`, and `i32` vs `u32`: on some targets, the calling conventions for these types
1589
+ /// differ in terms of what they guarantee for the remaining bits in the register that are not
1590
+ /// used by the value.
1591
+ /// * `i32` vs `f32` are not compatible either, as has already been mentioned above.
1592
+ /// * `struct Foo(u32)` and `u32` are not compatible (without `repr(transparent)`) since structs are
1593
+ /// aggregate types and often passed in a different way than primitives like `i32`.
1594
+ ///
1595
+ /// Note that these rules describe when two completely known types are ABI-compatible. When
1596
+ /// considering ABI compatibility of a type declared in another crate (including the standard
1597
+ /// library), consider that any type that has a private field or the `#[non_exhaustive]` attribute
1598
+ /// may change its layout as a non-breaking update unless documented otherwise -- so for instance,
1599
+ /// even if such a type is a 1-ZST or `repr(transparent)` right now, this might change with any
1600
+ /// library version bump.
1601
+ ///
1602
+ /// If the declared signature and the signature of the function pointer are ABI-compatible, then the
1603
+ /// function call behaves as if every argument was [`transmute`d][mem::transmute] from the
1604
+ /// type in the function pointer to the type at the function declaration, and the return value is
1605
+ /// [`transmute`d][mem::transmute] from the type in the declaration to the type in the
1606
+ /// pointer. All the usual caveats and concerns around transmutation apply; for instance, if the
1607
+ /// function expects a `NonNullI32` and the function pointer uses the ABI-compatible type
1608
+ /// `Option<NonNullI32>`, and the value used for the argument is `None`, then this call is Undefined
1609
+ /// Behavior since transmuting `None::<NonNullI32>` to `NonNullI32` violates the non-null
1610
+ /// requirement.
1611
+ ///
1612
+ /// #### Requirements concerning target features
1613
+ ///
1614
+ /// Under some conditions, the signature used by the caller and the callee can be ABI-incompatible
1615
+ /// even if the exact same ABI string and types are being used. As an example, the
1616
+ /// `std::arch::x86_64::__m256` type has a different `extern "C"` ABI when the `avx` feature is
1617
+ /// enabled vs when it is not enabled.
1618
+ ///
1619
+ /// Therefore, to ensure ABI compatibility when code using different target features is combined
1620
+ /// (such as via `#[target_feature]`), we further require that one of the following conditions is
1621
+ /// met:
1622
+ ///
1623
+ /// - The function uses the `"Rust"` ABI string (which is the default without `extern`).
1624
+ /// - Caller and callee are using the exact same set of target features. For the callee we consider
1625
+ /// the features enabled (via `#[target_feature]` and `-C target-feature`/`-C target-cpu`) at the
1626
+ /// declaration site; for the caller we consider the features enabled at the call site.
1627
+ /// - Neither any argument nor the return value involves a SIMD type (`#[repr(simd)]`) that is not
1628
+ /// behind a pointer indirection (i.e., `*mut __m256` is fine, but `(i32, __m256)` is not).
1629
+ ///
1522
1630
/// ### Trait implementations
1523
1631
///
1524
1632
/// In this documentation the shorthand `fn (T₁, T₂, …, Tₙ)` is used to represent non-variadic
0 commit comments