about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/casts/cast_ref_to_mut.rs28
-rw-r--r--clippy_lints/src/casts/mod.rs99
-rw-r--r--clippy_lints/src/lib.rs1
3 files changed, 68 insertions, 60 deletions
diff --git a/clippy_lints/src/casts/cast_ref_to_mut.rs b/clippy_lints/src/casts/cast_ref_to_mut.rs
new file mode 100644
index 00000000000..3fdc1c6168b
--- /dev/null
+++ b/clippy_lints/src/casts/cast_ref_to_mut.rs
@@ -0,0 +1,28 @@
+use rustc_hir::{Expr, ExprKind, MutTy, Mutability, TyKind, UnOp};
+use rustc_lint::LateContext;
+use rustc_middle::ty;
+
+use if_chain::if_chain;
+
+use crate::utils::span_lint;
+
+use super::CAST_REF_TO_MUT;
+
+pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+    if_chain! {
+        if let ExprKind::Unary(UnOp::Deref, e) = &expr.kind;
+        if let ExprKind::Cast(e, t) = &e.kind;
+        if let TyKind::Ptr(MutTy { mutbl: Mutability::Mut, .. }) = t.kind;
+        if let ExprKind::Cast(e, t) = &e.kind;
+        if let TyKind::Ptr(MutTy { mutbl: Mutability::Not, .. }) = t.kind;
+        if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind();
+        then {
+            span_lint(
+                cx,
+                CAST_REF_TO_MUT,
+                expr.span,
+                "casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`",
+            );
+        }
+    }
+}
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index cf8a64e1fd8..7d5ada18be3 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -3,6 +3,7 @@ mod cast_possible_truncation;
 mod cast_possible_wrap;
 mod cast_precision_loss;
 mod cast_ptr_alignment;
+mod cast_ref_to_mut;
 mod cast_sign_loss;
 mod fn_to_numeric_cast;
 mod fn_to_numeric_cast_with_truncation;
@@ -14,7 +15,7 @@ use std::borrow::Cow;
 use if_chain::if_chain;
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, MutTy, Mutability, TyKind, UnOp};
+use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, TypeAndMut, UintTy};
@@ -23,7 +24,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
 
 use crate::utils::sugg::Sugg;
 use crate::utils::{
-    is_hir_ty_cfg_dependant, meets_msrv, snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then,
+    is_hir_ty_cfg_dependant, meets_msrv, snippet_with_applicability, span_lint_and_sugg, span_lint_and_then,
 };
 
 declare_clippy_lint! {
@@ -255,12 +256,47 @@ declare_clippy_lint! {
     "casting a function pointer to a numeric type not wide enough to store the address"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
+    ///
+    /// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
+    /// `UnsafeCell` is the only way to obtain aliasable data that is considered
+    /// mutable.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust,ignore
+    /// fn x(r: &i32) {
+    ///     unsafe {
+    ///         *(r as *const _ as *mut _) += 1;
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// Instead consider using interior mutability types.
+    ///
+    /// ```rust
+    /// use std::cell::UnsafeCell;
+    ///
+    /// fn x(r: &UnsafeCell<i32>) {
+    ///     unsafe {
+    ///         *r.get() += 1;
+    ///     }
+    /// }
+    /// ```
+    pub CAST_REF_TO_MUT,
+    correctness,
+    "a cast of reference to a mutable pointer"
+}
+
 declare_lint_pass!(Casts => [
     CAST_PRECISION_LOSS,
     CAST_SIGN_LOSS,
     CAST_POSSIBLE_TRUNCATION,
     CAST_POSSIBLE_WRAP,
     CAST_LOSSLESS,
+    CAST_REF_TO_MUT,
     UNNECESSARY_CAST,
     CAST_PTR_ALIGNMENT,
     FN_TO_NUMERIC_CAST,
@@ -269,6 +305,8 @@ declare_lint_pass!(Casts => [
 
 impl<'tcx> LateLintPass<'tcx> for Casts {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        cast_ref_to_mut::check(cx, expr);
+
         if expr.span.from_expansion() {
             return;
         }
@@ -300,63 +338,6 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
     }
 }
 
-declare_clippy_lint! {
-    /// **What it does:** Checks for casts of `&T` to `&mut T` anywhere in the code.
-    ///
-    /// **Why is this bad?** It’s basically guaranteed to be undefined behaviour.
-    /// `UnsafeCell` is the only way to obtain aliasable data that is considered
-    /// mutable.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```rust,ignore
-    /// fn x(r: &i32) {
-    ///     unsafe {
-    ///         *(r as *const _ as *mut _) += 1;
-    ///     }
-    /// }
-    /// ```
-    ///
-    /// Instead consider using interior mutability types.
-    ///
-    /// ```rust
-    /// use std::cell::UnsafeCell;
-    ///
-    /// fn x(r: &UnsafeCell<i32>) {
-    ///     unsafe {
-    ///         *r.get() += 1;
-    ///     }
-    /// }
-    /// ```
-    pub CAST_REF_TO_MUT,
-    correctness,
-    "a cast of reference to a mutable pointer"
-}
-
-declare_lint_pass!(RefToMut => [CAST_REF_TO_MUT]);
-
-impl<'tcx> LateLintPass<'tcx> for RefToMut {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            if let ExprKind::Unary(UnOp::Deref, e) = &expr.kind;
-            if let ExprKind::Cast(e, t) = &e.kind;
-            if let TyKind::Ptr(MutTy { mutbl: Mutability::Mut, .. }) = t.kind;
-            if let ExprKind::Cast(e, t) = &e.kind;
-            if let TyKind::Ptr(MutTy { mutbl: Mutability::Not, .. }) = t.kind;
-            if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind();
-            then {
-                span_lint(
-                    cx,
-                    CAST_REF_TO_MUT,
-                    expr.span,
-                    "casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`",
-                );
-            }
-        }
-    }
-}
-
 const PTR_AS_PTR_MSRV: RustcVersion = RustcVersion::new(1, 38, 0);
 
 declare_clippy_lint! {
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index a46c56a01d5..47afd7beb74 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -1176,7 +1176,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
     store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy);
     store.register_late_pass(|| box unnecessary_wraps::UnnecessaryWraps);
-    store.register_late_pass(|| box casts::RefToMut);
     store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
     store.register_late_pass(|| box transmuting_null::TransmutingNull);
     store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite);