From f8bc571df70a0832890bbed82ff80d4c9921b6ac Mon Sep 17 00:00:00 2001 From: Falco Hirschenberger Date: Wed, 9 Jul 2014 09:45:32 +0200 Subject: [PATCH] Add range lint for float literals, fixing #10934 --- src/libcore/num/f32.rs | 2 ++ src/libcore/num/f64.rs | 2 ++ src/librustc/lint/builtin.rs | 32 +++++++++++++++------ src/test/compile-fail/lint-type-overflow.rs | 5 ++++ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index cadc874891d20..82745663e0cad 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -11,6 +11,8 @@ //! Operations and constants for 32-bits floats (`f32` type) #![doc(primitive = "f32")] +// FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353 +#![allow(type_overflow)] use intrinsics; use mem; diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 5e19015dd0281..a3a82aeec5ec7 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -11,6 +11,8 @@ //! Operations and constants for 64-bits floats (`f64` type) #![doc(primitive = "f64")] +// FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353 +#![allow(type_overflow)] use intrinsics; use mem; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 481187f7c2ce7..0f799e26cc741 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -37,14 +37,7 @@ use lint::{Context, LintPass, LintArray}; use std::cmp; use std::collections::HashMap; -use std::i16; -use std::i32; -use std::i64; -use std::i8; -use std::u16; -use std::u32; -use std::u64; -use std::u8; +use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; use std::gc::Gc; use syntax::abi; use syntax::ast_map; @@ -214,7 +207,21 @@ impl LintPass for TypeLimits { "literal out of range for its type"); } }, - + ty::ty_float(t) => { + let (min, max) = float_ty_range(t); + let lit_val: f64 = match lit.node { + ast::LitFloat(ref v, _) | + ast::LitFloatUnsuffixed(ref v) => match from_str(v.get()) { + Some(f) => f, + None => return + }, + _ => fail!() + }; + if lit_val < min || lit_val > max { + cx.span_lint(TYPE_OVERFLOW, e.span, + "literal out of range for its type"); + } + }, _ => () }; }, @@ -265,6 +272,13 @@ impl LintPass for TypeLimits { } } + fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) { + match float_ty { + ast::TyF32 => (f32::MIN_VALUE as f64, f32::MAX_VALUE as f64), + ast::TyF64 => (f64::MIN_VALUE, f64::MAX_VALUE) + } + } + fn check_limits(tcx: &ty::ctxt, binop: ast::BinOp, l: &ast::Expr, r: &ast::Expr) -> bool { let (lit, expr, swap) = match (&l.node, &r.node) { diff --git a/src/test/compile-fail/lint-type-overflow.rs b/src/test/compile-fail/lint-type-overflow.rs index e5a5c7dd1c7c2..676a6e7cb4452 100644 --- a/src/test/compile-fail/lint-type-overflow.rs +++ b/src/test/compile-fail/lint-type-overflow.rs @@ -47,4 +47,9 @@ fn main() { let x = -2147483648_i32; // should be OK let x: i32 = -2147483649; //~ error: literal out of range for its type let x = -2147483649_i32; //~ error: literal out of range for its type + + let x = -3.40282348e+38_f32; //~ error: literal out of range for its type + let x = 3.40282348e+38_f32; //~ error: literal out of range for its type + let x = -1.7976931348623159e+308_f64; //~ error: literal out of range for its type + let x = 1.7976931348623159e+308_f64; //~ error: literal out of range for its type }