lint: Use rustc_apfloat for overflowing_literals, add f16 and f128
Switch to parsing float literals for overflow checks using `rustc_apfloat` rather than host floats. This avoids small variations in platform support and makes it possible to start checking `f16` and `f128` as well. Using APFloat matches what we try to do elsewhere to avoid platform inconsistencies.
This commit is contained in:
parent
d10ac47c20
commit
9b15010686
6 changed files with 77 additions and 22 deletions
|
|
@ -7,6 +7,7 @@ edition = "2024"
|
|||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_apfloat = "0.2.0"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
use hir::{ExprKind, Node};
|
||||
use rustc_abi::{Integer, Size};
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_apfloat::ieee::{DoubleS, HalfS, IeeeFloat, QuadS, Semantics, SingleS};
|
||||
use rustc_hir::{HirId, attrs};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
use crate::LateContext;
|
||||
|
|
@ -383,6 +385,13 @@ fn lint_uint_literal<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
/// `None` if `v` does not parse as the float type, otherwise indicates whether a literal rounds
|
||||
/// to infinity.
|
||||
fn float_is_infinite<S: Semantics>(v: Symbol) -> Option<bool> {
|
||||
let x: IeeeFloat<S> = v.as_str().parse().ok()?;
|
||||
Some(x.is_infinite())
|
||||
}
|
||||
|
||||
pub(crate) fn lint_literal<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
type_limits: &TypeLimits,
|
||||
|
|
@ -405,18 +414,18 @@ pub(crate) fn lint_literal<'tcx>(
|
|||
lint_uint_literal(cx, hir_id, span, lit, t)
|
||||
}
|
||||
ty::Float(t) => {
|
||||
let (is_infinite, sym) = match lit.node {
|
||||
ast::LitKind::Float(v, _) => match t {
|
||||
// FIXME(f16_f128): add this check once `is_infinite` is reliable (ABI
|
||||
// issues resolved).
|
||||
ty::FloatTy::F16 => (Ok(false), v),
|
||||
ty::FloatTy::F32 => (v.as_str().parse().map(f32::is_infinite), v),
|
||||
ty::FloatTy::F64 => (v.as_str().parse().map(f64::is_infinite), v),
|
||||
ty::FloatTy::F128 => (Ok(false), v),
|
||||
},
|
||||
_ => bug!(),
|
||||
let ast::LitKind::Float(v, _) = lit.node else {
|
||||
bug!();
|
||||
};
|
||||
if is_infinite == Ok(true) {
|
||||
|
||||
let is_infinite = match t {
|
||||
ty::FloatTy::F16 => float_is_infinite::<HalfS>(v),
|
||||
ty::FloatTy::F32 => float_is_infinite::<SingleS>(v),
|
||||
ty::FloatTy::F64 => float_is_infinite::<DoubleS>(v),
|
||||
ty::FloatTy::F128 => float_is_infinite::<QuadS>(v),
|
||||
};
|
||||
|
||||
if is_infinite == Some(true) {
|
||||
cx.emit_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
span,
|
||||
|
|
@ -426,7 +435,7 @@ pub(crate) fn lint_literal<'tcx>(
|
|||
.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(lit.span)
|
||||
.unwrap_or_else(|_| sym.to_string()),
|
||||
.unwrap_or_else(|_| v.to_string()),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue