Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit f33bb3d

Browse files
committed
Move cast_ref_to_mut to its own module
1 parent ebd1ec0 commit f33bb3d

File tree

3 files changed

+68
-60
lines changed

3 files changed

+68
-60
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use rustc_hir::{Expr, ExprKind, MutTy, Mutability, TyKind, UnOp};
2+
use rustc_lint::LateContext;
3+
use rustc_middle::ty;
4+
5+
use if_chain::if_chain;
6+
7+
use crate::utils::span_lint;
8+
9+
use super::CAST_REF_TO_MUT;
10+
11+
pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
12+
if_chain! {
13+
if let ExprKind::Unary(UnOp::Deref, e) = &expr.kind;
14+
if let ExprKind::Cast(e, t) = &e.kind;
15+
if let TyKind::Ptr(MutTy { mutbl: Mutability::Mut, .. }) = t.kind;
16+
if let ExprKind::Cast(e, t) = &e.kind;
17+
if let TyKind::Ptr(MutTy { mutbl: Mutability::Not, .. }) = t.kind;
18+
if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind();
19+
then {
20+
span_lint(
21+
cx,
22+
CAST_REF_TO_MUT,
23+
expr.span,
24+
"casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`",
25+
);
26+
}
27+
}
28+
}

clippy_lints/src/casts/mod.rs

Lines changed: 40 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod cast_possible_truncation;
33
mod cast_possible_wrap;
44
mod cast_precision_loss;
55
mod cast_ptr_alignment;
6+
mod cast_ref_to_mut;
67
mod cast_sign_loss;
78
mod fn_to_numeric_cast;
89
mod fn_to_numeric_cast_with_truncation;
@@ -14,7 +15,7 @@ use std::borrow::Cow;
1415
use if_chain::if_chain;
1516
use rustc_ast::LitKind;
1617
use rustc_errors::Applicability;
17-
use rustc_hir::{Expr, ExprKind, MutTy, Mutability, TyKind, UnOp};
18+
use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
1819
use rustc_lint::{LateContext, LateLintPass, LintContext};
1920
use rustc_middle::lint::in_external_macro;
2021
use rustc_middle::ty::{self, TypeAndMut, UintTy};
@@ -23,7 +24,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
2324

2425
use crate::utils::sugg::Sugg;
2526
use crate::utils::{
26-
is_hir_ty_cfg_dependant, meets_msrv, snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then,
27+
is_hir_ty_cfg_dependant, meets_msrv, snippet_with_applicability, span_lint_and_sugg, span_lint_and_then,
2728
};
2829

2930
declare_clippy_lint! {
@@ -255,12 +256,47 @@ declare_clippy_lint! {
255256
"casting a function pointer to a numeric type not wide enough to store the address"
256257
}
257258

259+
declare_clippy_lint! {
260+
/// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
261+
///
262+
/// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
263+
/// `UnsafeCell` is the only way to obtain aliasable data that is considered
264+
/// mutable.
265+
///
266+
/// **Known problems:** None.
267+
///
268+
/// **Example:**
269+
/// ```rust,ignore
270+
/// fn x(r: &i32) {
271+
/// unsafe {
272+
/// *(r as *const _ as *mut _) += 1;
273+
/// }
274+
/// }
275+
/// ```
276+
///
277+
/// Instead consider using interior mutability types.
278+
///
279+
/// ```rust
280+
/// use std::cell::UnsafeCell;
281+
///
282+
/// fn x(r: &UnsafeCell<i32>) {
283+
/// unsafe {
284+
/// *r.get() += 1;
285+
/// }
286+
/// }
287+
/// ```
288+
pub CAST_REF_TO_MUT,
289+
correctness,
290+
"a cast of reference to a mutable pointer"
291+
}
292+
258293
declare_lint_pass!(Casts => [
259294
CAST_PRECISION_LOSS,
260295
CAST_SIGN_LOSS,
261296
CAST_POSSIBLE_TRUNCATION,
262297
CAST_POSSIBLE_WRAP,
263298
CAST_LOSSLESS,
299+
CAST_REF_TO_MUT,
264300
UNNECESSARY_CAST,
265301
CAST_PTR_ALIGNMENT,
266302
FN_TO_NUMERIC_CAST,
@@ -269,6 +305,8 @@ declare_lint_pass!(Casts => [
269305

270306
impl<'tcx> LateLintPass<'tcx> for Casts {
271307
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
308+
cast_ref_to_mut::check(cx, expr);
309+
272310
if expr.span.from_expansion() {
273311
return;
274312
}
@@ -300,63 +338,6 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
300338
}
301339
}
302340

303-
declare_clippy_lint! {
304-
/// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
305-
///
306-
/// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
307-
/// `UnsafeCell` is the only way to obtain aliasable data that is considered
308-
/// mutable.
309-
///
310-
/// **Known problems:** None.
311-
///
312-
/// **Example:**
313-
/// ```rust,ignore
314-
/// fn x(r: &i32) {
315-
/// unsafe {
316-
/// *(r as *const _ as *mut _) += 1;
317-
/// }
318-
/// }
319-
/// ```
320-
///
321-
/// Instead consider using interior mutability types.
322-
///
323-
/// ```rust
324-
/// use std::cell::UnsafeCell;
325-
///
326-
/// fn x(r: &UnsafeCell<i32>) {
327-
/// unsafe {
328-
/// *r.get() += 1;
329-
/// }
330-
/// }
331-
/// ```
332-
pub CAST_REF_TO_MUT,
333-
correctness,
334-
"a cast of reference to a mutable pointer"
335-
}
336-
337-
declare_lint_pass!(RefToMut => [CAST_REF_TO_MUT]);
338-
339-
impl<'tcx> LateLintPass<'tcx> for RefToMut {
340-
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
341-
if_chain! {
342-
if let ExprKind::Unary(UnOp::Deref, e) = &expr.kind;
343-
if let ExprKind::Cast(e, t) = &e.kind;
344-
if let TyKind::Ptr(MutTy { mutbl: Mutability::Mut, .. }) = t.kind;
345-
if let ExprKind::Cast(e, t) = &e.kind;
346-
if let TyKind::Ptr(MutTy { mutbl: Mutability::Not, .. }) = t.kind;
347-
if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind();
348-
then {
349-
span_lint(
350-
cx,
351-
CAST_REF_TO_MUT,
352-
expr.span,
353-
"casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`",
354-
);
355-
}
356-
}
357-
}
358-
}
359-
360341
const PTR_AS_PTR_MSRV: RustcVersion = RustcVersion::new(1, 38, 0);
361342

362343
declare_clippy_lint! {

clippy_lints/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11761176
store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
11771177
store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy);
11781178
store.register_late_pass(|| box unnecessary_wraps::UnnecessaryWraps);
1179-
store.register_late_pass(|| box casts::RefToMut);
11801179
store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
11811180
store.register_late_pass(|| box transmuting_null::TransmutingNull);
11821181
store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite);

0 commit comments

Comments
 (0)