]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/unnamed_address.rs
New upstream version 1.72.1+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / unnamed_address.rs
CommitLineData
cdc7bbd5
XL
1use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
2use clippy_utils::{match_def_path, paths};
f20569fa
XL
3use if_chain::if_chain;
4use rustc_hir::{BinOpKind, Expr, ExprKind};
5use rustc_lint::{LateContext, LateLintPass};
6use rustc_middle::ty;
7use rustc_session::{declare_lint_pass, declare_tool_lint};
8
9declare_clippy_lint! {
94222f64
XL
10 /// ### What it does
11 /// Checks for comparisons with an address of a function item.
f20569fa 12 ///
94222f64
XL
13 /// ### Why is this bad?
14 /// Function item address is not guaranteed to be unique and could vary
f20569fa
XL
15 /// between different code generation units. Furthermore different function items could have
16 /// the same address after being merged together.
17 ///
94222f64 18 /// ### Example
f20569fa
XL
19 /// ```rust
20 /// type F = fn();
21 /// fn a() {}
22 /// let f: F = a;
23 /// if f == a {
24 /// // ...
25 /// }
26 /// ```
a2a8927a 27 #[clippy::version = "1.44.0"]
f20569fa
XL
28 pub FN_ADDRESS_COMPARISONS,
29 correctness,
30 "comparison with an address of a function item"
31}
32
33declare_clippy_lint! {
94222f64
XL
34 /// ### What it does
35 /// Checks for comparisons with an address of a trait vtable.
f20569fa 36 ///
94222f64
XL
37 /// ### Why is this bad?
38 /// Comparing trait objects pointers compares an vtable addresses which
f20569fa
XL
39 /// are not guaranteed to be unique and could vary between different code generation units.
40 /// Furthermore vtables for different types could have the same address after being merged
41 /// together.
42 ///
94222f64 43 /// ### Example
f20569fa
XL
44 /// ```rust,ignore
45 /// let a: Rc<dyn Trait> = ...
46 /// let b: Rc<dyn Trait> = ...
47 /// if Rc::ptr_eq(&a, &b) {
48 /// ...
49 /// }
50 /// ```
a2a8927a 51 #[clippy::version = "1.44.0"]
f20569fa
XL
52 pub VTABLE_ADDRESS_COMPARISONS,
53 correctness,
54 "comparison with an address of a trait vtable"
55}
56
57declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS, VTABLE_ADDRESS_COMPARISONS]);
58
59impl LateLintPass<'_> for UnnamedAddress {
60 fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
61 fn is_comparison(binop: BinOpKind) -> bool {
62 matches!(
63 binop,
64 BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt
65 )
66 }
67
68 fn is_trait_ptr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
69 match cx.typeck_results().expr_ty_adjusted(expr).kind() {
70 ty::RawPtr(ty::TypeAndMut { ty, .. }) => ty.is_trait(),
71 _ => false,
72 }
73 }
74
75 fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
76 matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..))
77 }
78
79 if_chain! {
cdc7bbd5 80 if let ExprKind::Binary(binop, left, right) = expr.kind;
f20569fa
XL
81 if is_comparison(binop.node);
82 if is_trait_ptr(cx, left) && is_trait_ptr(cx, right);
83 then {
84 span_lint_and_help(
85 cx,
86 VTABLE_ADDRESS_COMPARISONS,
87 expr.span,
88 "comparing trait object pointers compares a non-unique vtable address",
89 None,
90 "consider extracting and comparing data pointers only",
91 );
92 }
93 }
94
95 if_chain! {
cdc7bbd5 96 if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind;
f20569fa
XL
97 if let ExprKind::Path(ref func_qpath) = func.kind;
98 if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
fe692bf9 99 if match_def_path(cx, def_id, &paths::PTR_EQ);
f20569fa
XL
100 let ty_param = cx.typeck_results().node_substs(func.hir_id).type_at(0);
101 if ty_param.is_trait();
102 then {
103 span_lint_and_help(
104 cx,
105 VTABLE_ADDRESS_COMPARISONS,
106 expr.span,
107 "comparing trait object pointers compares a non-unique vtable address",
108 None,
109 "consider extracting and comparing data pointers only",
110 );
111 }
112 }
113
114 if_chain! {
cdc7bbd5 115 if let ExprKind::Binary(binop, left, right) = expr.kind;
f20569fa 116 if is_comparison(binop.node);
cdc7bbd5
XL
117 if cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr();
118 if cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr();
f20569fa
XL
119 if is_fn_def(cx, left) || is_fn_def(cx, right);
120 then {
121 span_lint(
122 cx,
123 FN_ADDRESS_COMPARISONS,
124 expr.span,
125 "comparing with a non-unique address of a function item",
126 );
127 }
128 }
129 }
130}