about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/casts/mod.rs26
-rw-r--r--clippy_lints/src/casts/zero_ptr.rs39
-rw-r--r--clippy_lints/src/declared_lints.rs2
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/misc.rs84
5 files changed, 75 insertions, 78 deletions
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index 88ffbb55486..b00130ffd76 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -20,6 +20,7 @@ mod ptr_as_ptr;
 mod ptr_cast_constness;
 mod unnecessary_cast;
 mod utils;
+mod zero_ptr;
 
 use clippy_utils::is_hir_ty_cfg_dependant;
 use clippy_utils::msrvs::{self, Msrv};
@@ -665,6 +666,29 @@ declare_clippy_lint! {
     "casting a known floating-point NaN into an integer"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Catch casts from `0` to some pointer type
+    ///
+    /// ### Why is this bad?
+    /// This generally means `null` and is better expressed as
+    /// {`std`, `core`}`::ptr::`{`null`, `null_mut`}.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let a = 0 as *const u32;
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// let a = std::ptr::null::<u32>();
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub ZERO_PTR,
+    style,
+    "using `0 as *{const, mut} T`"
+}
+
 pub struct Casts {
     msrv: Msrv,
 }
@@ -699,6 +723,7 @@ impl_lint_pass!(Casts => [
     CAST_SLICE_FROM_RAW_PARTS,
     AS_PTR_CAST_MUT,
     CAST_NAN_TO_INT,
+    ZERO_PTR,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Casts {
@@ -729,6 +754,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to);
             fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
             fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
+            zero_ptr::check(cx, expr, cast_expr, cast_to_hir);
 
             if cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
                 cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span);
diff --git a/clippy_lints/src/casts/zero_ptr.rs b/clippy_lints/src/casts/zero_ptr.rs
new file mode 100644
index 00000000000..5071af5ecb9
--- /dev/null
+++ b/clippy_lints/src/casts/zero_ptr.rs
@@ -0,0 +1,39 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{in_constant, is_integer_literal, std_or_core};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, Mutability, Ty, TyKind};
+use rustc_lint::LateContext;
+
+use super::ZERO_PTR;
+
+pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>) {
+    if let TyKind::Ptr(ref mut_ty) = to.kind
+        && is_integer_literal(from, 0)
+        && !in_constant(cx, from.hir_id)
+        && let Some(std_or_core) = std_or_core(cx)
+    {
+        let (msg, sugg_fn) = match mut_ty.mutbl {
+            Mutability::Mut => ("`0 as *mut _` detected", "ptr::null_mut"),
+            Mutability::Not => ("`0 as *const _` detected", "ptr::null"),
+        };
+
+        let sugg = if let TyKind::Infer = mut_ty.ty.kind {
+            format!("{std_or_core}::{sugg_fn}()")
+        } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
+            format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()")
+        } else {
+            return;
+        };
+
+        span_lint_and_sugg(
+            cx,
+            ZERO_PTR,
+            expr.span,
+            msg,
+            "try",
+            sugg,
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index aa2ca0e1149..4d1281ec1e7 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -97,6 +97,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::casts::PTR_AS_PTR_INFO,
     crate::casts::PTR_CAST_CONSTNESS_INFO,
     crate::casts::UNNECESSARY_CAST_INFO,
+    crate::casts::ZERO_PTR_INFO,
     crate::checked_conversions::CHECKED_CONVERSIONS_INFO,
     crate::cognitive_complexity::COGNITIVE_COMPLEXITY_INFO,
     crate::collapsible_if::COLLAPSIBLE_ELSE_IF_INFO,
@@ -443,7 +444,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::misc::SHORT_CIRCUIT_STATEMENT_INFO,
     crate::misc::TOPLEVEL_REF_ARG_INFO,
     crate::misc::USED_UNDERSCORE_BINDING_INFO,
-    crate::misc::ZERO_PTR_INFO,
     crate::misc_early::BUILTIN_TYPE_SHADOW_INFO,
     crate::misc_early::DOUBLE_NEG_INFO,
     crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index dcc6ee68e1b..fa009c8b2d6 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -637,7 +637,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool));
     store.register_late_pass(|_| Box::new(needless_bool::BoolComparison));
     store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach));
