1
Fork 0

Rollup merge of #118833 - Urgau:lint_function_pointer_comparisons, r=cjgillot

Add lint against function pointer comparisons

This is kind of a follow-up to https://github.com/rust-lang/rust/pull/117758 where we added a lint against wide pointer comparisons for being ambiguous and unreliable; well function pointer comparisons are also unreliable. We should IMO follow a similar logic and warn people about it.

-----

## `unpredictable_function_pointer_comparisons`

*warn-by-default*

The `unpredictable_function_pointer_comparisons` lint checks comparison of function pointer as the operands.

### Example

```rust
fn foo() {}
let a = foo as fn();

let _ = a == foo;
```

### Explanation

Function pointers comparisons do not produce meaningful result since they are never guaranteed to be unique and could vary between different code generation units. Furthermore different function could have the same address after being merged together.

----

This PR also uplift the very similar `clippy::fn_address_comparisons` lint, which only linted on if one of the operand was an `ty::FnDef` while this PR lints proposes to lint on all `ty::FnPtr` and `ty::FnDef`.

```@rustbot``` labels +I-lang-nominated

~~Edit: Blocked on https://github.com/rust-lang/libs-team/issues/323 being accepted and it's follow-up pr~~
This commit is contained in:
León Orell Valerian Liehr 2024-12-05 07:29:53 +01:00 committed by GitHub
commit 35ea48d588
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 624 additions and 174 deletions

View file

