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"]

`