Rollup merge of #151529 - tgross35:lint-apfloat, r=nnethercote
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:
commit
af523529be
6 changed files with 77 additions and 22 deletions
|
|
@ -4170,6 +4170,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"bitflags",
|
||||
"rustc_abi",
|
||||
"rustc_apfloat",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr_parsing",
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,14 @@ macro_rules! impl_general_format {
|
|||
($($t:ident)*) => {
|
||||
$(impl GeneralFormat for $t {
|
||||
fn already_rounded_value_should_use_exponential(&self) -> bool {
|
||||
// `max_abs` rounds to infinity for `f16`. This is fine to save us from a more
|
||||
// complex macro, it just means a positive-exponent `f16` will never print as
|
||||
// scientific notation by default (reasonably, the max is 65504.0).
|
||||
#[allow(overflowing_literals)]
|
||||
let max_abs = 1e+16;
|
||||
|
||||
let abs = $t::abs(*self);
|
||||
(abs != 0.0 && abs < 1e-4) || abs >= 1e+16
|
||||
(abs != 0.0 && abs < 1e-4) || abs >= max_abs
|
||||
}
|
||||
})*
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
//@ compile-flags: -O
|
||||
|
||||
#![feature(f16)]
|
||||
#![feature(f128)]
|
||||
#![deny(overflowing_literals)]
|
||||
|
||||
fn main() {
|
||||
let x2: i8 = --128; //~ ERROR literal out of range for `i8`
|
||||
//~| WARN use of a double negation
|
||||
|
||||
let x = -65520.0_f16; //~ ERROR literal out of range for `f16`
|
||||
let x = 65520.0_f16; //~ ERROR literal out of range for `f16`
|
||||
let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
|
||||
let x = 3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
|
||||
let x = -1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64`
|
||||
let x = 1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64`
|
||||
let x = -1.1897314953572317650857593266280075e+4932_f128; //~ ERROR literal out of range for `f128`
|
||||
let x = 1.1897314953572317650857593266280075e+4932_f128; //~ ERROR literal out of range for `f128`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
warning: use of a double negation
|
||||
--> $DIR/lint-type-overflow2.rs:6:18
|
||||
--> $DIR/lint-type-overflow2.rs:8:18
|
||||
|
|
||||
LL | let x2: i8 = --128;
|
||||
| ^^^^^
|
||||
|
|
@ -13,7 +13,7 @@ LL | let x2: i8 = -(-128);
|
|||
| + +
|
||||
|
||||
error: literal out of range for `i8`
|
||||
--> $DIR/lint-type-overflow2.rs:6:20
|
||||
--> $DIR/lint-type-overflow2.rs:8:20
|
||||
|
|
||||
LL | let x2: i8 = --128;
|
||||
| ^^^
|
||||
|
|
@ -21,13 +21,29 @@ LL | let x2: i8 = --128;
|
|||
= note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
|
||||
= help: consider using the type `u8` instead
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-type-overflow2.rs:3:9
|
||||
--> $DIR/lint-type-overflow2.rs:5:9
|
||||
|
|
||||
LL | #![deny(overflowing_literals)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for `f16`
|
||||
--> $DIR/lint-type-overflow2.rs:11:14
|
||||
|
|
||||
LL | let x = -65520.0_f16;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: the literal `65520.0_f16` does not fit into the type `f16` and will be converted to `f16::INFINITY`
|
||||
|
||||
error: literal out of range for `f16`
|
||||
--> $DIR/lint-type-overflow2.rs:12:14
|
||||
|
|
||||
LL | let x = 65520.0_f16;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: the literal `65520.0_f16` does not fit into the type `f16` and will be converted to `f16::INFINITY`
|
||||
|
||||
error: literal out of range for `f32`
|
||||
--> $DIR/lint-type-overflow2.rs:9:14
|
||||
--> $DIR/lint-type-overflow2.rs:13:14
|
||||
|
|
||||
LL | let x = -3.40282357e+38_f32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -35,7 +51,7 @@ LL | let x = -3.40282357e+38_f32;
|
|||
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
|
||||
|
||||
error: literal out of range for `f32`
|
||||
--> $DIR/lint-type-overflow2.rs:10:14
|
||||
--> $DIR/lint-type-overflow2.rs:14:14
|
||||
|
|
||||
LL | let x = 3.40282357e+38_f32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -43,7 +59,7 @@ LL | let x = 3.40282357e+38_f32;
|
|||
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
|
||||
|
||||
error: literal out of range for `f64`
|
||||
--> $DIR/lint-type-overflow2.rs:11:14
|
||||
--> $DIR/lint-type-overflow2.rs:15:14
|
||||
|
|
||||
LL | let x = -1.7976931348623159e+308_f64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -51,12 +67,28 @@ LL | let x = -1.7976931348623159e+308_f64;
|
|||
= note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
|
||||
|
||||
error: literal out of range for `f64`
|
||||
--> $DIR/lint-type-overflow2.rs:12:14
|
||||
--> $DIR/lint-type-overflow2.rs:16:14
|
||||
|
|
||||
LL | let x = 1.7976931348623159e+308_f64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
|
||||
|
||||
error: aborting due to 5 previous errors; 1 warning emitted
|
||||
error: literal out of range for `f128`
|
||||
--> $DIR/lint-type-overflow2.rs:17:14
|
||||
|
|
||||
LL | let x = -1.1897314953572317650857593266280075e+4932_f128;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the literal `1.1897314953572317650857593266280075e+4932_f128` does not fit into the type `f128` and will be converted to `f128::INFINITY`
|
||||
|
||||
error: literal out of range for `f128`
|
||||
--> $DIR/lint-type-overflow2.rs:18:14
|
||||
|
|
||||
LL | let x = 1.1897314953572317650857593266280075e+4932_f128;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the literal `1.1897314953572317650857593266280075e+4932_f128` does not fit into the type `f128` and will be converted to `f128::INFINITY`
|
||||
|
||||
error: aborting due to 9 previous errors; 1 warning emitted
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue