forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherrs.rs
97 lines (91 loc) · 2.75 KB
/
errs.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use rustc_hir as hir;
use rustc_hir_pretty::qpath_to_string;
use rustc_lint_defs::builtin::STATIC_MUT_REF;
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;
use rustc_type_ir::Mutability;
use crate::errors;
/// Check for shared or mutable references of `static mut` inside expression
pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
let span = expr.span;
let hir_id = expr.hir_id;
if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind
&& matches!(borrow_kind, hir::BorrowKind::Ref)
&& let Some(var) = is_path_static_mut(*expr)
{
handle_static_mut_ref(
tcx,
span,
var,
span.edition().at_least_rust_2024(),
matches!(m, Mutability::Mut),
hir_id,
);
}
}
/// Check for shared or mutable references of `static mut` inside statement
pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
if let hir::StmtKind::Local(loc) = stmt.kind
&& let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
&& matches!(ba.0, rustc_ast::ByRef::Yes)
&& let Some(init) = loc.init
&& let Some(var) = is_path_static_mut(*init)
{
handle_static_mut_ref(
tcx,
init.span,
var,
loc.span.edition().at_least_rust_2024(),
matches!(ba.1, Mutability::Mut),
stmt.hir_id,
);
}
}
fn is_path_static_mut(expr: hir::Expr<'_>) -> Option<String> {
if let hir::ExprKind::Path(qpath) = expr.kind
&& let hir::QPath::Resolved(_, path) = qpath
&& let hir::def::Res::Def(def_kind, _) = path.res
&& let hir::def::DefKind::Static(mt) = def_kind
&& matches!(mt, Mutability::Mut)
{
return Some(qpath_to_string(&qpath));
}
None
}
fn handle_static_mut_ref(
tcx: TyCtxt<'_>,
span: Span,
var: String,
e2024: bool,
mutable: bool,
hir_id: hir::HirId,
) {
if e2024 {
let sugg = if mutable {
errors::StaticMutRefSugg::Mut { span, var }
} else {
errors::StaticMutRefSugg::Shared { span, var }
};
tcx.sess.parse_sess.dcx.emit_err(errors::StaticMutRef { span, sugg });
return;
}
let (label, sugg, shared) = if mutable {
(
errors::RefOfMutStaticLabel::Mut { span },
errors::RefOfMutStaticSugg::Mut { span, var },
"mutable ",
)
} else {
(
errors::RefOfMutStaticLabel::Shared { span },
errors::RefOfMutStaticSugg::Shared { span, var },
"shared ",
)
};
tcx.emit_spanned_lint(
STATIC_MUT_REF,
hir_id,
span,
errors::RefOfMutStatic { shared, why_note: (), label, sugg },
);
}