@ -885,6 +885,12 @@ lint_unnameable_test_items = cannot test inner items
lint_unnecessary_qualification = unnecessary qualification
.suggestion = remove the unnecessary path segments
lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique
.note_duplicated_fn = the address of the same function can vary between different codegen units
.note_deduplicated_fn = furthermore, different functions could have the same address after being merged together
.note_visit_fn_addr_eq = for more information visit <https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html>
.fn_addr_eq_suggestion = refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::`
lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe

View file

@ -1815,6 +1815,42 @@ pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
},
}
#[derive(LintDiagnostic)]
pub(crate) enum UnpredictableFunctionPointerComparisons<'a> {
#[diag(lint_unpredictable_fn_pointer_comparisons)]
#[note(lint_note_duplicated_fn)]
#[note(lint_note_deduplicated_fn)]
#[note(lint_note_visit_fn_addr_eq)]
Suggestion {
#[subdiagnostic]
sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a>,
},
#[diag(lint_unpredictable_fn_pointer_comparisons)]
#[note(lint_note_duplicated_fn)]
#[note(lint_note_deduplicated_fn)]
#[note(lint_note_visit_fn_addr_eq)]
Warn,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(
lint_fn_addr_eq_suggestion,
style = "verbose",
applicability = "maybe-incorrect"
)]
pub(crate) struct UnpredictableFunctionPointerComparisonsSuggestion<'a> {
pub ne: &'a str,
pub cast_right: String,
pub deref_left: &'a str,
pub deref_right: &'a str,
#[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
pub left: Span,
#[suggestion_part(code = ", {deref_right}")]
pub middle: Span,
#[suggestion_part(code = "{cast_right})")]
pub right: Span,
}
pub(crate) struct ImproperCTypes<'a> {
pub ty: Ty<'a>,
pub desc: &'a str,

View file

@ -23,7 +23,9 @@ use crate::lints::{
AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
InvalidNanComparisonsSuggestion, UnusedComparisons, VariantSizeDifferencesDiag,
InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons,
UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons,
VariantSizeDifferencesDiag,
};
use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
@ -166,6 +168,35 @@ declare_lint! {
"detects ambiguous wide pointer comparisons"
}
declare_lint! {
/// The `unpredictable_function_pointer_comparisons` lint checks comparison
/// of function pointer as the operands.
///
/// ### Example
///
/// ```rust
/// fn a() {}
/// fn b() {}
///
/// let f: fn() = a;
/// let g: fn() = b;
///
/// let _ = f == g;
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Function pointers comparisons do not produce meaningful result since
/// they are never guaranteed to be unique and could vary between different
/// code generation units. Furthermore, different functions could have the
/// same address after being merged together.
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
Warn,
"detects unpredictable function pointer comparisons"
}
#[derive(Copy, Clone, Default)]
pub(crate) struct TypeLimits {
/// Id of the last visited negated expression
@ -178,7 +209,8 @@ impl_lint_pass!(TypeLimits => [
UNUSED_COMPARISONS,
OVERFLOWING_LITERALS,
INVALID_NAN_COMPARISONS,
AMBIGUOUS_WIDE_POINTER_COMPARISONS
AMBIGUOUS_WIDE_POINTER_COMPARISONS,
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS
]);
impl TypeLimits {
@ -255,7 +287,7 @@ fn lint_nan<'tcx>(
cx.emit_span_lint(INVALID_NAN_COMPARISONS, e.span, lint);
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Copy, Clone)]
enum ComparisonOp {
BinOp(hir::BinOpKind),
Other,
@ -383,6 +415,100 @@ fn lint_wide_pointer<'tcx>(
);
}
fn lint_fn_pointer<'tcx>(
cx: &LateContext<'tcx>,
e: &'tcx hir::Expr<'tcx>,
cmpop: ComparisonOp,
l: &'tcx hir::Expr<'tcx>,
r: &'tcx hir::Expr<'tcx>,
) {
let peel_refs = |mut ty: Ty<'tcx>| -> (Ty<'tcx>, usize) {
let mut refs = 0;
while let ty::Ref(_, inner_ty, _) = ty.kind() {
ty = *inner_ty;
refs += 1;
}
(ty, refs)
};
// Left and right operands can have borrows, remove them
let l = l.peel_borrows();
let r = r.peel_borrows();
let Some(l_ty) = cx.typeck_results().expr_ty_opt(l) else { return };
let Some(r_ty) = cx.typeck_results().expr_ty_opt(r) else { return };
// Remove any references as `==` will deref through them (and count the
// number of references removed, for latter).
let (l_ty, l_ty_refs) = peel_refs(l_ty);
let (r_ty, r_ty_refs) = peel_refs(r_ty);
if !l_ty.is_fn() || !r_ty.is_fn() {
return;
}
// Let's try to suggest `ptr::fn_addr_eq` if/when possible.
let is_eq_ne = matches!(cmpop, ComparisonOp::BinOp(hir::BinOpKind::Eq | hir::BinOpKind::Ne));
if !is_eq_ne {
// Neither `==` nor `!=`, we can't suggest `ptr::fn_addr_eq`, just show the warning.
return cx.emit_span_lint(
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
e.span,
UnpredictableFunctionPointerComparisons::Warn,
);
}
let (Some(l_span), Some(r_span)) =
(l.span.find_ancestor_inside(e.span), r.span.find_ancestor_inside(e.span))
else {
// No appropriate spans for the left and right operands, just show the warning.
return cx.emit_span_lint(
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
e.span,
UnpredictableFunctionPointerComparisons::Warn,
);
};
let ne = if cmpop == ComparisonOp::BinOp(hir::BinOpKind::Ne) { "!" } else { "" };
// `ptr::fn_addr_eq` only works with raw pointer, deref any references.
let deref_left = &*"*".repeat(l_ty_refs);
let deref_right = &*"*".repeat(r_ty_refs);
let left = e.span.shrink_to_lo().until(l_span.shrink_to_lo());
let middle = l_span.shrink_to_hi().until(r_span.shrink_to_lo());
let right = r_span.shrink_to_hi().until(e.span.shrink_to_hi());
// We only check for a right cast as `FnDef` == `FnPtr` is not possible,
// only `FnPtr == FnDef` is possible.
let cast_right = if !r_ty.is_fn_ptr() {
let fn_sig = r_ty.fn_sig(cx.tcx);
format!(" as {fn_sig}")
} else {
String::new()
};
cx.emit_span_lint(
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
e.span,
UnpredictableFunctionPointerComparisons::Suggestion {
sugg: UnpredictableFunctionPointerComparisonsSuggestion {
ne,
deref_left,
deref_right,
left,
middle,
right,
cast_right,
},
},
);
}
impl<'tcx> LateLintPass<'tcx> for TypeLimits {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
match e.kind {
@ -399,7 +525,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
} else {
lint_nan(cx, e, binop, l, r);
lint_wide_pointer(cx, e, ComparisonOp::BinOp(binop.node), l, r);
let cmpop = ComparisonOp::BinOp(binop.node);
lint_wide_pointer(cx, e, cmpop, l, r);
lint_fn_pointer(cx, e, cmpop, l, r);
}
}
}
@ -411,6 +539,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
&& let Some(cmpop) = diag_item_cmpop(diag_item) =>
{
lint_wide_pointer(cx, e, cmpop, l, r);
lint_fn_pointer(cx, e, cmpop, l, r);
}
hir::ExprKind::MethodCall(_, l, [r], _)
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
@ -418,6 +547,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
&& let Some(cmpop) = diag_item_cmpop(diag_item) =>
{
lint_wide_pointer(cx, e, cmpop, l, r);
lint_fn_pointer(cx, e, cmpop, l, r);
}
_ => {}
};

