Rollup merge of #131457 - kpreid:fnaddr, r=dtolnay · qinheping/verify-rust-std@2348c06 (original) (raw)
`@@ -2107,13 +2107,39 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool {
`
2107
2107
``
2108
2108
`/// Compares the addresses of the two function pointers for equality.
`
2109
2109
`///
`
2110
``
`-
/// Function pointers comparisons can have surprising results since
`
2111
``
`-
/// they are never guaranteed to be unique and could vary between different
`
2112
``
`-
/// code generation units. Furthermore, different functions could have the
`
2113
``
`-
/// same address after being merged together.
`
``
2110
`` +
/// This is the same as f == g
, but using this function makes clear that the potentially
``
``
2111
`+
/// surprising semantics of function pointer comparison are involved.
`
``
2112
`+
///
`
``
2113
`+
/// There are very few guarantees about how functions are compiled and they have no intrinsic
`
``
2114
`+
/// “identity”; in particular, this comparison:
`
``
2115
`+
///
`
``
2116
`` +
/// * May return true
unexpectedly, in cases where functions are equivalent.
``
``
2117
`+
///
`
``
2118
`` +
/// For example, the following program is likely (but not guaranteed) to print (true, true)
``
``
2119
`+
/// when compiled with optimization:
`
``
2120
`+
///
`
``
2121
/// ```
``
2122
`+
/// # #![feature(ptr_fn_addr_eq)]
`
``
2123
`+
/// let f: fn(i32) -> i32 = |x| x;
`
``
2124
`+
/// let g: fn(i32) -> i32 = |x| x + 0; // different closure, different body
`
``
2125
`+
/// let h: fn(u32) -> u32 = |x| x + 0; // different signature too
`
``
2126
`+
/// dbg!(std::ptr::fn_addr_eq(f, g), std::ptr::fn_addr_eq(f, h)); // not guaranteed to be equal
`
``
2127
/// ```
``
2128
`+
///
`
``
2129
`` +
/// * May return false
in any case.
``
``
2130
`+
///
`
``
2131
`+
/// This is particularly likely with generic functions but may happen with any function.
`
``
2132
`+
/// (From an implementation perspective, this is possible because functions may sometimes be
`
``
2133
`+
/// processed more than once by the compiler, resulting in duplicate machine code.)
`
``
2134
`+
///
`
``
2135
`+
/// Despite these false positives and false negatives, this comparison can still be useful.
`
``
2136
`+
/// Specifically, if
`
``
2137
`+
///
`
``
2138
`` +
/// * T
is the same type as U
, T
is a [subtype] of U
, or U
is a [subtype] of T
, and
``
``
2139
`` +
/// * ptr::fn_addr_eq(f, g)
returns true,
``
``
2140
`+
///
`
``
2141
`` +
/// then calling f
and calling g
will be equivalent.
``
2114
2142
`///
`
2115
``
`` -
/// This is the same as f == g
but using this function makes clear
``
2116
``
`-
/// that you are aware of these potentially surprising semantics.
`
2117
2143
`///
`
2118
2144
`/// # Examples
`
2119
2145
`///
`
`@@ -2125,6 +2151,8 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool {
`
2125
2151
`/// fn b() { println!("b"); }
`
2126
2152
`/// assert!(!ptr::fn_addr_eq(a as fn(), b as fn()));
`
2127
2153
```` /// ```
````
``
2154
`+
///
`
``
2155
`+
/// [subtype]: https://doc.rust-lang.org/reference/subtyping.html
`
2128
2156
`#[unstable(feature = "ptr_fn_addr_eq", issue = "129322")]
`
2129
2157
`#[inline(always)]
`
2130
2158
`#[must_use = "function pointer comparison produces a value"]
`