2023-12-22 14:56:20 +03:00
|
|
|
use rustc_hir as hir;
|
|
|
|
use rustc_hir_pretty::qpath_to_string;
|
2024-02-17 22:01:56 +03:00
|
|
|
use rustc_lint_defs::builtin::STATIC_MUT_REFS;
|
2024-02-27 18:11:23 +00:00
|
|
|
use rustc_middle::ty::{Mutability, TyCtxt};
|
2023-12-22 14:56:20 +03:00
|
|
|
use rustc_span::Span;
|
|
|
|
|
|
|
|
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)
|
2024-04-14 10:26:59 -04:00
|
|
|
&& let Some(var) = path_if_static_mut(tcx, expr)
|
2023-12-22 14:56:20 +03:00
|
|
|
{
|
2024-03-23 21:04:45 -04:00
|
|
|
handle_static_mut_ref(tcx, span, var, span.edition().at_least_rust_2024(), m, hir_id);
|
2023-12-22 14:56:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-22 15:00:25 +03:00
|
|
|
/// Check for shared or mutable references of `static mut` inside statement
|
|
|
|
pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
|
2024-03-14 11:53:38 +01:00
|
|
|
if let hir::StmtKind::Let(loc) = stmt.kind
|
2023-12-22 15:00:25 +03:00
|
|
|
&& let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
|
2024-03-23 21:04:45 -04:00
|
|
|
&& let hir::ByRef::Yes(rmutbl) = ba.0
|
2023-12-22 15:00:25 +03:00
|
|
|
&& let Some(init) = loc.init
|
2024-04-14 10:26:59 -04:00
|
|
|
&& let Some(var) = path_if_static_mut(tcx, init)
|
2023-12-22 15:00:25 +03:00
|
|
|
{
|
|
|
|
handle_static_mut_ref(
|
|
|
|
tcx,
|
|
|
|
init.span,
|
|
|
|
var,
|
|
|
|
loc.span.edition().at_least_rust_2024(),
|
2024-03-23 21:04:45 -04:00
|
|
|
rmutbl,
|
2023-12-22 15:00:25 +03:00
|
|
|
stmt.hir_id,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-14 10:26:59 -04:00
|
|
|
fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option<String> {
|
2023-12-22 14:56:20 +03:00
|
|
|
if let hir::ExprKind::Path(qpath) = expr.kind
|
|
|
|
&& let hir::QPath::Resolved(_, path) = qpath
|
|
|
|
&& let hir::def::Res::Def(def_kind, _) = path.res
|
2024-03-11 17:33:57 +00:00
|
|
|
&& let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind
|
2023-12-22 14:56:20 +03:00
|
|
|
{
|
2024-04-14 10:26:59 -04:00
|
|
|
return Some(qpath_to_string(&tcx, &qpath));
|
2023-12-22 14:56:20 +03:00
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
fn handle_static_mut_ref(
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
span: Span,
|
|
|
|
var: String,
|
|
|
|
e2024: bool,
|
2024-03-23 21:04:45 -04:00
|
|
|
mutable: Mutability,
|
2023-12-22 14:56:20 +03:00
|
|
|
hir_id: hir::HirId,
|
|
|
|
) {
|
|
|
|
if e2024 {
|
2024-03-23 21:04:45 -04:00
|
|
|
let (sugg, shared) = if mutable == Mutability::Mut {
|
2024-02-17 22:01:56 +03:00
|
|
|
(errors::StaticMutRefSugg::Mut { span, var }, "mutable")
|
2023-12-22 14:56:20 +03:00
|
|
|
} else {
|
2024-02-17 22:01:56 +03:00
|
|
|
(errors::StaticMutRefSugg::Shared { span, var }, "shared")
|
2023-12-22 14:56:20 +03:00
|
|
|
};
|
2024-03-04 16:31:49 +11:00
|
|
|
tcx.sess.psess.dcx.emit_err(errors::StaticMutRef { span, sugg, shared });
|
2023-12-22 14:56:20 +03:00
|
|
|
} else {
|
2024-03-23 21:04:45 -04:00
|
|
|
let (sugg, shared) = if mutable == Mutability::Mut {
|
|
|
|
(errors::RefOfMutStaticSugg::Mut { span, var }, "mutable")
|
|
|
|
} else {
|
|
|
|
(errors::RefOfMutStaticSugg::Shared { span, var }, "shared")
|
|
|
|
};
|
|
|
|
tcx.emit_node_span_lint(
|
|
|
|
STATIC_MUT_REFS,
|
|
|
|
hir_id,
|
|
|
|
span,
|
|
|
|
errors::RefOfMutStatic { span, sugg, shared },
|
|
|
|
);
|
|
|
|
}
|
2023-12-22 14:56:20 +03:00
|
|
|
}
|