View file

@ -304,6 +304,7 @@ fn test_const_nonnull_new() {
#[test]
#[cfg(unix)] // printf may not be available on other platforms
#[allow(deprecated)] // For SipHasher
#[cfg_attr(not(bootstrap), allow(unpredictable_function_pointer_comparisons))]
pub fn test_variadic_fnptr() {
use core::ffi;
use core::hash::{Hash, SipHasher};

View file

@ -744,7 +744,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::unit_types::LET_UNIT_VALUE_INFO,
crate::unit_types::UNIT_ARG_INFO,
crate::unit_types::UNIT_CMP_INFO,
crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO,
crate::unnecessary_literal_bound::UNNECESSARY_LITERAL_BOUND_INFO,
crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO,

View file

@ -74,6 +74,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
#[clippy::version = "1.53.0"]
("clippy::filter_map", "clippy::manual_filter_map"),
#[clippy::version = ""]
("clippy::fn_address_comparisons", "unpredictable_function_pointer_comparisons"),
#[clippy::version = ""]
("clippy::identity_conversion", "clippy::useless_conversion"),
#[clippy::version = "pre 1.29.0"]
("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"),

View file

@ -363,7 +363,6 @@ mod uninhabited_references;
mod uninit_vec;
mod unit_return_expecting_ord;
mod unit_types;
mod unnamed_address;
mod unnecessary_box_returns;
mod unnecessary_literal_bound;
mod unnecessary_map_on_constructor;
@ -786,7 +785,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(conf)));
store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
store.register_late_pass(|_| Box::<dereference::Dereferencing<'_>>::default());
store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));

View file

@ -1,60 +0,0 @@
use clippy_utils::diagnostics::span_lint;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
declare_clippy_lint! {
/// ### What it does
/// Checks for comparisons with an address of a function item.
///
/// ### Why is this bad?
/// Function item address is not guaranteed to be unique and could vary
/// between different code generation units. Furthermore different function items could have
/// the same address after being merged together.
///
/// ### Example
/// ```no_run
/// type F = fn();
/// fn a() {}
/// let f: F = a;
/// if f == a {
/// // ...
/// }
/// ```
#[clippy::version = "1.44.0"]
pub FN_ADDRESS_COMPARISONS,
correctness,
"comparison with an address of a function item"
}
declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS]);
impl LateLintPass<'_> for UnnamedAddress {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
fn is_comparison(binop: BinOpKind) -> bool {
matches!(
binop,
BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt
)
}
fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..))
}
if let ExprKind::Binary(binop, left, right) = expr.kind
&& is_comparison(binop.node)
&& cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr()
&& cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr()
&& (is_fn_def(cx, left) || is_fn_def(cx, right))
{
span_lint(
cx,
FN_ADDRESS_COMPARISONS,
expr.span,
"comparing with a non-unique address of a function item",
);
}
}
}

View file

@ -1,23 +0,0 @@
use std::fmt::Debug;
use std::ptr;
use std::rc::Rc;
use std::sync::Arc;
fn a() {}
#[warn(clippy::fn_address_comparisons)]
fn main() {
type F = fn();
let f: F = a;
let g: F = f;
// These should fail:
let _ = f == a;
//~^ ERROR: comparing with a non-unique address of a function item
//~| NOTE: `-D clippy::fn-address-comparisons` implied by `-D warnings`
let _ = f != a;
//~^ ERROR: comparing with a non-unique address of a function item
// These should be fine:
let _ = f == g;
}

View file

@ -1,17 +0,0 @@
error: comparing with a non-unique address of a function item
--> tests/ui/fn_address_comparisons.rs:15:13
|
LL | let _ = f == a;
| ^^^^^^
|
= note: `-D clippy::fn-address-comparisons` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::fn_address_comparisons)]`
error: comparing with a non-unique address of a function item
--> tests/ui/fn_address_comparisons.rs:18:13
|
LL | let _ = f != a;
| ^^^^^^
error: aborting due to 2 previous errors

View file

@ -59,6 +59,7 @@
#![allow(unknown_lints)]
#![allow(unused_labels)]
#![allow(ambiguous_wide_pointer_comparisons)]
#![allow(unpredictable_function_pointer_comparisons)]
#![allow(clippy::reversed_empty_ranges)]
#![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
#![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name`
@ -74,6 +75,7 @@
#![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence`
#![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map`
#![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map`
#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
#![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion`
#![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
#![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result`

View file

@ -59,6 +59,7 @@
#![allow(unknown_lints)]
#![allow(unused_labels)]
#![allow(ambiguous_wide_pointer_comparisons)]
#![allow(unpredictable_function_pointer_comparisons)]
#![allow(clippy::reversed_empty_ranges)]
#![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
#![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name`
@ -74,6 +75,7 @@
#![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence`
#![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map`
#![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map`
#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons`
#![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion`
#![warn(clippy::if_let_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
#![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result`

View file

