|
1 | 1 | use super::ARITHMETIC_SIDE_EFFECTS; |
2 | 2 | use clippy_utils::consts::{constant, constant_simple, Constant}; |
3 | 3 | use clippy_utils::diagnostics::span_lint; |
4 | | -use clippy_utils::ty::type_diagnostic_name; |
| 4 | +use clippy_utils::ty::is_type_diagnostic_item; |
5 | 5 | use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary}; |
6 | 6 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
7 | 7 | use rustc_lint::{LateContext, LateLintPass}; |
8 | | -use rustc_middle::ty::Ty; |
| 8 | +use rustc_middle::ty::{self, Ty}; |
9 | 9 | use rustc_session::impl_lint_pass; |
10 | 10 | use rustc_span::source_map::Spanned; |
11 | 11 | use rustc_span::symbol::sym; |
@@ -88,37 +88,44 @@ impl ArithmeticSideEffects { |
88 | 88 | } |
89 | 89 |
|
90 | 90 | /// Verifies built-in types that have specific allowed operations |
91 | | - fn has_specific_allowed_type_and_operation( |
92 | | - cx: &LateContext<'_>, |
93 | | - lhs_ty: Ty<'_>, |
| 91 | + fn has_specific_allowed_type_and_operation<'tcx>( |
| 92 | + cx: &LateContext<'tcx>, |
| 93 | + lhs_ty: Ty<'tcx>, |
94 | 94 | op: &Spanned<hir::BinOpKind>, |
95 | | - rhs_ty: Ty<'_>, |
| 95 | + rhs_ty: Ty<'tcx>, |
96 | 96 | ) -> bool { |
97 | 97 | let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem); |
98 | | - let is_non_zero_u = |symbol: Option<Symbol>| { |
99 | | - matches!( |
100 | | - symbol, |
101 | | - Some( |
102 | | - sym::NonZeroU128 |
103 | | - | sym::NonZeroU16 |
104 | | - | sym::NonZeroU32 |
105 | | - | sym::NonZeroU64 |
106 | | - | sym::NonZeroU8 |
107 | | - | sym::NonZeroUsize |
108 | | - ) |
109 | | - ) |
| 98 | + let is_non_zero_u = |cx: &LateContext<'tcx>, ty: Ty<'tcx>| { |
| 99 | + let tcx = cx.tcx; |
| 100 | + |
| 101 | + let ty::Adt(adt, substs) = ty.kind() else { return false }; |
| 102 | + |
| 103 | + if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) { |
| 104 | + return false; |
| 105 | + }; |
| 106 | + |
| 107 | + let int_type = substs.type_at(0); |
| 108 | + let unsigned_int_types = [ |
| 109 | + tcx.types.u8, |
| 110 | + tcx.types.u16, |
| 111 | + tcx.types.u32, |
| 112 | + tcx.types.u64, |
| 113 | + tcx.types.u128, |
| 114 | + tcx.types.usize, |
| 115 | + ]; |
| 116 | + |
| 117 | + unsigned_int_types.contains(&int_type) |
110 | 118 | }; |
111 | 119 | let is_sat_or_wrap = |ty: Ty<'_>| { |
112 | | - let is_sat = type_diagnostic_name(cx, ty) == Some(sym::Saturating); |
113 | | - let is_wrap = type_diagnostic_name(cx, ty) == Some(sym::Wrapping); |
114 | | - is_sat || is_wrap |
| 120 | + is_type_diagnostic_item(cx, ty, sym::Saturating) || is_type_diagnostic_item(cx, ty, sym::Wrapping) |
115 | 121 | }; |
116 | 122 |
|
117 | | - // If the RHS is NonZeroU*, then division or module by zero will never occur |
118 | | - if is_non_zero_u(type_diagnostic_name(cx, rhs_ty)) && is_div_or_rem { |
| 123 | + // If the RHS is `NonZero<u*>`, then division or module by zero will never occur. |
| 124 | + if is_non_zero_u(cx, rhs_ty) && is_div_or_rem { |
119 | 125 | return true; |
120 | 126 | } |
121 | | - // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module |
| 127 | + |
| 128 | + // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module. |
122 | 129 | if is_sat_or_wrap(lhs_ty) { |
123 | 130 | return !is_div_or_rem; |
124 | 131 | } |
|
0 commit comments