Skip to content

Commit 4d2d3e9

Browse files
committed
fix f16/f128 lints
1 parent a5a7eea commit 4d2d3e9

File tree

5 files changed

+86
-51
lines changed

5 files changed

+86
-51
lines changed

clippy_lints/src/casts/cast_lossless.rs

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use clippy_utils::ty::is_isize_or_usize;
77
use rustc_errors::Applicability;
88
use rustc_hir::{Expr, QPath, TyKind};
99
use rustc_lint::LateContext;
10-
use rustc_middle::ty::{self, FloatTy, Ty};
10+
use rustc_middle::ty::{self, Ty};
1111
use rustc_span::hygiene;
1212

1313
use super::{CAST_LOSSLESS, utils};
@@ -76,29 +76,42 @@ 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) => {
81-
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);
84-
!is_isize_or_usize(cast_from)
85-
&& !is_isize_or_usize(cast_to)
86-
&& from_nbits < to_nbits
87-
&& !cast_signed_to_unsigned
88-
},
79+
if matches!(cast_from.kind(), ty::Bool) && cast_to.is_integral() {
80+
return msrv.meets(cx, msrvs::FROM_BOOL);
81+
}
8982

90-
(true, false) => {
91-
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
92-
let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.kind() {
93-
32
94-
} else {
95-
64
96-
};
97-
!is_isize_or_usize(cast_from) && from_nbits < to_nbits
98-
},
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-
},
83+
if cast_from.is_numeric() {
84+
return match (cast_from.is_integral(), cast_to.is_integral()) {
85+
(true, true) => {
86+
let cast_signed_to_unsigned = cast_from.is_signed() && !cast_to.is_signed();
87+
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
88+
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
89+
!is_isize_or_usize(cast_from)
90+
&& !is_isize_or_usize(cast_to)
91+
&& from_nbits < to_nbits
92+
&& !cast_signed_to_unsigned
93+
},
94+
(true, false) => {
95+
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
96+
let to_nbits = utils::float_ty_to_nbits(cast_to);
97+
if from_nbits == 64 && to_nbits == 128 {
98+
// FIXME(f16_f128): https://github.com/rust-lang/rust/blob/91fad92585b2dafc52a074e502b2a6c1f093ca35/library/core/src/convert/num.rs#L171
99+
return false;
100+
}
101+
!is_isize_or_usize(cast_from) && from_nbits < to_nbits
102+
},
103+
(false, true) => false,
104+
(false, false) => {
105+
let from_nbits = utils::float_ty_to_nbits(cast_from);
106+
let to_nbits = utils::float_ty_to_nbits(cast_to);
107+
if from_nbits == 16 && to_nbits == 32 {
108+
// FIXME(f16_f128): https://github.com/rust-lang/rust/issues/123831
109+
return false;
110+
}
111+
from_nbits < to_nbits
112+
},
113+
};
103114
}
115+
116+
false
104117
}

clippy_lints/src/casts/cast_possible_truncation.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_errors::{Applicability, Diag};
99
use rustc_hir::def::{DefKind, Res};
1010
use rustc_hir::{BinOpKind, Expr, ExprKind};
1111
use rustc_lint::LateContext;
12-
use rustc_middle::ty::{self, FloatTy, Ty};
12+
use rustc_middle::ty::{self, Ty};
1313
use rustc_span::Span;
1414

1515
use super::{CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION, utils};
@@ -161,8 +161,14 @@ pub(super) fn check(
161161
format!("casting `{cast_from}` to `{cast_to}` may truncate the value")
162162
},
163163

164-
(ty::Float(FloatTy::F64), false) if matches!(cast_to.kind(), &ty::Float(FloatTy::F32)) => {
165-
"casting `f64` to `f32` may truncate the value".to_string()
164+
(ty::Float(_), false) => {
165+
let from_nbits = utils::float_ty_to_nbits(cast_from);
166+
let to_nbits = utils::float_ty_to_nbits(cast_to);
167+
if from_nbits > to_nbits {
168+
format!("casting `f{from_nbits}` to `f{to_nbits}` may truncate the value")
169+
} else {
170+
return;
171+
}
166172
},
167173

168174
_ => return,

clippy_lints/src/casts/cast_precision_loss.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint;
22
use clippy_utils::ty::is_isize_or_usize;
33
use rustc_hir::Expr;
44
use rustc_lint::LateContext;
5-
use rustc_middle::ty::{self, FloatTy, Ty};
5+
use rustc_middle::ty::Ty;
66

77
use super::{CAST_PRECISION_LOSS, utils};
88

@@ -12,19 +12,15 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
1212
}
1313

1414
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
19-
};
15+
let to_nbits = utils::float_ty_to_nbits(cast_to);
2016

2117
if !(is_isize_or_usize(cast_from) || from_nbits >= to_nbits) {
2218
return;
2319
}
2420