-    store.register_late_pass(|_| Box::<misc::LintPass>::default());
+    store.register_late_pass(|_| Box::new(misc::LintPass));
     store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
     store.register_late_pass(|_| Box::new(mut_mut::MutMut));
     store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index f8e76a5833e..9c8b47fb303 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -1,21 +1,20 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
-use clippy_utils::source::{snippet, snippet_opt, snippet_with_context};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then, span_lint_hir_and_then};
+use clippy_utils::source::{snippet, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    any_parent_is_automatically_derived, fulfill_or_allowed, get_parent_expr, in_constant, is_integer_literal,
-    is_lint_allowed, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
+    any_parent_is_automatically_derived, fulfill_or_allowed, get_parent_expr, is_lint_allowed, iter_input_pats,
+    last_path_segment, SpanlessEq,
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
-    BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind, Ty,
-    TyKind,
+    BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map::Span;
 
@@ -55,6 +54,7 @@ declare_clippy_lint! {
     style,
     "an entire binding declared as `ref`, in a function argument or a `let` statement"
 }
+
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for the use of bindings with a single leading
@@ -102,51 +102,13 @@ declare_clippy_lint! {
     "using a short circuit boolean condition as a statement"
 }
 
-declare_clippy_lint! {
-    /// ### What it does
-    /// Catch casts from `0` to some pointer type
-    ///
-    /// ### Why is this bad?
-    /// This generally means `null` and is better expressed as
-    /// {`std`, `core`}`::ptr::`{`null`, `null_mut`}.
-    ///
-    /// ### Example
-    /// ```rust
-    /// let a = 0 as *const u32;
-    /// ```
-    ///
-    /// Use instead:
-    /// ```rust
-    /// let a = std::ptr::null::<u32>();
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub ZERO_PTR,
-    style,
-    "using `0 as *{const, mut} T`"
-}
-
-pub struct LintPass {
-    std_or_core: &'static str,
-}
-impl Default for LintPass {
-    fn default() -> Self {
-        Self { std_or_core: "std" }
-    }
-}
-impl_lint_pass!(LintPass => [
+declare_lint_pass!(LintPass => [
     TOPLEVEL_REF_ARG,
     USED_UNDERSCORE_BINDING,
     SHORT_CIRCUIT_STATEMENT,
-    ZERO_PTR,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for LintPass {
-    fn check_crate(&mut self, cx: &LateContext<'_>) {
-        if is_no_std_crate(cx) {
-            self.std_or_core = "core";
-        }
-    }
-
     fn check_fn(
         &mut self,
         cx: &LateContext<'tcx>,
@@ -252,10 +214,6 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Cast(e, ty) = expr.kind {
-            self.check_cast(cx, expr.span, e, ty);
-            return;
-        }
         if in_external_macro(cx.sess(), expr.span)
             || expr.span.desugaring_kind().is_some()
             || any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
@@ -320,29 +278,3 @@ fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         _ => is_used(cx, parent),
     })
 }
-
-impl LintPass {
-    fn check_cast(&self, cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &Ty<'_>) {
-        if_chain! {
-            if let TyKind::Ptr(ref mut_ty) = ty.kind;
-            if is_integer_literal(e, 0);
-            if !in_constant(cx, e.hir_id);
-            then {
-                let (msg, sugg_fn) = match mut_ty.mutbl {
-                    Mutability::Mut => ("`0 as *mut _` detected", "ptr::null_mut"),
-                    Mutability::Not => ("`0 as *const _` detected", "ptr::null"),
-                };
-
-                let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind {
-                    (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MachineApplicable)
-                } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
-                    (format!("{}::{sugg_fn}::<{mut_ty_snip}>()", self.std_or_core), Applicability::MachineApplicable)
-                } else {
-                    // `MaybeIncorrect` as type inference may not work with the suggested code
-                    (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MaybeIncorrect)
-                };
-                span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
-            }
-        }
-    }
-}