Skip to content

Commit 639ed75

Browse files
committed
Treat f16 and f128 as floats in constant evaluation
1 parent 62589a2 commit 639ed75

File tree

8 files changed

+229
-197
lines changed

8 files changed

+229
-197
lines changed

clippy_lints/src/neg_multiply.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,10 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply {
6262
}
6363

6464
fn check_mul(cx: &LateContext<'_>, mul_expr: &Expr<'_>, lit: &Expr<'_>, exp: &Expr<'_>) {
65-
const F16_ONE: u16 = 1.0_f16.to_bits();
66-
const F128_ONE: u128 = 1.0_f128.to_bits();
6765
if let ExprKind::Lit(l) = lit.kind
6866
&& matches!(
6967
consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)),
70-
Constant::Int(1)
71-
| Constant::F16(F16_ONE)
72-
| Constant::F32(1.0)
73-
| Constant::F64(1.0)
74-
| Constant::F128(F128_ONE)
68+
Constant::Int(1) | Constant::F16(1.0) | Constant::F32(1.0) | Constant::F64(1.0) | Constant::F128(1.0)
7569
)
7670
&& cx.typeck_results().expr_ty(exp).is_numeric()
7771
{

clippy_utils/src/consts.rs

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{clip, is_direct_expn_of, sext, sym, unsext};
1010

1111
use rustc_abi::Size;
1212
use rustc_apfloat::Float;
13-
use rustc_apfloat::ieee::{Half, Quad};
13+
use rustc_apfloat::ieee::Quad;
1414
use rustc_ast::ast::{LitFloatType, LitKind};
1515
use rustc_hir::def::{DefKind, Res};
1616
use rustc_hir::{
@@ -41,16 +41,14 @@ pub enum Constant {
4141
Char(char),
4242
/// An integer's bit representation.
4343
Int(u128),
44-
/// An `f16` bitcast to a `u16`.
45-
// FIXME(f16_f128): use `f16` once builtins are available on all host tools platforms.
46-
F16(u16),
44+
/// An `f16`.
45+
F16(f16),
4746
/// An `f32`.
4847
F32(f32),
4948
/// An `f64`.
5049
F64(f64),
5150
/// An `f128` bitcast to a `u128`.
52-
// FIXME(f16_f128): use `f128` once builtins are available on all host tools platforms.
53-
F128(u128),
51+
F128(f128),
5452
/// `true` or `false`.
5553
Bool(bool),
5654
/// An array of constants.
@@ -172,8 +170,7 @@ impl Hash for Constant {
172170
i.hash(state);
173171
},
174172
Self::F16(f) => {
175-
// FIXME(f16_f128): once conversions to/from `f128` are available on all platforms,
176-
f.hash(state);
173+
f64::from(f).to_bits().hash(state);
177174
},
178175
Self::F32(f) => {
179176
f64::from(f).to_bits().hash(state);
@@ -182,7 +179,7 @@ impl Hash for Constant {
182179
f.to_bits().hash(state);
183180
},
184181
Self::F128(f) => {
185-
f.hash(state);
182+
f.to_bits().hash(state);
186183
},
187184
Self::Bool(b) => {
188185
b.hash(state);
@@ -284,14 +281,9 @@ impl Constant {
284281
self
285282
}
286283

287-
fn parse_f16(s: &str) -> Self {
288-
let f: Half = s.parse().unwrap();
289-
Self::F16(f.to_bits().try_into().unwrap())
290-
}
291-
292284
fn parse_f128(s: &str) -> Self {
293285
let f: Quad = s.parse().unwrap();
294-
Self::F128(f.to_bits())
286+
Self::F128(f128::from_bits(f.to_bits()))
295287
}
296288

297289
pub fn new_numeric_min<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Self> {
@@ -397,18 +389,20 @@ impl Constant {
397389

398390
pub fn is_pos_infinity(&self) -> bool {
399391
match *self {
400-
// FIXME(f16_f128): add f16 and f128 when constants are available
392+
Constant::F16(x) => x == f16::INFINITY,
401393
Constant::F32(x) => x == f32::INFINITY,
402394
Constant::F64(x) => x == f64::INFINITY,
395+
Constant::F128(x) => x == f128::INFINITY,
403396
_ => false,
404397
}
405398
}
406399

407400
pub fn is_neg_infinity(&self) -> bool {
408401
match *self {
409-
// FIXME(f16_f128): add f16 and f128 when constants are available
402+
Constant::F16(x) => x == f16::NEG_INFINITY,
410403
Constant::F32(x) => x == f32::NEG_INFINITY,
411404
Constant::F64(x) => x == f64::NEG_INFINITY,
405+
Constant::F128(x) => x == f128::NEG_INFINITY,
412406
_ => false,
413407
}
414408
}
@@ -423,14 +417,14 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
423417
LitKind::Char(c) => Constant::Char(c),
424418
LitKind::Int(n, _) => Constant::Int(n.get()),
425419
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
426-
// FIXME(f16_f128): just use `parse()` directly when available for `f16`/`f128`
427-
FloatTy::F16 => Constant::parse_f16(is.as_str()),
420+
FloatTy::F16 => Constant::F16(is.as_str().parse().unwrap()),
428421
FloatTy::F32 => Constant::F32(is.as_str().parse().unwrap()),
429422
FloatTy::F64 => Constant::F64(is.as_str().parse().unwrap()),
423+
// FIXME(f16_f128): just use `parse()` directly when available for `f128`
430424
FloatTy::F128 => Constant::parse_f128(is.as_str()),
431425
},
432426
LitKind::Float(ref is, LitFloatType::Unsuffixed) => match ty.expect("type of float is known").kind() {
433-
ty::Float(FloatTy::F16) => Constant::parse_f16(is.as_str()),
427+
ty::Float(FloatTy::F16) => Constant::F16(is.as_str().parse().unwrap()),
434428
ty::Float(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()),
435429
ty::Float(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()),
436430
ty::Float(FloatTy::F128) => Constant::parse_f128(is.as_str()),
@@ -935,6 +929,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
935929
}
936930
}
937931

932+
#[expect(clippy::too_many_lines)]
938933
fn binop(&self, op: BinOpKind, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant> {
939934
let l = self.expr(left)?;
940935
let r = self.expr(right);
@@ -1006,7 +1001,20 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
10061001
},
10071002
_ => None,
10081003
},
1009-
// FIXME(f16_f128): add these types when binary operations are available on all platforms
1004+
(Constant::F16(l), Some(Constant::F16(r))) => match op {
1005+
BinOpKind::Add => Some(Constant::F16(l + r)),
1006+
BinOpKind::Sub => Some(Constant::F16(l - r)),
1007+
BinOpKind::Mul => Some(Constant::F16(l * r)),
1008+
BinOpKind::Div => Some(Constant::F16(l / r)),
1009+
BinOpKind::Rem => Some(Constant::F16(l % r)),
1010+
BinOpKind::Eq => Some(Constant::Bool(l == r)),
1011+
BinOpKind::Ne => Some(Constant::Bool(l != r)),
1012+
BinOpKind::Lt => Some(Constant::Bool(l < r)),
1013+
BinOpKind::Le => Some(Constant::Bool(l <= r)),
1014+
BinOpKind::Ge => Some(Constant::Bool(l >= r)),
1015+
BinOpKind::Gt => Some(Constant::Bool(l > r)),
1016+
_ => None,
1017+
},
10101018
(Constant::F32(l), Some(Constant::F32(r))) => match op {
10111019
BinOpKind::Add => Some(Constant::F32(l + r)),
10121020
BinOpKind::Sub => Some(Constant::F32(l - r)),
@@ -1035,6 +1043,20 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
10351043
BinOpKind::Gt => Some(Constant::Bool(l > r)),
10361044
_ => None,
10371045
},
1046+
(Constant::F128(l), Some(Constant::F128(r))) => match op {
1047+
BinOpKind::Add => Some(Constant::F128(l + r)),
1048+
BinOpKind::Sub => Some(Constant::F128(l - r)),
1049+
BinOpKind::Mul => Some(Constant::F128(l * r)),
1050+
BinOpKind::Div => Some(Constant::F128(l / r)),
1051+
BinOpKind::Rem => Some(Constant::F128(l % r)),
1052+
BinOpKind::Eq => Some(Constant::Bool(l == r)),
1053+
BinOpKind::Ne => Some(Constant::Bool(l != r)),
1054+
BinOpKind::Lt => Some(Constant::Bool(l < r)),
1055+
BinOpKind::Le => Some(Constant::Bool(l <= r)),
1056+
BinOpKind::Ge => Some(Constant::Bool(l >= r)),
1057+
BinOpKind::Gt => Some(Constant::Bool(l > r)),
1058+
_ => None,
1059+
},
10381060
(l, r) => match (op, l, r) {
10391061
(BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)),
10401062
(BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)),
@@ -1056,10 +1078,10 @@ pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, val: ConstValue, ty: Ty<'tcx>) -> O
10561078
(ConstValue::Scalar(Scalar::Int(int)), _) => match ty.kind() {
10571079
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
10581080
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.to_bits(int.size()))),
1059-
ty::Float(FloatTy::F16) => Some(Constant::F16(int.into())),
1081+
ty::Float(FloatTy::F16) => Some(Constant::F16(f16::from_bits(int.into()))),
10601082
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(int.into()))),
10611083
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(int.into()))),
1062-
ty::Float(FloatTy::F128) => Some(Constant::F128(int.into())),
1084+
ty::Float(FloatTy::F128) => Some(Constant::F128(f128::from_bits(int.into()))),
10631085
ty::RawPtr(_, _) => Some(Constant::RawPtr(int.to_bits(int.size()))),
10641086
_ => None,
10651087
},
@@ -1079,10 +1101,10 @@ pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, val: ConstValue, ty: Ty<'tcx>) -> O
10791101
let range = alloc_range(offset + size * idx, size);
10801102
let val = alloc.read_scalar(&tcx, range, /* read_provenance */ false).ok()?;
10811103
res.push(match flt {
1082-
FloatTy::F16 => Constant::F16(val.to_u16().discard_err()?),
1104+
FloatTy::F16 => Constant::F16(f16::from_bits(val.to_u16().discard_err()?)),
10831105
FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().discard_err()?)),
10841106
FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().discard_err()?)),
1085-
FloatTy::F128 => Constant::F128(val.to_u128().discard_err()?),
1107+
FloatTy::F128 => Constant::F128(f128::from_bits(val.to_u128().discard_err()?)),
10861108
});
10871109
}
10881110
Some(Constant::Vec(res))

clippy_utils/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#![feature(box_patterns)]
2+
#![feature(f128)]
3+
#![feature(f16)]
24
#![feature(if_let_guard)]
35
#![feature(macro_metavar_expr)]
46
#![feature(never_type)]

tests/ui/arithmetic_side_effects.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,9 @@ pub fn association_with_structures_should_not_trigger_the_lint() {
165165

166166
pub fn hard_coded_allowed() {
167167
let _ = 1f16 + 1f16;
168-
//~^ arithmetic_side_effects
169168
let _ = 1f32 + 1f32;
170169
let _ = 1f64 + 1f64;
171170
let _ = 1f128 + 1f128;
172-
//~^ arithmetic_side_effects
173171

174172
let _ = Saturating(0u32) + Saturating(0u32);
175173
let _ = String::new() + "";

0 commit comments

Comments
 (0)