25-
let cast_to_f64 = to_nbits == 64;
26-
let mantissa_nbits = if cast_to_f64 { 52 } else { 23 };
27-
let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64;
21+
let mantissa_nbits = utils::float_ty_to_mantissa_nbits(cast_to);
22+
23+
let arch_dependent = is_isize_or_usize(cast_from) && to_nbits == 64;
2824
let arch_dependent_str = "on targets with 64-bit wide pointers ";
2925
let from_nbits_str = if arch_dependent {
3026
"64".to_owned()
@@ -42,7 +38,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
4238
"casting `{0}` to `{1}` causes a loss of precision {2}(`{0}` is {3} bits wide, \
4339
but `{1}`'s mantissa is only {4} bits wide)",
4440
cast_from,
45-
if cast_to_f64 { "f64" } else { "f32" },
41+
format!("f{to_nbits}"),
4642
if arch_dependent { arch_dependent_str } else { "" },
4743
from_nbits_str,
4844
mantissa_nbits

clippy_lints/src/casts/unnecessary_cast.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::casts::utils;
12
use clippy_utils::diagnostics::span_lint_and_sugg;
23
use clippy_utils::numeric_literal::NumericLiteral;
34
use clippy_utils::source::{SpanRangeExt, snippet_opt};
@@ -9,7 +10,7 @@ use rustc_hir::def::{DefKind, Res};
910
use rustc_hir::{Expr, ExprKind, Lit, Node, Path, QPath, TyKind, UnOp};
1011
use rustc_lint::{LateContext, LintContext};
1112
use rustc_middle::ty::adjustment::Adjust;
12-
use rustc_middle::ty::{self, FloatTy, InferTy, Ty};
13+
use rustc_middle::ty::{self, Ty};
1314
use rustc_span::{Symbol, sym};
1415
use std::ops::ControlFlow;
1516

@@ -108,8 +109,8 @@ pub(super) fn check<'tcx>(
108109
&& let Some(src) = cast_expr.span.get_source_text(cx)
109110
&& cast_to.is_floating_point()
110111
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
111-
&& let from_nbits = 128 - n.get().leading_zeros()
112-
&& let to_nbits = fp_ty_mantissa_nbits(cast_to)
112+
&& let from_nbits = 128 - u64::from(n.get().leading_zeros())
113+
&& let to_nbits = utils::float_ty_to_mantissa_nbits(cast_to)
113114
&& from_nbits != 0
114115
&& to_nbits != 0
115116
&& from_nbits <= to_nbits
@@ -257,16 +258,6 @@ fn get_numeric_literal<'e>(expr: &'e Expr<'e>) -> Option<&'e Lit> {
257258
}
258259
}
259260

260-
/// Returns the mantissa bits wide of a fp type.
261-
/// Will return 0 if the type is not a fp
262-
fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 {
263-
match typ.kind() {
264-
ty::Float(FloatTy::F32) => 23,
265-
ty::Float(FloatTy::F64) | ty::Infer(InferTy::FloatVar(_)) => 52,
266-
_ => 0,
267-
}
268-
}
269-
270261
/// Finds whether an `Expr` returns a type alias.
271262
///
272263
/// TODO: Maybe we should move this to `clippy_utils` so others won't need to go down this dark,

clippy_lints/src/casts/utils.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clippy_utils::ty::{EnumValue, read_explicit_enum_value};
2-
use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TyCtxt, UintTy, VariantDiscr};
2+
use rustc_middle::ty::{self, AdtDef, FloatTy, InferTy, IntTy, Ty, TyCtxt, UintTy, VariantDiscr};
33

44
/// Returns the size in bits of an integral type.
55
/// Will return 0 if the type is not an int or uint variant
@@ -25,6 +25,35 @@ pub(super) fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_>) -> u64 {
2525
}
2626
}
2727

28+
/// Returns the size in bits of an floating type.
29+
/// Will return 0 if the type is not an float variant
30+
pub(super) fn float_ty_to_nbits(typ: Ty<'_>) -> u64 {
31+
match typ.kind() {
32+
ty::Float(i) => match i {
33+
FloatTy::F16 => 16,
34+
FloatTy::F32 => 32,
35+
FloatTy::F64 => 64,
36+
FloatTy::F128 => 128,
37+
},
38+
_ => 0,
39+
}
40+
}
41+
42+
/// Returns the mantissa size in bits of an floating type.
43+
/// Will return 0 if the type is not an float variant
44+
pub(super) fn float_ty_to_mantissa_nbits(typ: Ty<'_>) -> u64 {
45+
match typ.kind() {
46+
ty::Float(i) => match i {
47+
FloatTy::F16 => 10,
48+
FloatTy::F32 => 23,
49+
FloatTy::F64 => 52,
50+
FloatTy::F128 => 112,
51+
},
52+
ty::Infer(InferTy::FloatVar(_)) => 52,
53+
_ => 0,
54+
}
55+
}
56+
2857
pub(super) fn enum_value_nbits(value: EnumValue) -> u64 {
2958
match value {
3059
EnumValue::Unsigned(x) => 128 - x.leading_zeros(),

0 commit comments

Comments
 (0)