Fix NonZero
clippy lints.
This commit is contained in:
parent
554b0f70c3
commit
ca2ec7af35
@ -1,11 +1,11 @@
|
|||||||
use super::ARITHMETIC_SIDE_EFFECTS;
|
use super::ARITHMETIC_SIDE_EFFECTS;
|
||||||
use clippy_utils::consts::{constant, constant_simple, Constant};
|
use clippy_utils::consts::{constant, constant_simple, Constant};
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use clippy_utils::ty::type_diagnostic_name;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary};
|
use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
@ -88,37 +88,44 @@ impl ArithmeticSideEffects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Verifies built-in types that have specific allowed operations
|
/// Verifies built-in types that have specific allowed operations
|
||||||
fn has_specific_allowed_type_and_operation(
|
fn has_specific_allowed_type_and_operation<'tcx>(
|
||||||
cx: &LateContext<'_>,
|
cx: &LateContext<'tcx>,
|
||||||
lhs_ty: Ty<'_>,
|
lhs_ty: Ty<'tcx>,
|
||||||
op: &Spanned<hir::BinOpKind>,
|
op: &Spanned<hir::BinOpKind>,
|
||||||
rhs_ty: Ty<'_>,
|
rhs_ty: Ty<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem);
|
let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem);
|
||||||
let is_non_zero_u = |symbol: Option<Symbol>| {
|
let is_non_zero_u = |cx: &LateContext<'tcx>, ty: Ty<'tcx>| {
|
||||||
matches!(
|
let tcx = cx.tcx;
|
||||||
symbol,
|
|
||||||
Some(
|
let ty::Adt(adt, substs) = ty.kind() else { return false };
|
||||||
sym::NonZeroU128
|
|
||||||
| sym::NonZeroU16
|
if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) {
|
||||||
| sym::NonZeroU32
|
return false;
|
||||||
| sym::NonZeroU64
|
|
||||||
| sym::NonZeroU8
|
|
||||||
| sym::NonZeroUsize
|
|
||||||
)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let is_sat_or_wrap = |ty: Ty<'_>| {
|
|
||||||
let is_sat = type_diagnostic_name(cx, ty) == Some(sym::Saturating);
|
|
||||||
let is_wrap = type_diagnostic_name(cx, ty) == Some(sym::Wrapping);
|
|
||||||
is_sat || is_wrap
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the RHS is NonZeroU*, then division or module by zero will never occur
|
let int_type = substs.type_at(0);
|
||||||
if is_non_zero_u(type_diagnostic_name(cx, rhs_ty)) && is_div_or_rem {
|
let unsigned_int_types = [
|
||||||
|
tcx.types.u8,
|
||||||
|
tcx.types.u16,
|
||||||
|
tcx.types.u32,
|
||||||
|
tcx.types.u64,
|
||||||
|
tcx.types.u128,
|
||||||
|
tcx.types.usize,
|
||||||
|
];
|
||||||
|
|
||||||
|
unsigned_int_types.contains(&int_type)
|
||||||
|
};
|
||||||
|
let is_sat_or_wrap = |ty: Ty<'_>| {
|
||||||
|
is_type_diagnostic_item(cx, ty, sym::Saturating) || is_type_diagnostic_item(cx, ty, sym::Wrapping)
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the RHS is `NonZero<u*>`, then division or module by zero will never occur.
|
||||||
|
if is_non_zero_u(cx, rhs_ty) && is_div_or_rem {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module
|
|
||||||
|
// `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module.
|
||||||
if is_sat_or_wrap(lhs_ty) {
|
if is_sat_or_wrap(lhs_ty) {
|
||||||
return !is_div_or_rem;
|
return !is_div_or_rem;
|
||||||
}
|
}
|
||||||
|
@ -16,40 +16,55 @@ pub(super) fn check<'tcx>(
|
|||||||
to_ty: Ty<'tcx>,
|
to_ty: Ty<'tcx>,
|
||||||
arg: &'tcx Expr<'_>,
|
arg: &'tcx Expr<'_>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let (ty::Int(_) | ty::Uint(_), Some(to_ty_adt)) = (&from_ty.kind(), to_ty.ty_adt_def()) else {
|
let tcx = cx.tcx;
|
||||||
return false;
|
|
||||||
};
|
let (ty::Int(_) | ty::Uint(_), ty::Adt(adt, substs)) = (&from_ty.kind(), to_ty.kind()) else {
|
||||||
let Some(to_type_sym) = cx.tcx.get_diagnostic_name(to_ty_adt.did()) else {
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !matches!(
|
if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) {
|
||||||
to_type_sym,
|
|
||||||
sym::NonZeroU8
|
|
||||||
| sym::NonZeroU16
|
|
||||||
| sym::NonZeroU32
|
|
||||||
| sym::NonZeroU64
|
|
||||||
| sym::NonZeroU128
|
|
||||||
| sym::NonZeroI8
|
|
||||||
| sym::NonZeroI16
|
|
||||||
| sym::NonZeroI32
|
|
||||||
| sym::NonZeroI64
|
|
||||||
| sym::NonZeroI128
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: This can be simplified once `NonZero<T>` is stable.
|
||||||
|
let coercable_types = [
|
||||||
|
("NonZeroU8", tcx.types.u8),
|
||||||
|
("NonZeroU16", tcx.types.u16),
|
||||||
|
("NonZeroU32", tcx.types.u32),
|
||||||
|
("NonZeroU64", tcx.types.u64),
|
||||||
|
("NonZeroU128", tcx.types.u128),
|
||||||
|
("NonZeroUsize", tcx.types.usize),
|
||||||
|
("NonZeroI8", tcx.types.i8),
|
||||||
|
("NonZeroI16", tcx.types.i16),
|
||||||
|
("NonZeroI32", tcx.types.i32),
|
||||||
|
("NonZeroI64", tcx.types.i64),
|
||||||
|
("NonZeroI128", tcx.types.i128),
|
||||||
|
("NonZeroIsize", tcx.types.isize),
|
||||||
|
];
|
||||||
|
|
||||||
|
let int_type = substs.type_at(0);
|
||||||
|
|
||||||
|
let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| {
|
||||||
|
if *t == int_type && *t == from_ty {
|
||||||
|
Some(nonzero_alias)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
}) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
TRANSMUTE_INT_TO_NON_ZERO,
|
TRANSMUTE_INT_TO_NON_ZERO,
|
||||||
e.span,
|
e.span,
|
||||||
&format!("transmute from a `{from_ty}` to a `{to_type_sym}`"),
|
&format!("transmute from a `{from_ty}` to a `{nonzero_alias}`"),
|
||||||
|diag| {
|
|diag| {
|
||||||
let arg = sugg::Sugg::hir(cx, arg, "..");
|
let arg = sugg::Sugg::hir(cx, arg, "..");
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
e.span,
|
e.span,
|
||||||
"consider using",
|
"consider using",
|
||||||
format!("{to_type_sym}::{}({arg})", sym::new_unchecked),
|
format!("{nonzero_alias}::{}({arg})", sym::new_unchecked),
|
||||||
Applicability::Unspecified,
|
Applicability::Unspecified,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user