Skip to content

Lint on fn pointers comparisons in external macros #134536

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ declare_lint! {
/// same address after being merged together.
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
Warn,
"detects unpredictable function pointer comparisons"
"detects unpredictable function pointer comparisons",
report_in_external_macro
}

#[derive(Copy, Clone, Default)]
Expand Down
1 change: 1 addition & 0 deletions library/core/src/task/wake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl RawWaker {
/// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot
/// be sent across threads.
#[stable(feature = "futures_api", since = "1.36.0")]
#[cfg_attr(not(bootstrap), allow(unpredictable_function_pointer_comparisons))]
#[derive(PartialEq, Copy, Clone, Debug)]
pub struct RawWakerVTable {
/// This function will be called when the [`RawWaker`] gets cloned, e.g. when
Expand Down
1 change: 1 addition & 0 deletions tests/ui/issues/issue-28561.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct Array<T> {
}

#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[allow(unpredictable_function_pointer_comparisons)]
struct Fn<A, B, C, D, E, F, G, H, I, J, K, L> {
f00: fn(),
f01: fn(A),
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/lint/fn-ptr-comparisons-some.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ fn main() {
let _ = Some::<FnPtr>(func) == Some(func as unsafe extern "C" fn());
//~^ WARN function pointer comparisons

// Undecided as of https://github.com/rust-lang/rust/pull/134536
assert_eq!(Some::<FnPtr>(func), Some(func as unsafe extern "C" fn()));
//~^ WARN function pointer comparisons
}
13 changes: 12 additions & 1 deletion tests/ui/lint/fn-ptr-comparisons-some.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,16 @@ LL | let _ = Some::<FnPtr>(func) == Some(func as unsafe extern "C" fn());
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
= note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default

warning: 1 warning emitted
warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons-some.rs:15:5
|
LL | assert_eq!(Some::<FnPtr>(func), Some(func as unsafe extern "C" fn()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the address of the same function can vary between different codegen units
= note: furthermore, different functions could have the same address after being merged together
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
= note: this warning originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: 2 warnings emitted

10 changes: 10 additions & 0 deletions tests/ui/lint/fn-ptr-comparisons-weird.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
//@ check-pass

#[derive(PartialEq, Eq)]
struct A {
f: fn(),
//~^ WARN function pointer comparisons
}

fn main() {
let f: fn() = main;
let g: fn() = main;
Expand All @@ -12,4 +18,8 @@ fn main() {
//~^ WARN function pointer comparisons
let _ = f < g;
//~^ WARN function pointer comparisons
let _ = assert_eq!(g, g);
//~^ WARN function pointer comparisons
let _ = assert_ne!(g, g);
//~^ WARN function pointer comparisons
}
48 changes: 42 additions & 6 deletions tests/ui/lint/fn-ptr-comparisons-weird.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons-weird.rs:7:13
--> $DIR/fn-ptr-comparisons-weird.rs:5:5
|
LL | #[derive(PartialEq, Eq)]
| --------- in this derive macro expansion
LL | struct A {
LL | f: fn(),
| ^^^^^^^
|
= note: the address of the same function can vary between different codegen units
= note: furthermore, different functions could have the same address after being merged together
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
= note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default
= note: this warning originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons-weird.rs:13:13
|
LL | let _ = f > g;
| ^^^^^
|
= note: the address of the same function can vary between different codegen units
= note: furthermore, different functions could have the same address after being merged together
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
= note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons-weird.rs:9:13
--> $DIR/fn-ptr-comparisons-weird.rs:15:13
|
LL | let _ = f >= g;
| ^^^^^^
Expand All @@ -20,7 +34,7 @@ LL | let _ = f >= g;
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons-weird.rs:11:13
--> $DIR/fn-ptr-comparisons-weird.rs:17:13
|
LL | let _ = f <= g;
| ^^^^^^
Expand All @@ -30,7 +44,7 @@ LL | let _ = f <= g;
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons-weird.rs:13:13
--> $DIR/fn-ptr-comparisons-weird.rs:19:13
|
LL | let _ = f < g;
| ^^^^^
Expand All @@ -39,5 +53,27 @@ LL | let _ = f < g;
= note: furthermore, different functions could have the same address after being merged together
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>

warning: 4 warnings emitted
warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons-weird.rs:21:13
|
LL | let _ = assert_eq!(g, g);
| ^^^^^^^^^^^^^^^^
|
= note: the address of the same function can vary between different codegen units
= note: furthermore, different functions could have the same address after being merged together
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
= note: this warning originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons-weird.rs:23:13
|
LL | let _ = assert_ne!(g, g);
| ^^^^^^^^^^^^^^^^
|
= note: the address of the same function can vary between different codegen units
= note: furthermore, different functions could have the same address after being merged together
= note: for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
= note: this warning originates in the macro `assert_ne` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: 7 warnings emitted

2 changes: 0 additions & 2 deletions tests/ui/lint/fn-ptr-comparisons.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ extern "C" fn c() {}

extern "C" fn args(_a: i32) -> i32 { 0 }

#[derive(PartialEq, Eq)]
struct A {
f: fn(),
}
Expand Down Expand Up @@ -52,7 +51,6 @@ fn main() {
let _ = std::ptr::fn_addr_eq(t, test as unsafe extern "C" fn());
//~^ WARN function pointer comparisons

let _ = a1 == a2; // should not warn
let _ = std::ptr::fn_addr_eq(a1.f, a2.f);
//~^ WARN function pointer comparisons
}
2 changes: 0 additions & 2 deletions tests/ui/lint/fn-ptr-comparisons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ extern "C" fn c() {}

extern "C" fn args(_a: i32) -> i32 { 0 }

#[derive(PartialEq, Eq)]
struct A {
f: fn(),
}
Expand Down Expand Up @@ -52,7 +51,6 @@ fn main() {
let _ = t == test;
//~^ WARN function pointer comparisons

let _ = a1 == a2; // should not warn
let _ = a1.f == a2.f;
//~^ WARN function pointer comparisons
}
24 changes: 12 additions & 12 deletions tests/ui/lint/fn-ptr-comparisons.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:26:13
--> $DIR/fn-ptr-comparisons.rs:25:13
|
LL | let _ = f == a;
| ^^^^^^
Expand All @@ -14,7 +14,7 @@ LL | let _ = std::ptr::fn_addr_eq(f, a as fn());
| +++++++++++++++++++++ ~ ++++++++

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:28:13
--> $DIR/fn-ptr-comparisons.rs:27:13
|
LL | let _ = f != a;
| ^^^^^^
Expand All @@ -28,7 +28,7 @@ LL | let _ = !std::ptr::fn_addr_eq(f, a as fn());
| ++++++++++++++++++++++ ~ ++++++++

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:30:13
--> $DIR/fn-ptr-comparisons.rs:29:13
|
LL | let _ = f == g;
| ^^^^^^
Expand All @@ -42,7 +42,7 @@ LL | let _ = std::ptr::fn_addr_eq(f, g);
| +++++++++++++++++++++ ~ +

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:32:13
--> $DIR/fn-ptr-comparisons.rs:31:13
|
LL | let _ = f == f;
| ^^^^^^
Expand All @@ -56,7 +56,7 @@ LL | let _ = std::ptr::fn_addr_eq(f, f);
| +++++++++++++++++++++ ~ +

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:34:13
--> $DIR/fn-ptr-comparisons.rs:33:13
|
LL | let _ = g == g;
| ^^^^^^
Expand All @@ -70,7 +70,7 @@ LL | let _ = std::ptr::fn_addr_eq(g, g);
| +++++++++++++++++++++ ~ +

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:36:13
--> $DIR/fn-ptr-comparisons.rs:35:13
|
LL | let _ = g == g;
| ^^^^^^
Expand All @@ -84,7 +84,7 @@ LL | let _ = std::ptr::fn_addr_eq(g, g);
| +++++++++++++++++++++ ~ +

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:38:13
--> $DIR/fn-ptr-comparisons.rs:37:13
|
LL | let _ = &g == &g;
| ^^^^^^^^
Expand All @@ -98,7 +98,7 @@ LL | let _ = std::ptr::fn_addr_eq(g, g);
| ~~~~~~~~~~~~~~~~~~~~~ ~ +

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:40:13
--> $DIR/fn-ptr-comparisons.rs:39:13
|
LL | let _ = a as fn() == g;
| ^^^^^^^^^^^^^^
Expand All @@ -112,7 +112,7 @@ LL | let _ = std::ptr::fn_addr_eq(a as fn(), g);
| +++++++++++++++++++++ ~ +

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:44:13
--> $DIR/fn-ptr-comparisons.rs:43:13
|
LL | let _ = cfn == c;
| ^^^^^^^^
Expand All @@ -126,7 +126,7 @@ LL | let _ = std::ptr::fn_addr_eq(cfn, c as extern "C" fn());
| +++++++++++++++++++++ ~ +++++++++++++++++++

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:48:13
--> $DIR/fn-ptr-comparisons.rs:47:13
|
LL | let _ = argsfn == args;
| ^^^^^^^^^^^^^^
Expand All @@ -140,7 +140,7 @@ LL | let _ = std::ptr::fn_addr_eq(argsfn, args as extern "C" fn(i32) -> i32)
| +++++++++++++++++++++ ~ +++++++++++++++++++++++++++++

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:52:13
--> $DIR/fn-ptr-comparisons.rs:51:13
|
LL | let _ = t == test;
| ^^^^^^^^^
Expand All @@ -154,7 +154,7 @@ LL | let _ = std::ptr::fn_addr_eq(t, test as unsafe extern "C" fn());
| +++++++++++++++++++++ ~ ++++++++++++++++++++++++++

warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
--> $DIR/fn-ptr-comparisons.rs:56:13
--> $DIR/fn-ptr-comparisons.rs:54:13
|
LL | let _ = a1.f == a2.f;
| ^^^^^^^^^^^^
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/mir/mir_refs_correct.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//@ run-pass
//@ aux-build:mir_external_refs.rs

#![allow(unpredictable_function_pointer_comparisons)]

extern crate mir_external_refs as ext;

struct S(#[allow(dead_code)] u8);
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/nullable-pointer-iotareduction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
// trying to get assert failure messages that at least identify which case
// failed.

#![allow(unpredictable_function_pointer_comparisons)]

enum E<T> { Thing(isize, T), #[allow(dead_code)] Nothing((), ((), ()), [i8; 0]) }
impl<T> E<T> {
fn is_none(&self) -> bool {
Expand Down
Loading