@ -1,5 +1,5 @@
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
--> tests/ui/rename.rs:63:9
--> tests/ui/rename.rs:64:9
|
LL | #![warn(clippy::almost_complete_letter_range)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@ -8,394 +8,400 @@ LL | #![warn(clippy::almost_complete_letter_range)]
= help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
--> tests/ui/rename.rs:64:9
--> tests/ui/rename.rs:65:9
|
LL | #![warn(clippy::blacklisted_name)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions`
--> tests/ui/rename.rs:65:9
--> tests/ui/rename.rs:66:9
|
LL | #![warn(clippy::block_in_if_condition_expr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions`
--> tests/ui/rename.rs:66:9
--> tests/ui/rename.rs:67:9
|
LL | #![warn(clippy::block_in_if_condition_stmt)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions`
--> tests/ui/rename.rs:67:9
--> tests/ui/rename.rs:68:9
|
LL | #![warn(clippy::blocks_in_if_conditions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
--> tests/ui/rename.rs:68:9
--> tests/ui/rename.rs:69:9
|
LL | #![warn(clippy::box_vec)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
--> tests/ui/rename.rs:69:9
--> tests/ui/rename.rs:70:9
|
LL | #![warn(clippy::const_static_lifetime)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
--> tests/ui/rename.rs:70:9
--> tests/ui/rename.rs:71:9
|
LL | #![warn(clippy::cyclomatic_complexity)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
--> tests/ui/rename.rs:71:9
--> tests/ui/rename.rs:72:9
|
LL | #![warn(clippy::derive_hash_xor_eq)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
--> tests/ui/rename.rs:72:9
--> tests/ui/rename.rs:73:9
|
LL | #![warn(clippy::disallowed_method)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
--> tests/ui/rename.rs:73:9
--> tests/ui/rename.rs:74:9
|
LL | #![warn(clippy::disallowed_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
--> tests/ui/rename.rs:74:9
--> tests/ui/rename.rs:75:9
|
LL | #![warn(clippy::eval_order_dependence)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map`
--> tests/ui/rename.rs:75:9
--> tests/ui/rename.rs:76:9
|
LL | #![warn(clippy::find_map)]
| ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map`
error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map`
--> tests/ui/rename.rs:76:9
--> tests/ui/rename.rs:77:9
|
LL | #![warn(clippy::filter_map)]
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_filter_map`
error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons`
--> tests/ui/rename.rs:78:9
|
LL | #![warn(clippy::fn_address_comparisons)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons`
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
--> tests/ui/rename.rs:77:9
--> tests/ui/rename.rs:79:9
|
LL | #![warn(clippy::identity_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching`
--> tests/ui/rename.rs:78:9
--> tests/ui/rename.rs:80:9
|
LL | #![warn(clippy::if_let_redundant_pattern_matching)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_pattern_matching`
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
--> tests/ui/rename.rs:79:9
--> tests/ui/rename.rs:81:9
|
LL | #![warn(clippy::if_let_some_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
--> tests/ui/rename.rs:80:9
--> tests/ui/rename.rs:82:9
|
LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
--> tests/ui/rename.rs:81:9
--> tests/ui/rename.rs:83:9
|
LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
--> tests/ui/rename.rs:82:9
--> tests/ui/rename.rs:84:9
|
LL | #![warn(clippy::integer_arithmetic)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
--> tests/ui/rename.rs:83:9
--> tests/ui/rename.rs:85:9
|
LL | #![warn(clippy::logic_bug)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
--> tests/ui/rename.rs:84:9
--> tests/ui/rename.rs:86:9
|
LL | #![warn(clippy::new_without_default_derive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
--> tests/ui/rename.rs:85:9
--> tests/ui/rename.rs:87:9
|
LL | #![warn(clippy::option_and_then_some)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
--> tests/ui/rename.rs:86:9
--> tests/ui/rename.rs:88:9
|
LL | #![warn(clippy::option_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
--> tests/ui/rename.rs:87:9
--> tests/ui/rename.rs:89:9
|
LL | #![warn(clippy::option_map_unwrap_or)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
--> tests/ui/rename.rs:88:9
--> tests/ui/rename.rs:90:9
|
LL | #![warn(clippy::option_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
--> tests/ui/rename.rs:89:9
--> tests/ui/rename.rs:91:9
|
LL | #![warn(clippy::option_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks`
--> tests/ui/rename.rs:90:9
--> tests/ui/rename.rs:92:9
|
LL | #![warn(clippy::overflow_check_conditional)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks`
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
--> tests/ui/rename.rs:91:9
--> tests/ui/rename.rs:93:9
|
LL | #![warn(clippy::ref_in_deref)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
--> tests/ui/rename.rs:92:9
--> tests/ui/rename.rs:94:9
|
LL | #![warn(clippy::result_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
--> tests/ui/rename.rs:93:9
--> tests/ui/rename.rs:95:9
|
LL | #![warn(clippy::result_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
--> tests/ui/rename.rs:94:9
--> tests/ui/rename.rs:96:9
|
LL | #![warn(clippy::result_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
--> tests/ui/rename.rs:95:9
--> tests/ui/rename.rs:97:9
|
LL | #![warn(clippy::single_char_push_str)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
--> tests/ui/rename.rs:96:9
--> tests/ui/rename.rs:98:9
|
LL | #![warn(clippy::stutter)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
error: lint `clippy::thread_local_initializer_can_be_made_const` has been renamed to `clippy::missing_const_for_thread_local`
--> tests/ui/rename.rs:97:9
--> tests/ui/rename.rs:99:9
|
LL | #![warn(clippy::thread_local_initializer_can_be_made_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::missing_const_for_thread_local`
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
--> tests/ui/rename.rs:98:9
--> tests/ui/rename.rs:100:9
|
LL | #![warn(clippy::to_string_in_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
--> tests/ui/rename.rs:99:9
--> tests/ui/rename.rs:101:9
|
LL | #![warn(clippy::unwrap_or_else_default)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
--> tests/ui/rename.rs:100:9
--> tests/ui/rename.rs:102:9
|
LL | #![warn(clippy::zero_width_space)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
--> tests/ui/rename.rs:101:9
--> tests/ui/rename.rs:103:9
|
LL | #![warn(clippy::cast_ref_to_mut)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
--> tests/ui/rename.rs:102:9
--> tests/ui/rename.rs:104:9
|
LL | #![warn(clippy::clone_double_ref)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
--> tests/ui/rename.rs:103:9
--> tests/ui/rename.rs:105:9
|
LL | #![warn(clippy::cmp_nan)]
| ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
--> tests/ui/rename.rs:104:9
--> tests/ui/rename.rs:106:9
|
LL | #![warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
--> tests/ui/rename.rs:105:9
--> tests/ui/rename.rs:107:9
|
LL | #![warn(clippy::drop_copy)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
error: lint `clippy::drop_ref` has been renamed to `dropping_references`
--> tests/ui/rename.rs:106:9
--> tests/ui/rename.rs:108:9
|
LL | #![warn(clippy::drop_ref)]
| ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
--> tests/ui/rename.rs:107:9
--> tests/ui/rename.rs:109:9
|
LL | #![warn(clippy::fn_null_check)]
| ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
--> tests/ui/rename.rs:108:9
--> tests/ui/rename.rs:110:9
|
LL | #![warn(clippy::for_loop_over_option)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
--> tests/ui/rename.rs:109:9
--> tests/ui/rename.rs:111:9
|
LL | #![warn(clippy::for_loop_over_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
--> tests/ui/rename.rs:110:9
--> tests/ui/rename.rs:112:9
|
LL | #![warn(clippy::for_loops_over_fallibles)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
--> tests/ui/rename.rs:111:9
--> tests/ui/rename.rs:113:9
|
LL | #![warn(clippy::forget_copy)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
--> tests/ui/rename.rs:112:9
--> tests/ui/rename.rs:114:9
|
LL | #![warn(clippy::forget_ref)]
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
--> tests/ui/rename.rs:113:9
--> tests/ui/rename.rs:115:9
|
LL | #![warn(clippy::into_iter_on_array)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
--> tests/ui/rename.rs:114:9
--> tests/ui/rename.rs:116:9
|
LL | #![warn(clippy::invalid_atomic_ordering)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
--> tests/ui/rename.rs:115:9
--> tests/ui/rename.rs:117:9
|
LL | #![warn(clippy::invalid_ref)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
--> tests/ui/rename.rs:116:9
--> tests/ui/rename.rs:118:9
|
LL | #![warn(clippy::invalid_utf8_in_unchecked)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
--> tests/ui/rename.rs:117:9
--> tests/ui/rename.rs:119:9
|
LL | #![warn(clippy::let_underscore_drop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs`
--> tests/ui/rename.rs:118:9
--> tests/ui/rename.rs:120:9
|
LL | #![warn(clippy::maybe_misused_cfg)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
--> tests/ui/rename.rs:119:9
--> tests/ui/rename.rs:121:9
|
LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs`
--> tests/ui/rename.rs:120:9
--> tests/ui/rename.rs:122:9
|
LL | #![warn(clippy::mismatched_target_os)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
--> tests/ui/rename.rs:121:9
--> tests/ui/rename.rs:123:9
|
LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
--> tests/ui/rename.rs:122:9
--> tests/ui/rename.rs:124:9
|
LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
--> tests/ui/rename.rs:123:9
--> tests/ui/rename.rs:125:9
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
--> tests/ui/rename.rs:124:9
--> tests/ui/rename.rs:126:9
|
LL | #![warn(clippy::undropped_manually_drops)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
--> tests/ui/rename.rs:125:9
--> tests/ui/rename.rs:127:9
|
LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels`
--> tests/ui/rename.rs:126:9
--> tests/ui/rename.rs:128:9
|
LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
--> tests/ui/rename.rs:127:9
--> tests/ui/rename.rs:129:9
|
LL | #![warn(clippy::vtable_address_comparisons)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges`
--> tests/ui/rename.rs:128:9
--> tests/ui/rename.rs:130:9
|
LL | #![warn(clippy::reverse_range_loop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`
error: aborting due to 66 previous errors
error: aborting due to 67 previous errors

