Skip to content

Commit e03c7af

Browse files
committed
Treat f16 and f128 as floats in constant evaluation
1 parent 25cbcb4 commit e03c7af

File tree

8 files changed

+225
-193
lines changed

8 files changed

+225
-193
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::{BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, PatExpr, PatExprKind, QPath, TyKind, UnOp};
@@ -38,16 +38,14 @@ pub enum Constant {
3838
Char(char),
3939
/// An integer's bit representation.
4040
Int(u128),
41-
/// An `f16` bitcast to a `u16`.
42-
// FIXME(f16_f128): use `f16` once builtins are available on all host tools platforms.
43-
F16(u16),
41+
/// An `f16`.
42+
F16(f16),
4443
/// An `f32`.
4544
F32(f32),
4645
/// An `f64`.
4746
F64(f64),
4847
/// An `f128` bitcast to a `u128`.
49-
// FIXME(f16_f128): use `f128` once builtins are available on all host tools platforms.
50-
F128(u128),
48+
F128(f128),
5149
/// `true` or `false`.
5250
Bool(bool),
5351
/// An array of constants.
@@ -169,8 +167,7 @@ impl Hash for Constant {
169167
i.hash(state);
170168
},
171169
Self::F16(f) => {
172-
// FIXME(f16_f128): once conversions to/from `f128` are available on all platforms,
173-
f.hash(state);
170+
f64::from(f).to_bits().hash(state);
174171
},
175172
Self::F32(f) => {
176173
f64::from(f).to_bits().hash(state);
@@ -179,7 +176,7 @@ impl Hash for Constant {
179176
f.to_bits().hash(state);
180177
},
181178
Self::F128(f) => {
182-
f.hash(state);
179+
f.to_bits().hash(state);
183180
},
184181
Self::Bool(b) => {
185182
b.hash(state);
@@ -281,14 +278,9 @@ impl Constant {
281278
self
282279
}
283280

284-
fn parse_f16(s: &str) -> Self {
285-
let f: Half = s.parse().unwrap();
286-
Self::F16(f.to_bits().try_into().unwrap())
287-
}
288-
289281
fn parse_f128(s: &str) -> Self {
290282
let f: Quad = s.parse().unwrap();
291-
Self::F128(f.to_bits())
283+
Self::F128(f128::from_bits(f.to_bits()))
292284
}
293285

294286
pub fn new_numeric_min<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Self> {
@@ -394,18 +386,20 @@ impl Constant {
394386

395387
pub fn is_pos_infinity(&self) -> bool {
396388
match *self {
397-
// FIXME(f16_f128): add f16 and f128 when constants are available
389+
Constant::F16(x) => x == f16::INFINITY,
398390
Constant::F32(x) => x == f32::INFINITY,
399391
Constant::F64(x) => x == f64::INFINITY,
392+
Constant::F128(x) => x == f128::INFINITY,
400393
_ => false,
401394
}
402395
}
403396

404397
pub fn is_neg_infinity(&self) -> bool {
405398
match *self {
406-
// FIXME(f16_f128): add f16 and f128 when constants are available
399+
Constant::F16(x) => x == f16::NEG_INFINITY,
407400
Constant::F32(x) => x == f32::NEG_INFINITY,
408401
Constant::F64(x) => x == f64::NEG_INFINITY,
402+
Constant::F128(x) => x == f128::NEG_INFINITY,
409403
_ => false,
410404
}
411405
}
@@ -420,14 +414,14 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
420414
LitKind::Char(c) => Constant::Char(c),
421415
LitKind::Int(n, _) => Constant::Int(n.get()),
422416
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
423-
// FIXME(f16_f128): just use `parse()` directly when available for `f16`/`f128`
424-
FloatTy::F16 => Constant::parse_f16(is.as_str()),
417+
FloatTy::F16 => Constant::F16(is.as_str().parse().unwrap()),
425418
FloatTy::F32 => Constant::F32(is.as_str().parse().unwrap()),
426419
FloatTy::F64 => Constant::F64(is.as_str().parse().unwrap()),
420+
// FIXME(f16_f128): just use `parse()` directly when available for `f128`
427421
FloatTy::F128 => Constant::parse_f128(is.as_str()),
428422
},
429423
LitKind::Float(ref is, LitFloatType::Unsuffixed) => match ty.expect("type of float is known").kind() {
430-
ty::Float(FloatTy::F16) => Constant::parse_f16(is.as_str()),
424+
ty::Float(FloatTy::F16) => Constant::F16(is.as_str().parse().unwrap()),
431425
ty::Float(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()),
432426
ty::Float(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()),
433427
ty::Float(FloatTy::F128) => Constant::parse_f128(is.as_str()),
@@ -932,6 +926,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
932926
}
933927
}
934928

929+
#[expect(clippy::too_many_lines)]
935930
fn binop(&self, op: BinOpKind, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant> {
936931
let l = self.expr(left)?;
937932
let r = self.expr(right);
@@ -1003,7 +998,20 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
1003998
},
1004999
_ => None,
10051000
},
1006-
// FIXME(f16_f128): add these types when binary operations are available on all platforms
1001+
(Constant::F16(l), Some(Constant::F16(r))) => match op {
1002+
BinOpKind::Add => Some(Constant::F16(l + r)),
1003+
BinOpKind::Sub => Some(Constant::F16(l - r)),
1004+
BinOpKind::Mul => Some(Constant::F16(l * r)),
1005+
BinOpKind::Div => Some(Constant::F16(l / r)),
1006+
BinOpKind::Rem => Some(Constant::F16(l % r)),
1007+
BinOpKind::Eq => Some(Constant::Bool(l == r)),
1008+
BinOpKind::Ne => Some(Constant::Bool(l != r)),
1009+
BinOpKind::Lt => Some(Constant::Bool(l < r)),
1010+
BinOpKind::Le => Some(Constant::Bool(l <= r)),
1011+
BinOpKind::Ge => Some(Constant::Bool(l >= r)),
1012+
BinOpKind::Gt => Some(Constant::Bool(l > r)),
1013+
_ => None,
1014+
},
10071015
(Constant::F32(l), Some(Constant::F32(r))) => match op {
10081016
BinOpKind::Add => Some(Constant::F32(l + r)),
10091017
BinOpKind::Sub => Some(Constant::F32(l - r)),
@@ -1032,6 +1040,20 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
10321040
BinOpKind::Gt => Some(Constant::Bool(l > r)),
10331041
_ => None,
10341042
},
1043+
(Constant::F128(l), Some(Constant::F128(r))) => match op {
1044+
BinOpKind::Add => Some(Constant::F128(l + r)),
1045+
BinOpKind::Sub => Some(Constant::F128(l - r)),
1046+
BinOpKind::Mul => Some(Constant::F128(l * r)),
1047+
BinOpKind::Div => Some(Constant::F128(l / r)),
1048+
BinOpKind::Rem => Some(Constant::F128(l % r)),
1049+
BinOpKind::Eq => Some(Constant::Bool(l == r)),
1050+
BinOpKind::Ne => Some(Constant::Bool(l != r)),
1051+
BinOpKind::Lt => Some(Constant::Bool(l < r)),
1052+
BinOpKind::Le => Some(Constant::Bool(l <= r)),
1053+
BinOpKind::Ge => Some(Constant::Bool(l >= r)),
1054+
BinOpKind::Gt => Some(Constant::Bool(l > r)),
1055+
_ => None,
1056+
},
10351057
(l, r) => match (op, l, r) {
10361058
(BinOpKind::And, Constant::Bool(false), _) => Some(Constant::Bool(false)),
10371059
(BinOpKind::Or, Constant::Bool(true), _) => Some(Constant::Bool(true)),
@@ -1053,10 +1075,10 @@ pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, val: ConstValue, ty: Ty<'tcx>) -> O
10531075
(ConstValue::Scalar(Scalar::Int(int)), _) => match ty.kind() {
10541076
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
10551077
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.to_bits(int.size()))),
1056-
ty::Float(FloatTy::F16) => Some(Constant::F16(int.into())),
1078+
ty::Float(FloatTy::F16) => Some(Constant::F16(f16::from_bits(int.into()))),
10571079
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(int.into()))),
10581080
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(int.into()))),
1059-
ty::Float(FloatTy::F128) => Some(Constant::F128(int.into())),
1081+
ty::Float(FloatTy::F128) => Some(Constant::F128(f128::from_bits(int.into()))),
10601082
ty::RawPtr(_, _) => Some(Constant::RawPtr(int.to_bits(int.size()))),
10611083
_ => None,
10621084
},
@@ -1076,10 +1098,10 @@ pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, val: ConstValue, ty: Ty<'tcx>) -> O
10761098
let range = alloc_range(offset + size * idx, size);
10771099
let val = alloc.read_scalar(&tcx, range, /* read_provenance */ false).ok()?;
10781100
res.push(match flt {
1079-
FloatTy::F16 => Constant::F16(val.to_u16().discard_err()?),
1101+
FloatTy::F16 => Constant::F16(f16::from_bits(val.to_u16().discard_err()?)),
10801102
FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().discard_err()?)),
10811103
FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().discard_err()?)),
1082-
FloatTy::F128 => Constant::F128(val.to_u128().discard_err()?),
1104+
FloatTy::F128 => Constant::F128(f128::from_bits(val.to_u128().discard_err()?)),
10831105
});
10841106
}
10851107
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
@@ -164,11 +164,9 @@ pub fn association_with_structures_should_not_trigger_the_lint() {
164164

165165
pub fn hard_coded_allowed() {
166166
let _ = 1f16 + 1f16;
167-
//~^ arithmetic_side_effects
168167
let _ = 1f32 + 1f32;
169168
let _ = 1f64 + 1f64;
170169
let _ = 1f128 + 1f128;
171-
//~^ arithmetic_side_effects
172170

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

0 commit comments

Comments
 (0)