Auto merge of #11530 - Alexendoo:zero-ptr-file-location, r=blyxyas
Move zero_ptr to the casts module Also a bit of a touch up to the code while I was there changelog: none
This commit is contained in:
commit
889e1b99bd
@ -20,6 +20,7 @@
|
|||||||
mod ptr_cast_constness;
|
mod ptr_cast_constness;
|
||||||
mod unnecessary_cast;
|
mod unnecessary_cast;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod zero_ptr;
|
||||||
|
|
||||||
use clippy_utils::is_hir_ty_cfg_dependant;
|
use clippy_utils::is_hir_ty_cfg_dependant;
|
||||||
use clippy_utils::msrvs::{self, Msrv};
|
use clippy_utils::msrvs::{self, Msrv};
|
||||||
@ -665,6 +666,29 @@
|
|||||||
"casting a known floating-point NaN into an integer"
|
"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 {
|
pub struct Casts {
|
||||||
msrv: Msrv,
|
msrv: Msrv,
|
||||||
}
|
}
|
||||||
@ -699,6 +723,7 @@ pub fn new(msrv: Msrv) -> Self {
|
|||||||
CAST_SLICE_FROM_RAW_PARTS,
|
CAST_SLICE_FROM_RAW_PARTS,
|
||||||
AS_PTR_CAST_MUT,
|
AS_PTR_CAST_MUT,
|
||||||
CAST_NAN_TO_INT,
|
CAST_NAN_TO_INT,
|
||||||
|
ZERO_PTR,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Casts {
|
impl<'tcx> LateLintPass<'tcx> for Casts {
|
||||||
@ -729,6 +754,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
|||||||
fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to);
|
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::check(cx, expr, cast_expr, cast_from, cast_to);
|
||||||
fn_to_numeric_cast_with_truncation::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) {
|
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);
|
cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span);
|
||||||
|
39
clippy_lints/src/casts/zero_ptr.rs
Normal file
39
clippy_lints/src/casts/zero_ptr.rs
Normal file
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -97,6 +97,7 @@
|
|||||||
crate::casts::PTR_AS_PTR_INFO,
|
crate::casts::PTR_AS_PTR_INFO,
|
||||||
crate::casts::PTR_CAST_CONSTNESS_INFO,
|
crate::casts::PTR_CAST_CONSTNESS_INFO,
|
||||||
crate::casts::UNNECESSARY_CAST_INFO,
|
crate::casts::UNNECESSARY_CAST_INFO,
|
||||||
|
crate::casts::ZERO_PTR_INFO,
|
||||||
crate::checked_conversions::CHECKED_CONVERSIONS_INFO,
|
crate::checked_conversions::CHECKED_CONVERSIONS_INFO,
|
||||||
crate::cognitive_complexity::COGNITIVE_COMPLEXITY_INFO,
|
crate::cognitive_complexity::COGNITIVE_COMPLEXITY_INFO,
|
||||||
crate::collapsible_if::COLLAPSIBLE_ELSE_IF_INFO,
|
crate::collapsible_if::COLLAPSIBLE_ELSE_IF_INFO,
|
||||||
@ -443,7 +444,6 @@
|
|||||||
crate::misc::SHORT_CIRCUIT_STATEMENT_INFO,
|
crate::misc::SHORT_CIRCUIT_STATEMENT_INFO,
|
||||||
crate::misc::TOPLEVEL_REF_ARG_INFO,
|
crate::misc::TOPLEVEL_REF_ARG_INFO,
|
||||||
crate::misc::USED_UNDERSCORE_BINDING_INFO,
|
crate::misc::USED_UNDERSCORE_BINDING_INFO,
|
||||||
crate::misc::ZERO_PTR_INFO,
|
|
||||||
crate::misc_early::BUILTIN_TYPE_SHADOW_INFO,
|
crate::misc_early::BUILTIN_TYPE_SHADOW_INFO,
|
||||||
crate::misc_early::DOUBLE_NEG_INFO,
|
crate::misc_early::DOUBLE_NEG_INFO,
|
||||||
crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO,
|
crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO,
|
||||||
|
@ -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::NeedlessBool));
|
||||||
store.register_late_pass(|_| Box::new(needless_bool::BoolComparison));
|
store.register_late_pass(|_| Box::new(needless_bool::BoolComparison));
|
||||||
store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach));
|
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(eta_reduction::EtaReduction));
|
||||||
store.register_late_pass(|_| Box::new(mut_mut::MutMut));
|
store.register_late_pass(|_| Box::new(mut_mut::MutMut));
|
||||||
store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
|
store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
|
||||||
|
@ -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::diagnostics::{span_lint, span_lint_and_then, span_lint_hir_and_then};
|
||||||
use clippy_utils::source::{snippet, snippet_opt, snippet_with_context};
|
use clippy_utils::source::{snippet, snippet_with_context};
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
any_parent_is_automatically_derived, fulfill_or_allowed, get_parent_expr, in_constant, is_integer_literal,
|
any_parent_is_automatically_derived, fulfill_or_allowed, get_parent_expr, is_lint_allowed, iter_input_pats,
|
||||||
is_lint_allowed, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
|
last_path_segment, SpanlessEq,
|
||||||
};
|
};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind, Ty,
|
BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind,
|
||||||
TyKind,
|
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_middle::lint::in_external_macro;
|
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::def_id::LocalDefId;
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
|
|
||||||
@ -55,6 +54,7 @@
|
|||||||
style,
|
style,
|
||||||
"an entire binding declared as `ref`, in a function argument or a `let` statement"
|
"an entire binding declared as `ref`, in a function argument or a `let` statement"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
/// Checks for the use of bindings with a single leading
|
/// Checks for the use of bindings with a single leading
|
||||||
@ -102,51 +102,13 @@
|
|||||||
"using a short circuit boolean condition as a statement"
|
"using a short circuit boolean condition as a statement"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_lint_pass!(LintPass => [
|
||||||
/// ### 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 => [
|
|
||||||
TOPLEVEL_REF_ARG,
|
TOPLEVEL_REF_ARG,
|
||||||
USED_UNDERSCORE_BINDING,
|
USED_UNDERSCORE_BINDING,
|
||||||
SHORT_CIRCUIT_STATEMENT,
|
SHORT_CIRCUIT_STATEMENT,
|
||||||
ZERO_PTR,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for LintPass {
|
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(
|
fn check_fn(
|
||||||
&mut self,
|
&mut self,
|
||||||
cx: &LateContext<'tcx>,
|
cx: &LateContext<'tcx>,
|
||||||
@ -252,10 +214,6 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
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)
|
if in_external_macro(cx.sess(), expr.span)
|
||||||
|| expr.span.desugaring_kind().is_some()
|
|| expr.span.desugaring_kind().is_some()
|
||||||
|| any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
|
|| 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),
|
_ => 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user