View file

@ -1,3 +1,5 @@
#![allow(unpredictable_function_pointer_comparisons)]
use std::mem;
trait Answer {

View file

@ -1,3 +1,5 @@
#![allow(unpredictable_function_pointer_comparisons)]
type BuiltIn = for<'a> fn(&str);
struct Function {

View file

@ -1,6 +1,9 @@
//@ run-pass
// Tests equality between supertype and subtype of a function
// See the issue #91636
#![allow(unpredictable_function_pointer_comparisons)]
fn foo(_a: &str) {}
fn main() {

View file

@ -1,6 +1,9 @@
//@ run-pass
// We used to have a __rust_abi shim that resulted in duplicated symbols
// whenever the item path wasn't enough to disambiguate between them.
#![allow(unpredictable_function_pointer_comparisons)]
fn main() {
let a = {
extern "C" fn good() -> i32 { return 0; }

View file

@ -1,5 +1,7 @@
//@ run-pass
#![allow(non_upper_case_globals)]
#![allow(unpredictable_function_pointer_comparisons)]
extern "C" fn foopy() {}

View file

@ -1,6 +1,8 @@
//@ run-pass
//@ aux-build:cci_const.rs
#![allow(non_upper_case_globals)]
#![allow(unpredictable_function_pointer_comparisons)]
extern crate cci_const;
use cci_const::bar;

View file

@ -2,6 +2,7 @@
// Tests that we can compare various kinds of extern fn signatures.
#![allow(non_camel_case_types)]
#![allow(unpredictable_function_pointer_comparisons)]
// `dbg!()` differentiates these functions to ensure they won't be merged.
extern "C" fn voidret1() { dbg!() }

View file

@ -1,6 +1,8 @@
//@ run-pass
//@ aux-build:extern-take-value.rs
#![allow(unpredictable_function_pointer_comparisons)]
extern crate extern_take_value;
pub fn main() {

View file

@ -1,6 +1,8 @@
//@ compile-flags: -C opt-level=3
//@ run-pass
#![allow(unpredictable_function_pointer_comparisons)]
fn foo(_i: i32) -> i32 {
1
}

View file

@ -1,5 +1,7 @@
//@ run-pass
#![allow(unpredictable_function_pointer_comparisons)]
fn main() {
// We shouldn't promote this
let _ = &(main as fn() == main as fn());

View file

@ -0,0 +1,15 @@
//@ check-pass
fn main() {
let f: fn() = main;
let g: fn() = main;
let _ = f > g;
//~^ WARN function pointer comparisons
let _ = f >= g;
//~^ WARN function pointer comparisons
let _ = f <= g;
//~^ WARN function pointer comparisons
let _ = f < g;
//~^ WARN function pointer comparisons
}

View file

@ -0,0 +1,43 @@
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
|
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
|
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>
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
|
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>
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>
warning: 4 warnings emitted

View file

@ -0,0 +1,58 @@
//@ check-pass
//@ run-rustfix
extern "C" {
fn test();
}
fn a() {}
extern "C" fn c() {}
extern "C" fn args(_a: i32) -> i32 { 0 }
#[derive(PartialEq, Eq)]
struct A {
f: fn(),
}
fn main() {
let f: fn() = a;
let g: fn() = f;
let a1 = A { f };
let a2 = A { f };
let _ = std::ptr::fn_addr_eq(f, a as fn());
//~^ WARN function pointer comparisons
let _ = !std::ptr::fn_addr_eq(f, a as fn());
//~^ WARN function pointer comparisons
let _ = std::ptr::fn_addr_eq(f, g);
//~^ WARN function pointer comparisons
let _ = std::ptr::fn_addr_eq(f, f);
//~^ WARN function pointer comparisons
let _ = std::ptr::fn_addr_eq(g, g);
//~^ WARN function pointer comparisons
let _ = std::ptr::fn_addr_eq(g, g);
//~^ WARN function pointer comparisons
let _ = std::ptr::fn_addr_eq(g, g);
//~^ WARN function pointer comparisons
let _ = std::ptr::fn_addr_eq(a as fn(), g);
//~^ WARN function pointer comparisons
let cfn: extern "C" fn() = c;
let _ = std::ptr::fn_addr_eq(cfn, c as extern "C" fn());
//~^ WARN function pointer comparisons
let argsfn: extern "C" fn(i32) -> i32 = args;
let _ = std::ptr::fn_addr_eq(argsfn, args as extern "C" fn(i32) -> i32);
//~^ WARN function pointer comparisons
let t: unsafe extern "C" fn() = test;
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
}

View file

@ -0,0 +1,58 @@
//@ check-pass
//@ run-rustfix
extern "C" {
fn test();
}
fn a() {}
extern "C" fn c() {}
extern "C" fn args(_a: i32) -> i32 { 0 }
#[derive(PartialEq, Eq)]
struct A {
f: fn(),
}
fn main() {
let f: fn() = a;
let g: fn() = f;
let a1 = A { f };
let a2 = A { f };
let _ = f == a;
//~^ WARN function pointer comparisons
let _ = f != a;
//~^ WARN function pointer comparisons
let _ = f == g;
//~^ WARN function pointer comparisons
let _ = f == f;
//~^ WARN function pointer comparisons
let _ = g == g;
//~^ WARN function pointer comparisons
let _ = g == g;
//~^ WARN function pointer comparisons
let _ = &g == &g;
//~^ WARN function pointer comparisons
let _ = a as fn() == g;
//~^ WARN function pointer comparisons
let cfn: extern "C" fn() = c;
let _ = cfn == c;
//~^ WARN function pointer comparisons
let argsfn: extern "C" fn(i32) -> i32 = args;
let _ = argsfn == args;
//~^ WARN function pointer comparisons
let t: unsafe extern "C" fn() = test;
let _ = t == test;
//~^ WARN function pointer comparisons
let _ = a1 == a2; // should not warn
let _ = a1.f == a2.f;
//~^ WARN function pointer comparisons
}

View file

@ -0,0 +1,171 @@
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
|
LL | let _ = f == a;
| ^^^^^^
|
= 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
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = f != a;
| ^^^^^^
|
= 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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = f == f;
| ^^^^^^
|
= 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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = 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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = 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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = &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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = a as fn() == 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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = cfn == c;
| ^^^^^^^^
|
= 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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = argsfn == args;
| ^^^^^^^^^^^^^^
|
= 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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = t == test;
| ^^^^^^^^^
|
= 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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
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
|
LL | let _ = a1.f == a2.f;
| ^^^^^^^^^^^^
|
= 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>
help: refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint
|
LL | let _ = std::ptr::fn_addr_eq(a1.f, a2.f);
| +++++++++++++++++++++ ~ +
warning: 12 warnings emitted

View file

@ -1,6 +1,8 @@
//@ check-pass
//@ compile-flags: -Zvalidate-mir
#![allow(unpredictable_function_pointer_comparisons)]
fn foo(_a: &str) {}
fn main() {