Skip to content

Commit 6fa2866

Browse files
authored
Use None::<u64> instead of 0 to denote an absence of value (#14957)
`clippy_lints::casts::utils::int_ty_to_nbits` used to return `0` to indicate that the argument was not an integral type. It is more idiomatic to use `Option<u64>` as a return type. Also, I've added a few `FIXME:` at places where only `f32` and `f64` are considered, as we now have `f16` and `f128` to deal with. changelog: none
2 parents d7b27ec + 225abd6 commit 6fa2866

File tree

7 files changed

+45
-65
lines changed

7 files changed

+45
-65
lines changed

clippy_lints/src/casts/cast_lossless.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,29 +76,28 @@ fn should_lint(cx: &LateContext<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: M
7676
return false;
7777
}
7878

79-
match (cast_from.is_integral(), cast_to.is_integral()) {
80-
(true, true) => {
79+
match (
80+
utils::int_ty_to_nbits(cx.tcx, cast_from),
81+
utils::int_ty_to_nbits(cx.tcx, cast_to),
82+
) {
83+
(Some(from_nbits), Some(to_nbits)) => {
8184
let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed();
82-
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
83-
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
8485
!is_isize_or_usize(cast_from)
8586
&& !is_isize_or_usize(cast_to)
8687
&& from_nbits < to_nbits
8788
&& !cast_signed_to_unsigned
8889
},
8990

90-
(true, false) => {
91-
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
91+
(Some(from_nbits), None) => {
92+
// FIXME: handle `f16` and `f128`
9293
let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.kind() {
9394
32
9495
} else {
9596
64
9697
};
9798
!is_isize_or_usize(cast_from) && from_nbits < to_nbits
9899
},
99-
(false, true) if matches!(cast_from.kind(), ty::Bool) && msrv.meets(cx, msrvs::FROM_BOOL) => true,
100-
(_, _) => {
101-
matches!(cast_from.kind(), ty::Float(FloatTy::F32)) && matches!(cast_to.kind(), ty::Float(FloatTy::F64))
102-
},
100+
(None, Some(_)) if cast_from.is_bool() && msrv.meets(cx, msrvs::FROM_BOOL) => true,
101+
_ => matches!(cast_from.kind(), ty::Float(FloatTy::F32)) && matches!(cast_to.kind(), ty::Float(FloatTy::F64)),
103102
}
104103
}

clippy_lints/src/casts/cast_possible_truncation.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,14 @@ pub(super) fn check(
9191
cast_to: Ty<'_>,
9292
cast_to_span: Span,
9393
) {
94-
let msg = match (cast_from.kind(), cast_to.is_integral()) {
95-
(ty::Int(_) | ty::Uint(_), true) => {
94+
let msg = match (cast_from.kind(), utils::int_ty_to_nbits(cx.tcx, cast_to)) {
95+
(ty::Int(_) | ty::Uint(_), Some(to_nbits)) => {
9696
let from_nbits = apply_reductions(
9797
cx,
98-
utils::int_ty_to_nbits(cast_from, cx.tcx),
98+
utils::int_ty_to_nbits(cx.tcx, cast_from).unwrap(),
9999
cast_expr,
100100
cast_from.is_signed(),
101101
);
102-
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
103102

104103
let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
105104
(true, true) | (false, false) => (to_nbits < from_nbits, ""),
@@ -121,7 +120,7 @@ pub(super) fn check(
121120
format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",)
122121
},
123122

124-
(ty::Adt(def, _), true) if def.is_enum() => {
123+
(ty::Adt(def, _), Some(to_nbits)) if def.is_enum() => {
125124
let (from_nbits, variant) = if let ExprKind::Path(p) = &cast_expr.kind
126125
&& let Res::Def(DefKind::Ctor(..), id) = cx.qpath_res(p, cast_expr.hir_id)
127126
{
@@ -132,7 +131,6 @@ pub(super) fn check(
132131
} else {
133132
(utils::enum_ty_to_nbits(*def, cx.tcx), None)
134133
};
135-
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
136134

137135
let cast_from_ptr_size = def.repr().int.is_none_or(|ty| matches!(ty, IntegerType::Pointer(_),));
138136
let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) {
@@ -157,11 +155,11 @@ pub(super) fn check(
157155
format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}")
158156
},
159157

160-
(ty::Float(_), true) => {
158+
(ty::Float(_), Some(_)) => {
161159
format!("casting `{cast_from}` to `{cast_to}` may truncate the value")
162160
},
163161

164-
(ty::Float(FloatTy::F64), false) if matches!(cast_to.kind(), &ty::Float(FloatTy::F32)) => {
162+
(ty::Float(FloatTy::F64), None) if matches!(cast_to.kind(), &ty::Float(FloatTy::F32)) => {
165163
"casting `f64` to `f32` may truncate the value".to_string()
166164
},
167165

clippy_lints/src/casts/cast_possible_wrap.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ enum EmitState {
1717
}
1818

1919
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
20-
if !(cast_from.is_integral() && cast_to.is_integral()) {
20+
let (Some(from_nbits), Some(to_nbits)) = (
21+
utils::int_ty_to_nbits(cx.tcx, cast_from),
22+
utils::int_ty_to_nbits(cx.tcx, cast_to),
23+
) else {
2124
return;
22-
}
25+
};
2326

2427
// emit a lint if a cast is:
2528
// 1. unsigned to signed
@@ -35,9 +38,6 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
3538
return;
3639
}
3740

38-
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
39-
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
40-
4141
let should_lint = match (cast_from.is_ptr_sized_integral(), cast_to.is_ptr_sized_integral()) {
4242
(true, true) => {
4343
// casts between two ptr sized integers are trivially always the same size

clippy_lints/src/casts/cast_precision_loss.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@ use rustc_middle::ty::{self, FloatTy, Ty};
77
use super::{CAST_PRECISION_LOSS, utils};
88

99
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
10-
if !cast_from.is_integral() || cast_to.is_integral() {
10+
let Some(from_nbits) = utils::int_ty_to_nbits(cx.tcx, cast_from) else {
1111
return;
12-
}
12+
};
1313

14-
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
15-
let to_nbits = if cast_to.kind() == &ty::Float(FloatTy::F32) {
16-
32
17-
} else {
18-
64
14+
// FIXME: handle `f16` and `f128`
15+
let to_nbits = match cast_to.kind() {
16+
ty::Float(f @ (FloatTy::F32 | FloatTy::F64)) => f.bit_width(),
17+
_ => return,
1918
};
2019

2120
if !(is_isize_or_usize(cast_from) || from_nbits >= to_nbits) {
@@ -29,9 +28,10 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
2928
let from_nbits_str = if arch_dependent {
3029
"64".to_owned()
3130
} else if is_isize_or_usize(cast_from) {
31+
// FIXME: handle 16 bits `usize` type
3232
"32 or 64".to_owned()
3333
} else {
34-
utils::int_ty_to_nbits(cast_from, cx.tcx).to_string()
34+
from_nbits.to_string()
3535
};
3636

3737
span_lint(

clippy_lints/src/casts/fn_to_numeric_cast.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,22 @@ use clippy_utils::source::snippet_with_applicability;
33
use rustc_errors::Applicability;
44
use rustc_hir::Expr;
55
use rustc_lint::LateContext;
6-
use rustc_middle::ty::{self, Ty, UintTy};
6+
use rustc_middle::ty::{self, Ty};
77

88
use super::{FN_TO_NUMERIC_CAST, utils};
99

1010
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
1111
// We only want to check casts to `ty::Uint` or `ty::Int`
12-
match cast_to.kind() {
13-
ty::Uint(_) | ty::Int(..) => { /* continue on */ },
14-
_ => return,
15-
}
12+
let Some(to_nbits) = utils::int_ty_to_nbits(cx.tcx, cast_to) else {
13+
return;
14+
};
1615

1716
match cast_from.kind() {
1817
ty::FnDef(..) | ty::FnPtr(..) => {
1918
let mut applicability = Applicability::MaybeIncorrect;
20-
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
21-
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
2219

23-
if (to_nbits >= cx.tcx.data_layout.pointer_size.bits()) && (*cast_to.kind() != ty::Uint(UintTy::Usize)) {
20+
if to_nbits >= cx.tcx.data_layout.pointer_size.bits() && !cast_to.is_usize() {
21+
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
2422
span_lint_and_sugg(
2523
cx,
2624
FN_TO_NUMERIC_CAST,

clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ use super::{FN_TO_NUMERIC_CAST_WITH_TRUNCATION, utils};
99

1010
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
1111
// We only want to check casts to `ty::Uint` or `ty::Int`
12-
match cast_to.kind() {
13-
ty::Uint(_) | ty::Int(..) => { /* continue on */ },
14-
_ => return,
15-
}
12+
let Some(to_nbits) = utils::int_ty_to_nbits(cx.tcx, cast_to) else {
13+
return;
14+
};
1615
match cast_from.kind() {
1716
ty::FnDef(..) | ty::FnPtr(..) => {
1817
let mut applicability = Applicability::MaybeIncorrect;
1918
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
2019

21-
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
2220
if to_nbits < cx.tcx.data_layout.pointer_size.bits() {
2321
span_lint_and_sugg(
2422
cx,

clippy_lints/src/casts/utils.rs

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,14 @@
11
use clippy_utils::ty::{EnumValue, read_explicit_enum_value};
22
use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TyCtxt, UintTy, VariantDiscr};
33

4-
/// Returns the size in bits of an integral type.
5-
/// Will return 0 if the type is not an int or uint variant
6-
pub(super) fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_>) -> u64 {
7-
match typ.kind() {
8-
ty::Int(i) => match i {
9-
IntTy::Isize => tcx.data_layout.pointer_size.bits(),
10-
IntTy::I8 => 8,
11-
IntTy::I16 => 16,
12-
IntTy::I32 => 32,
13-
IntTy::I64 => 64,
14-
IntTy::I128 => 128,
15-
},
16-
ty::Uint(i) => match i {
17-
UintTy::Usize => tcx.data_layout.pointer_size.bits(),
18-
UintTy::U8 => 8,
19-
UintTy::U16 => 16,
20-
UintTy::U32 => 32,
21-
UintTy::U64 => 64,
22-
UintTy::U128 => 128,
23-
},
24-
_ => 0,
4+
/// Returns the size in bits of an integral type, or `None` if `ty` is not an
5+
/// integral type.
6+
pub(super) fn int_ty_to_nbits(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<u64> {
7+
match ty.kind() {
8+
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(tcx.data_layout.pointer_size.bits()),
9+
ty::Int(i) => i.bit_width(),
10+
ty::Uint(i) => i.bit_width(),
11+
_ => None,
2512
}
2613
}
2714

0 commit comments

Comments
 (0)