Fix zero_ptr suggestion for no_std crates

This commit is contained in:
Jason Newcomb 2022-12-01 23:29:47 -05:00
parent d822110d3b
commit 6ba2cda79a
5 changed files with 111 additions and 25 deletions

View file

@ -538,7 +538,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::new(misc::MiscLints));
store.register_late_pass(|_| Box::<misc::LintPass>::default());
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));

View file

@ -9,12 +9,14 @@ use rustc_hir::{
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{ExpnKind, Span};
use clippy_utils::sugg::Sugg;
use clippy_utils::{get_parent_expr, in_constant, is_integer_literal, iter_input_pats, last_path_segment, SpanlessEq};
use clippy_utils::{
get_parent_expr, in_constant, is_integer_literal, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
};
declare_clippy_lint! {
/// ### What it does
@ -120,14 +122,28 @@ declare_clippy_lint! {
"using `0 as *{const, mut} T`"
}
declare_lint_pass!(MiscLints => [
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,
USED_UNDERSCORE_BINDING,
SHORT_CIRCUIT_STATEMENT,
ZERO_PTR,
]);
impl<'tcx> LateLintPass<'tcx> for MiscLints {
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>,
@ -231,7 +247,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Cast(e, ty) = expr.kind {
check_cast(cx, expr.span, e, ty);
self.check_cast(cx, expr.span, e, ty);
return;
}
if in_attributes_expansion(expr) || expr.span.is_desugaring(DesugaringKind::Await) {
@ -310,26 +326,28 @@ fn non_macro_local(cx: &LateContext<'_>, res: def::Res) -> bool {
}
}
fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::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", "std::ptr::null_mut"),
Mutability::Not => ("`0 as *const _` detected", "std::ptr::null"),
};
impl LintPass {
fn check_cast(&self, cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::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}()"), Applicability::MachineApplicable)
} else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
(format!("{sugg_fn}::<{mut_ty_snip}>()"), Applicability::MachineApplicable)
} else {
// `MaybeIncorrect` as type inference may not work with the suggested code
(format!("{sugg_fn}()"), Applicability::MaybeIncorrect)
};
span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
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);
}
}
}
}

View file

@ -0,0 +1,21 @@
// run-rustfix
#![feature(lang_items, start, libc)]
#![no_std]
#![deny(clippy::zero_ptr)]
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
let _ = core::ptr::null::<usize>();
let _ = core::ptr::null_mut::<f64>();
let _: *const u8 = core::ptr::null();
0
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
#[lang = "eh_personality"]
extern "C" fn eh_personality() {}

View file

@ -0,0 +1,21 @@
// run-rustfix
#![feature(lang_items, start, libc)]
#![no_std]
#![deny(clippy::zero_ptr)]
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
let _ = 0 as *const usize;
let _ = 0 as *mut f64;
let _: *const u8 = 0 as *const _;
0
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
#[lang = "eh_personality"]
extern "C" fn eh_personality() {}

View file

@ -0,0 +1,26 @@
error: `0 as *const _` detected
--> $DIR/zero_ptr_no_std.rs:9:13
|
LL | let _ = 0 as *const usize;
| ^^^^^^^^^^^^^^^^^ help: try: `core::ptr::null::<usize>()`
|
note: the lint level is defined here
--> $DIR/zero_ptr_no_std.rs:5:9
|
LL | #![deny(clippy::zero_ptr)]
| ^^^^^^^^^^^^^^^^
error: `0 as *mut _` detected
--> $DIR/zero_ptr_no_std.rs:10:13
|
LL | let _ = 0 as *mut f64;
| ^^^^^^^^^^^^^ help: try: `core::ptr::null_mut::<f64>()`
error: `0 as *const _` detected
--> $DIR/zero_ptr_no_std.rs:11:24
|
LL | let _: *const u8 = 0 as *const _;
| ^^^^^^^^^^^^^ help: try: `core::ptr::null()`
error: aborting due to 3 previous errors