Rollup merge of #60330 - varkor:range-endpoint-overflow-lint, r=estebank
Suggest using an inclusive range instead of an exclusive range when the endpoint overflows by 1 Fixes https://github.com/rust-lang/rust/issues/47213.
This commit is contained in:
commit
6d78142bf0
19 changed files with 551 additions and 399 deletions
|
|
@ -5400,3 +5400,65 @@ fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
|
|||
body_ids.sort_by_key(|b| bodies[b].value.span);
|
||||
body_ids
|
||||
}
|
||||
|
||||
/// Checks if the specified expression is a built-in range literal.
|
||||
/// (See: `LoweringContext::lower_expr()`).
|
||||
pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool {
|
||||
use hir::{Path, QPath, ExprKind, TyKind};
|
||||
|
||||
// Returns whether the given path represents a (desugared) range,
|
||||
// either in std or core, i.e. has either a `::std::ops::Range` or
|
||||
// `::core::ops::Range` prefix.
|
||||
fn is_range_path(path: &Path) -> bool {
|
||||
let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.as_str().to_string()).collect();
|
||||
let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
|
||||
|
||||
// "{{root}}" is the equivalent of `::` prefix in `Path`.
|
||||
if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
|
||||
(*std_core == "std" || *std_core == "core") && range.starts_with("Range")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
// Check whether a span corresponding to a range expression is a
|
||||
// range literal, rather than an explicit struct or `new()` call.
|
||||
fn is_lit(sess: &Session, span: &Span) -> bool {
|
||||
let source_map = sess.source_map();
|
||||
let end_point = source_map.end_point(*span);
|
||||
|
||||
if let Ok(end_string) = source_map.span_to_snippet(end_point) {
|
||||
!(end_string.ends_with("}") || end_string.ends_with(")"))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
match expr.node {
|
||||
// All built-in range literals but `..=` and `..` desugar to `Struct`s.
|
||||
ExprKind::Struct(ref qpath, _, _) => {
|
||||
if let QPath::Resolved(None, ref path) = **qpath {
|
||||
return is_range_path(&path) && is_lit(sess, &expr.span);
|
||||
}
|
||||
}
|
||||
|
||||
// `..` desugars to its struct path.
|
||||
ExprKind::Path(QPath::Resolved(None, ref path)) => {
|
||||
return is_range_path(&path) && is_lit(sess, &expr.span);
|
||||
}
|
||||
|
||||
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
|
||||
ExprKind::Call(ref func, _) => {
|
||||
if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node {
|
||||
if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node {
|
||||
let new_call = segment.ident.as_str() == "new";
|
||||
return is_range_path(&path) && is_lit(sess, &expr.span) && new_call;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use rustc::hir::Node;
|
||||
use rustc::hir::{ExprKind, Node};
|
||||
use rustc::hir::lowering::is_range_literal;
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
||||
use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx};
|
||||
|
|
@ -57,6 +58,347 @@ impl TypeLimits {
|
|||
}
|
||||
}
|
||||
|
||||
/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint.
|
||||
/// Returns `true` iff the lint was overridden.
|
||||
fn lint_overflowing_range_endpoint<'a, 'tcx>(
|
||||
cx: &LateContext<'a, 'tcx>,
|
||||
lit: &ast::Lit,
|
||||
lit_val: u128,
|
||||
max: u128,
|
||||
expr: &'tcx hir::Expr,
|
||||
parent_expr: &'tcx hir::Expr,
|
||||
ty: impl std::fmt::Debug,
|
||||
) -> bool {
|
||||
// We only want to handle exclusive (`..`) ranges,
|
||||
// which are represented as `ExprKind::Struct`.
|
||||
if let ExprKind::Struct(_, eps, _) = &parent_expr.node {
|
||||
debug_assert_eq!(eps.len(), 2);
|
||||
// We can suggest using an inclusive range
|
||||
// (`..=`) instead only if it is the `end` that is
|
||||
// overflowing and only by 1.
|
||||
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
|
||||
let mut err = cx.struct_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
parent_expr.span,
|
||||
&format!("range endpoint is out of range for `{:?}`", ty),
|
||||
);
|
||||
if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
|
||||
use ast::{LitKind, LitIntType};
|
||||
// We need to preserve the literal's suffix,
|
||||
// as it may determine typing information.
|
||||
let suffix = match lit.node {
|
||||
LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s),
|
||||
LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s),
|
||||
LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(),
|
||||
_ => bug!(),
|
||||
};
|
||||
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
|
||||
err.span_suggestion(
|
||||
parent_expr.span,
|
||||
&"use an inclusive range instead",
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
// For `isize` & `usize`, be conservative with the warnings, so that the
|
||||
// warnings are consistent between 32- and 64-bit platforms.
|
||||
fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) {
|
||||
match int_ty {
|
||||
ast::IntTy::Isize => (i64::min_value() as i128, i64::max_value() as i128),
|
||||
ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128),
|
||||
ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128),
|
||||
ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128),
|
||||
ast::IntTy::I64 => (i64::min_value() as i128, i64::max_value() as i128),
|
||||
ast::IntTy::I128 =>(i128::min_value() as i128, i128::max_value()),
|
||||
}
|
||||
}
|
||||
|
||||
fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
|
||||
match uint_ty {
|
||||
ast::UintTy::Usize => (u64::min_value() as u128, u64::max_value() as u128),
|
||||
ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128),
|
||||
ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128),
|
||||
ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128),
|
||||
ast::UintTy::U64 => (u64::min_value() as u128, u64::max_value() as u128),
|
||||
ast::UintTy::U128 => (u128::min_value(), u128::max_value()),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &ast::Lit) -> Option<String> {
|
||||
let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?;
|
||||
let firstch = src.chars().next()?;
|
||||
|
||||
if firstch == '0' {
|
||||
match src.chars().nth(1) {
|
||||
Some('x') | Some('b') => return Some(src),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn report_bin_hex_error(
|
||||
cx: &LateContext<'_, '_>,
|
||||
expr: &hir::Expr,
|
||||
ty: attr::IntType,
|
||||
repr_str: String,
|
||||
val: u128,
|
||||
negative: bool,
|
||||
) {
|
||||
let size = layout::Integer::from_attr(&cx.tcx, ty).size();
|
||||
let (t, actually) = match ty {
|
||||
attr::IntType::SignedInt(t) => {
|
||||
let actually = sign_extend(val, size) as i128;
|
||||
(format!("{:?}", t), actually.to_string())
|
||||
}
|
||||
attr::IntType::UnsignedInt(t) => {
|
||||
let actually = truncate(val, size);
|
||||
(format!("{:?}", t), actually.to_string())
|
||||
}
|
||||
};
|
||||
let mut err = cx.struct_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
expr.span,
|
||||
&format!("literal out of range for {}", t),
|
||||
);
|
||||
err.note(&format!(
|
||||
"the literal `{}` (decimal `{}`) does not fit into \
|
||||
an `{}` and will become `{}{}`",
|
||||
repr_str, val, t, actually, t
|
||||
));
|
||||
if let Some(sugg_ty) =
|
||||
get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative)
|
||||
{
|
||||
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
|
||||
let (sans_suffix, _) = repr_str.split_at(pos);
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
&format!("consider using `{}` instead", sugg_ty),
|
||||
format!("{}{}", sans_suffix, sugg_ty),
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
} else {
|
||||
err.help(&format!("consider using `{}` instead", sugg_ty));
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
// This function finds the next fitting type and generates a suggestion string.
|
||||
// It searches for fitting types in the following way (`X < Y`):
|
||||
// - `iX`: if literal fits in `uX` => `uX`, else => `iY`
|
||||
// - `-iX` => `iY`
|
||||
// - `uX` => `uY`
|
||||
//
|
||||
// No suggestion for: `isize`, `usize`.
|
||||
fn get_type_suggestion<'a>(
|
||||
t: Ty<'_>,
|
||||
val: u128,
|
||||
negative: bool,
|
||||
) -> Option<String> {
|
||||
use syntax::ast::IntTy::*;
|
||||
use syntax::ast::UintTy::*;
|
||||
macro_rules! find_fit {
|
||||
($ty:expr, $val:expr, $negative:expr,
|
||||
$($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => {
|
||||
{
|
||||
let _neg = if negative { 1 } else { 0 };
|
||||
match $ty {
|
||||
$($type => {
|
||||
$(if !negative && val <= uint_ty_range($utypes).1 {
|
||||
return Some(format!("{:?}", $utypes))
|
||||
})*
|
||||
$(if val <= int_ty_range($itypes).1 as u128 + _neg {
|
||||
return Some(format!("{:?}", $itypes))
|
||||
})*
|
||||
None
|
||||
},)*
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
match t.sty {
|
||||
ty::Int(i) => find_fit!(i, val, negative,
|
||||
I8 => [U8] => [I16, I32, I64, I128],
|
||||
I16 => [U16] => [I32, I64, I128],
|
||||
I32 => [U32] => [I64, I128],
|
||||
I64 => [U64] => [I128],
|
||||
I128 => [U128] => []),
|
||||
ty::Uint(u) => find_fit!(u, val, negative,
|
||||
U8 => [U8, U16, U32, U64, U128] => [],
|
||||
U16 => [U16, U32, U64, U128] => [],
|
||||
U32 => [U32, U64, U128] => [],
|
||||
U64 => [U64, U128] => [],
|
||||
U128 => [U128] => []),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_int_literal<'a, 'tcx>(
|
||||
cx: &LateContext<'a, 'tcx>,
|
||||
type_limits: &TypeLimits,
|
||||
e: &'tcx hir::Expr,
|
||||
lit: &ast::Lit,
|
||||
t: ast::IntTy,
|
||||
v: u128,
|
||||
) {
|
||||
let int_type = if let ast::IntTy::Isize = t {
|
||||
cx.sess().target.isize_ty
|
||||
} else {
|
||||
t
|
||||
};
|
||||
|
||||
let (_, max) = int_ty_range(int_type);
|
||||
let max = max as u128;
|
||||
let negative = type_limits.negated_expr_id == e.hir_id;
|
||||
|
||||
// Detect literal value out of range [min, max] inclusive
|
||||
// avoiding use of -min to prevent overflow/panic
|
||||
if (negative && v > max + 1) || (!negative && v > max) {
|
||||
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
|
||||
report_bin_hex_error(
|
||||
cx,
|
||||
e,
|
||||
attr::IntType::SignedInt(t),
|
||||
repr_str,
|
||||
v,
|
||||
negative,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let par_id = cx.tcx.hir().get_parent_node_by_hir_id(e.hir_id);
|
||||
if let Node::Expr(par_e) = cx.tcx.hir().get_by_hir_id(par_id) {
|
||||
if let hir::ExprKind::Struct(..) = par_e.node {
|
||||
if is_range_literal(cx.sess(), par_e)
|
||||
&& lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t)
|
||||
{
|
||||
// The overflowing literal lint was overridden.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cx.span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
e.span,
|
||||
&format!("literal out of range for `{:?}`", t),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_uint_literal<'a, 'tcx>(
|
||||
cx: &LateContext<'a, 'tcx>,
|
||||
e: &'tcx hir::Expr,
|
||||
lit: &ast::Lit,
|
||||
t: ast::UintTy,
|
||||
) {
|
||||
let uint_type = if let ast::UintTy::Usize = t {
|
||||
cx.sess().target.usize_ty
|
||||
} else {
|
||||
t
|
||||
};
|
||||
let (min, max) = uint_ty_range(uint_type);
|
||||
let lit_val: u128 = match lit.node {
|
||||
// _v is u8, within range by definition
|
||||
ast::LitKind::Byte(_v) => return,
|
||||
ast::LitKind::Int(v, _) => v,
|
||||
_ => bug!(),
|
||||
};
|
||||
if lit_val < min || lit_val > max {
|
||||
let parent_id = cx.tcx.hir().get_parent_node_by_hir_id(e.hir_id);
|
||||
if let Node::Expr(par_e) = cx.tcx.hir().get_by_hir_id(parent_id) {
|
||||
match par_e.node {
|
||||
hir::ExprKind::Cast(..) => {
|
||||
if let ty::Char = cx.tables.expr_ty(par_e).sty {
|
||||
let mut err = cx.struct_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
par_e.span,
|
||||
"only `u8` can be cast into `char`",
|
||||
);
|
||||
err.span_suggestion(
|
||||
par_e.span,
|
||||
&"use a `char` literal instead",
|
||||
format!("'\\u{{{:X}}}'", lit_val),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
hir::ExprKind::Struct(..)
|
||||
if is_range_literal(cx.sess(), par_e) => {
|
||||
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
|
||||
// The overflowing literal lint was overridden.
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
|
||||
report_bin_hex_error(cx, e, attr::IntType::UnsignedInt(t), repr_str, lit_val, false);
|
||||
return;
|
||||
}
|
||||
cx.span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
e.span,
|
||||
&format!("literal out of range for `{:?}`", t),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_literal<'a, 'tcx>(
|
||||
cx: &LateContext<'a, 'tcx>,
|
||||
type_limits: &TypeLimits,
|
||||
e: &'tcx hir::Expr,
|
||||
lit: &ast::Lit,
|
||||
) {
|
||||
match cx.tables.node_type(e.hir_id).sty {
|
||||
ty::Int(t) => {
|
||||
match lit.node {
|
||||
ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
|
||||
ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => {
|
||||
lint_int_literal(cx, type_limits, e, lit, t, v)
|
||||
}
|
||||
_ => bug!(),
|
||||
};
|
||||
}
|
||||
ty::Uint(t) => {
|
||||
lint_uint_literal(cx, e, lit, t)
|
||||
}
|
||||
ty::Float(t) => {
|
||||
let is_infinite = match lit.node {
|
||||
ast::LitKind::Float(v, _) |
|
||||
ast::LitKind::FloatUnsuffixed(v) => {
|
||||
match t {
|
||||
ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
|
||||
ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
|
||||
}
|
||||
}
|
||||
_ => bug!(),
|
||||
};
|
||||
if is_infinite == Ok(true) {
|
||||
cx.span_lint(OVERFLOWING_LITERALS,
|
||||
e.span,
|
||||
&format!("literal out of range for `{:?}`", t));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
|
||||
match e.node {
|
||||
|
|
@ -73,118 +415,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
|
|||
"comparison is useless due to type limits");
|
||||
}
|
||||
}
|
||||
hir::ExprKind::Lit(ref lit) => {
|
||||
match cx.tables.node_type(e.hir_id).sty {
|
||||
ty::Int(t) => {
|
||||
match lit.node {
|
||||
ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
|
||||
ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => {
|
||||
let int_type = if let ast::IntTy::Isize = t {
|
||||
cx.sess().target.isize_ty
|
||||
} else {
|
||||
t
|
||||
};
|
||||
let (_, max) = int_ty_range(int_type);
|
||||
let max = max as u128;
|
||||
let negative = self.negated_expr_id == e.hir_id;
|
||||
|
||||
// Detect literal value out of range [min, max] inclusive
|
||||
// avoiding use of -min to prevent overflow/panic
|
||||
if (negative && v > max + 1) || (!negative && v > max) {
|
||||
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
|
||||
report_bin_hex_error(
|
||||
cx,
|
||||
e,
|
||||
attr::IntType::SignedInt(t),
|
||||
repr_str,
|
||||
v,
|
||||
negative,
|
||||
);
|
||||
return;
|
||||
}
|
||||
cx.span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
e.span,
|
||||
&format!("literal out of range for {:?}", t),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => bug!(),
|
||||
};
|
||||
}
|
||||
ty::Uint(t) => {
|
||||
let uint_type = if let ast::UintTy::Usize = t {
|
||||
cx.sess().target.usize_ty
|
||||
} else {
|
||||
t
|
||||
};
|
||||
let (min, max) = uint_ty_range(uint_type);
|
||||
let lit_val: u128 = match lit.node {
|
||||
// _v is u8, within range by definition
|
||||
ast::LitKind::Byte(_v) => return,
|
||||
ast::LitKind::Int(v, _) => v,
|
||||
_ => bug!(),
|
||||
};
|
||||
if lit_val < min || lit_val > max {
|
||||
let parent_id = cx.tcx.hir().get_parent_node_by_hir_id(e.hir_id);
|
||||
if let Node::Expr(parent_expr) = cx.tcx.hir().get_by_hir_id(parent_id) {
|
||||
if let hir::ExprKind::Cast(..) = parent_expr.node {
|
||||
if let ty::Char = cx.tables.expr_ty(parent_expr).sty {
|
||||
let mut err = cx.struct_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
parent_expr.span,
|
||||
"only u8 can be cast into char");
|
||||
err.span_suggestion(
|
||||
parent_expr.span,
|
||||
&"use a char literal instead",
|
||||
format!("'\\u{{{:X}}}'", lit_val),
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
err.emit();
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
|
||||
report_bin_hex_error(
|
||||
cx,
|
||||
e,
|
||||
attr::IntType::UnsignedInt(t),
|
||||
repr_str,
|
||||
lit_val,
|
||||
false,
|
||||
);
|
||||
return;
|
||||
}
|
||||
cx.span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
e.span,
|
||||
&format!("literal out of range for {:?}", t),
|
||||
);
|
||||
}
|
||||
}
|
||||
ty::Float(t) => {
|
||||
let is_infinite = match lit.node {
|
||||
ast::LitKind::Float(v, _) |
|
||||
ast::LitKind::FloatUnsuffixed(v) => {
|
||||
match t {
|
||||
ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
|
||||
ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
|
||||
}
|
||||
}
|
||||
_ => bug!(),
|
||||
};
|
||||
if is_infinite == Ok(true) {
|
||||
cx.span_lint(OVERFLOWING_LITERALS,
|
||||
e.span,
|
||||
&format!("literal out of range for {:?}", t));
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
}
|
||||
_ => (),
|
||||
hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
fn is_valid<T: cmp::PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool {
|
||||
|
|
@ -209,30 +441,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
|
|||
})
|
||||
}
|
||||
|
||||
// for isize & usize, be conservative with the warnings, so that the
|
||||
// warnings are consistent between 32- and 64-bit platforms
|
||||
fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) {
|
||||
match int_ty {
|
||||
ast::IntTy::Isize => (i64::min_value() as i128, i64::max_value() as i128),
|
||||
ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128),
|
||||
ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128),
|
||||
ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128),
|
||||
ast::IntTy::I64 => (i64::min_value() as i128, i64::max_value() as i128),
|
||||
ast::IntTy::I128 =>(i128::min_value() as i128, i128::max_value()),
|
||||
}
|
||||
}
|
||||
|
||||
fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
|
||||
match uint_ty {
|
||||
ast::UintTy::Usize => (u64::min_value() as u128, u64::max_value() as u128),
|
||||
ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128),
|
||||
ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128),
|
||||
ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128),
|
||||
ast::UintTy::U64 => (u64::min_value() as u128, u64::max_value() as u128),
|
||||
ast::UintTy::U128 => (u128::min_value(), u128::max_value()),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_limits(cx: &LateContext<'_, '_>,
|
||||
binop: hir::BinOp,
|
||||
l: &hir::Expr,
|
||||
|
|
@ -289,119 +497,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &ast::Lit) -> Option<String> {
|
||||
let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?;
|
||||
let firstch = src.chars().next()?;
|
||||
|
||||
if firstch == '0' {
|
||||
match src.chars().nth(1) {
|
||||
Some('x') | Some('b') => return Some(src),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// This function finds the next fitting type and generates a suggestion string.
|
||||
// It searches for fitting types in the following way (`X < Y`):
|
||||
// - `iX`: if literal fits in `uX` => `uX`, else => `iY`
|
||||
// - `-iX` => `iY`
|
||||
// - `uX` => `uY`
|
||||
//
|
||||
// No suggestion for: `isize`, `usize`.
|
||||
fn get_type_suggestion<'a>(
|
||||
t: Ty<'_>,
|
||||
val: u128,
|
||||
negative: bool,
|
||||
) -> Option<String> {
|
||||
use syntax::ast::IntTy::*;
|
||||
use syntax::ast::UintTy::*;
|
||||
macro_rules! find_fit {
|
||||
($ty:expr, $val:expr, $negative:expr,
|
||||
$($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => {
|
||||
{
|
||||
let _neg = if negative { 1 } else { 0 };
|
||||
match $ty {
|
||||
$($type => {
|
||||
$(if !negative && val <= uint_ty_range($utypes).1 {
|
||||
return Some(format!("{:?}", $utypes))
|
||||
})*
|
||||
$(if val <= int_ty_range($itypes).1 as u128 + _neg {
|
||||
return Some(format!("{:?}", $itypes))
|
||||
})*
|
||||
None
|
||||
},)*
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
match t.sty {
|
||||
ty::Int(i) => find_fit!(i, val, negative,
|
||||
I8 => [U8] => [I16, I32, I64, I128],
|
||||
I16 => [U16] => [I32, I64, I128],
|
||||
I32 => [U32] => [I64, I128],
|
||||
I64 => [U64] => [I128],
|
||||
I128 => [U128] => []),
|
||||
ty::Uint(u) => find_fit!(u, val, negative,
|
||||
U8 => [U8, U16, U32, U64, U128] => [],
|
||||
U16 => [U16, U32, U64, U128] => [],
|
||||
U32 => [U32, U64, U128] => [],
|
||||
U64 => [U64, U128] => [],
|
||||
U128 => [U128] => []),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn report_bin_hex_error(
|
||||
cx: &LateContext<'_, '_>,
|
||||
expr: &hir::Expr,
|
||||
ty: attr::IntType,
|
||||
repr_str: String,
|
||||
val: u128,
|
||||
negative: bool,
|
||||
) {
|
||||
let size = layout::Integer::from_attr(&cx.tcx, ty).size();
|
||||
let (t, actually) = match ty {
|
||||
attr::IntType::SignedInt(t) => {
|
||||
let actually = sign_extend(val, size) as i128;
|
||||
(format!("{:?}", t), actually.to_string())
|
||||
}
|
||||
attr::IntType::UnsignedInt(t) => {
|
||||
let actually = truncate(val, size);
|
||||
(format!("{:?}", t), actually.to_string())
|
||||
}
|
||||
};
|
||||
let mut err = cx.struct_span_lint(
|
||||
OVERFLOWING_LITERALS,
|
||||
expr.span,
|
||||
&format!("literal out of range for {}", t),
|
||||
);
|
||||
err.note(&format!(
|
||||
"the literal `{}` (decimal `{}`) does not fit into \
|
||||
an `{}` and will become `{}{}`",
|
||||
repr_str, val, t, actually, t
|
||||
));
|
||||
if let Some(sugg_ty) =
|
||||
get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative)
|
||||
{
|
||||
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
|
||||
let (sans_suffix, _) = repr_str.split_at(pos);
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
&format!("consider using `{}` instead", sugg_ty),
|
||||
format!("{}{}", sans_suffix, sugg_ty),
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
} else {
|
||||
err.help(&format!("consider using `{}` instead", sugg_ty));
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use syntax_pos::Span;
|
|||
use rustc::hir;
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::Node;
|
||||
use rustc::hir::print;
|
||||
use rustc::hir::{print, lowering::is_range_literal};
|
||||
use rustc::ty::{self, Ty, AssociatedItem};
|
||||
use rustc::ty::adjustment::AllowTwoPhase;
|
||||
use errors::{Applicability, DiagnosticBuilder};
|
||||
|
|
@ -380,7 +380,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
hir::ExprKind::Cast(_, _) |
|
||||
hir::ExprKind::Binary(_, _, _) => true,
|
||||
// parenthesize borrows of range literals (Issue #54505)
|
||||
_ if self.is_range_literal(expr) => true,
|
||||
_ if is_range_literal(self.tcx.sess, expr) => true,
|
||||
_ => false,
|
||||
};
|
||||
let sugg_expr = if needs_parens {
|
||||
|
|
@ -479,70 +479,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
None
|
||||
}
|
||||
|
||||
/// This function checks if the specified expression is a built-in range literal.
|
||||
/// (See: `LoweringContext::lower_expr()` in `src/librustc/hir/lowering.rs`).
|
||||
fn is_range_literal(&self, expr: &hir::Expr) -> bool {
|
||||
use hir::{Path, QPath, ExprKind, TyKind};
|
||||
|
||||
// We support `::std::ops::Range` and `::core::ops::Range` prefixes
|
||||
let is_range_path = |path: &Path| {
|
||||
let mut segs = path.segments.iter()
|
||||
.map(|seg| seg.ident.as_str());
|
||||
|
||||
if let (Some(root), Some(std_core), Some(ops), Some(range), None) =
|
||||
(segs.next(), segs.next(), segs.next(), segs.next(), segs.next())
|
||||
{
|
||||
// "{{root}}" is the equivalent of `::` prefix in Path
|
||||
root == "{{root}}" && (std_core == "std" || std_core == "core")
|
||||
&& ops == "ops" && range.starts_with("Range")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
let span_is_range_literal = |span: &Span| {
|
||||
// Check whether a span corresponding to a range expression
|
||||
// is a range literal, rather than an explicit struct or `new()` call.
|
||||
let source_map = self.tcx.sess.source_map();
|
||||
let end_point = source_map.end_point(*span);
|
||||
|
||||
if let Ok(end_string) = source_map.span_to_snippet(end_point) {
|
||||
!(end_string.ends_with("}") || end_string.ends_with(")"))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
match expr.node {
|
||||
// All built-in range literals but `..=` and `..` desugar to Structs
|
||||
ExprKind::Struct(ref qpath, _, _) => {
|
||||
if let QPath::Resolved(None, ref path) = **qpath {
|
||||
return is_range_path(&path) && span_is_range_literal(&expr.span);
|
||||
}
|
||||
}
|
||||
// `..` desugars to its struct path
|
||||
ExprKind::Path(QPath::Resolved(None, ref path)) => {
|
||||
return is_range_path(&path) && span_is_range_literal(&expr.span);
|
||||
}
|
||||
|
||||
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`
|
||||
ExprKind::Call(ref func, _) => {
|
||||
if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node {
|
||||
if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node {
|
||||
let call_to_new = segment.ident.as_str() == "new";
|
||||
|
||||
return is_range_path(&path) && span_is_range_literal(&expr.span)
|
||||
&& call_to_new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn check_for_cast(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'tcx>,
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
fn main() {
|
||||
const XYZ: char = 0x1F888 as char;
|
||||
//~^ ERROR only u8 can be cast into char
|
||||
//~^ ERROR only `u8` can be cast into `char`
|
||||
const XY: char = 129160 as char;
|
||||
//~^ ERROR only u8 can be cast into char
|
||||
//~^ ERROR only `u8` can be cast into `char`
|
||||
const ZYX: char = '\u{01F888}';
|
||||
println!("{}", XYZ);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error: only u8 can be cast into char
|
||||
error: only `u8` can be cast into `char`
|
||||
--> $DIR/cast_char.rs:4:23
|
||||
|
|
||||
LL | const XYZ: char = 0x1F888 as char;
|
||||
| ^^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'`
|
||||
| ^^^^^^^^^^^^^^^ help: use a `char` literal instead: `'\u{1F888}'`
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/cast_char.rs:1:9
|
||||
|
|
@ -10,11 +10,11 @@ note: lint level defined here
|
|||
LL | #![deny(overflowing_literals)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: only u8 can be cast into char
|
||||
error: only `u8` can be cast into `char`
|
||||
--> $DIR/cast_char.rs:6:22
|
||||
|
|
||||
LL | const XY: char = 129160 as char;
|
||||
| ^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'`
|
||||
| ^^^^^^^^^^^^^^ help: use a `char` literal instead: `'\u{1F888}'`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -5,28 +5,28 @@
|
|||
enum Ei8 {
|
||||
Ai8 = 23,
|
||||
Bi8 = -23,
|
||||
Ci8 = 223, //~ ERROR literal out of range for i8
|
||||
Ci8 = 223, //~ ERROR literal out of range for `i8`
|
||||
}
|
||||
|
||||
#[repr(i16)]
|
||||
enum Ei16 {
|
||||
Ai16 = 23,
|
||||
Bi16 = -22333,
|
||||
Ci16 = 55555, //~ ERROR literal out of range for i16
|
||||
Ci16 = 55555, //~ ERROR literal out of range for `i16`
|
||||
}
|
||||
|
||||
#[repr(i32)]
|
||||
enum Ei32 {
|
||||
Ai32 = 23,
|
||||
Bi32 = -2_000_000_000,
|
||||
Ci32 = 3_000_000_000, //~ ERROR literal out of range for i32
|
||||
Ci32 = 3_000_000_000, //~ ERROR literal out of range for `i32`
|
||||
}
|
||||
|
||||
#[repr(i64)]
|
||||
enum Ei64 {
|
||||
Ai64 = 23,
|
||||
Bi64 = -9223372036854775808,
|
||||
Ci64 = 9223372036854775809, //~ ERROR literal out of range for i64
|
||||
Ci64 = 9223372036854775809, //~ ERROR literal out of range for `i64`
|
||||
}
|
||||
|
||||
// u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`. This is a
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: literal out of range for i8
|
||||
error: literal out of range for `i8`
|
||||
--> $DIR/enum-discrim-too-small2.rs:8:11
|
||||
|
|
||||
LL | Ci8 = 223,
|
||||
|
|
@ -10,19 +10,19 @@ note: lint level defined here
|
|||
LL | #![deny(overflowing_literals)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i16
|
||||
error: literal out of range for `i16`
|
||||
--> $DIR/enum-discrim-too-small2.rs:15:12
|
||||
|
|
||||
LL | Ci16 = 55555,
|
||||
| ^^^^^
|
||||
|
||||
error: literal out of range for i32
|
||||
error: literal out of range for `i32`
|
||||
--> $DIR/enum-discrim-too-small2.rs:22:12
|
||||
|
|
||||
LL | Ci32 = 3_000_000_000,
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i64
|
||||
error: literal out of range for `i64`
|
||||
--> $DIR/enum-discrim-too-small2.rs:29:12
|
||||
|
|
||||
LL | Ci64 = 9223372036854775809,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
fn main() {
|
||||
let x: u8 = 256;
|
||||
//~^ error: literal out of range for u8
|
||||
//~^ error: literal out of range for `u8`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: literal out of range for u8
|
||||
error: literal out of range for `u8`
|
||||
--> $DIR/deny-overflowing-literals.rs:2:17
|
||||
|
|
||||
LL | let x: u8 = 256;
|
||||
|
|
|
|||
17
src/test/ui/lint/lint-range-endpoint-overflow.rs
Normal file
17
src/test/ui/lint/lint-range-endpoint-overflow.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#![deny(overflowing_literals)]
|
||||
|
||||
fn main() {
|
||||
let range_a = 0..256; //~ ERROR range endpoint is out of range for `u8`
|
||||
let range_b = 0..=255; // ok
|
||||
let range_c = 0..=256; //~ ERROR literal out of range for `u8`
|
||||
let range_d = 256..5; //~ ERROR literal out of range for `u8`
|
||||
let range_e = 0..257; //~ ERROR literal out of range for `u8`
|
||||
let _range_f = 0..256u8; //~ ERROR range endpoint is out of range for `u8`
|
||||
let _range_g = 0..128i8; //~ ERROR range endpoint is out of range for `i8`
|
||||
|
||||
range_a.collect::<Vec<u8>>();
|
||||
range_b.collect::<Vec<u8>>();
|
||||
range_c.collect::<Vec<u8>>();
|
||||
range_d.collect::<Vec<u8>>();
|
||||
range_e.collect::<Vec<u8>>();
|
||||
}
|
||||
44
src/test/ui/lint/lint-range-endpoint-overflow.stderr
Normal file
44
src/test/ui/lint/lint-range-endpoint-overflow.stderr
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
error: range endpoint is out of range for `u8`
|
||||
--> $DIR/lint-range-endpoint-overflow.rs:4:19
|
||||
|
|
||||
LL | let range_a = 0..256;
|
||||
| ^^^^^^ help: use an inclusive range instead: `0..=255`
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/lint-range-endpoint-overflow.rs:1:9
|
||||
|
|
||||
LL | #![deny(overflowing_literals)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for `u8`
|
||||
--> $DIR/lint-range-endpoint-overflow.rs:6:23
|
||||
|
|
||||
LL | let range_c = 0..=256;
|
||||
| ^^^
|
||||
|
||||
error: literal out of range for `u8`
|
||||
--> $DIR/lint-range-endpoint-overflow.rs:7:19
|
||||
|
|
||||
LL | let range_d = 256..5;
|
||||
| ^^^
|
||||
|
||||
error: literal out of range for `u8`
|
||||
--> $DIR/lint-range-endpoint-overflow.rs:8:22
|
||||
|
|
||||
LL | let range_e = 0..257;
|
||||
| ^^^
|
||||
|
||||
error: range endpoint is out of range for `u8`
|
||||
--> $DIR/lint-range-endpoint-overflow.rs:9:20
|
||||
|
|
||||
LL | let _range_f = 0..256u8;
|
||||
| ^^^^^^^^ help: use an inclusive range instead: `0..=255u8`
|
||||
|
||||
error: range endpoint is out of range for `i8`
|
||||
--> $DIR/lint-range-endpoint-overflow.rs:10:20
|
||||
|
|
||||
LL | let _range_g = 0..128i8;
|
||||
| ^^^^^^^^ help: use an inclusive range instead: `0..=127i8`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
@ -11,5 +11,5 @@ fn bar() -> i8 {
|
|||
|
||||
fn baz() -> bool {
|
||||
128 > bar() //~ ERROR comparison is useless due to type limits
|
||||
//~| WARN literal out of range for i8
|
||||
//~| WARN literal out of range for `i8`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ LL | 128 > bar()
|
|||
|
|
||||
= note: requested on the command line with `-D unused-comparisons`
|
||||
|
||||
warning: literal out of range for i8
|
||||
warning: literal out of range for `i8`
|
||||
--> $DIR/lint-type-limits2.rs:13:5
|
||||
|
|
||||
LL | 128 > bar()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ fn main() { }
|
|||
fn qux() {
|
||||
let mut i = 1i8;
|
||||
while 200 != i { //~ ERROR comparison is useless due to type limits
|
||||
//~| WARN literal out of range for i8
|
||||
//~| WARN literal out of range for `i8`
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ LL | while 200 != i {
|
|||
|
|
||||
= note: requested on the command line with `-D unused-comparisons`
|
||||
|
||||
warning: literal out of range for i8
|
||||
warning: literal out of range for `i8`
|
||||
--> $DIR/lint-type-limits3.rs:9:11
|
||||
|
|
||||
LL | while 200 != i {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
//
|
||||
|
||||
#![deny(overflowing_literals)]
|
||||
|
||||
fn test(x: i8) {
|
||||
|
|
@ -9,39 +7,39 @@ fn test(x: i8) {
|
|||
#[allow(unused_variables)]
|
||||
fn main() {
|
||||
let x1: u8 = 255; // should be OK
|
||||
let x1: u8 = 256; //~ error: literal out of range for u8
|
||||
let x1: u8 = 256; //~ error: literal out of range for `u8`
|
||||
|
||||
let x1 = 255_u8; // should be OK
|
||||
let x1 = 256_u8; //~ error: literal out of range for u8
|
||||
let x1 = 256_u8; //~ error: literal out of range for `u8`
|
||||
|
||||
let x2: i8 = -128; // should be OK
|
||||
let x1: i8 = 128; //~ error: literal out of range for i8
|
||||
let x1: i8 = 128; //~ error: literal out of range for `i8`
|
||||
|
||||
let x3: i8 = -129; //~ error: literal out of range for i8
|
||||
let x3: i8 = -(129); //~ error: literal out of range for i8
|
||||
let x3: i8 = -{129}; //~ error: literal out of range for i8
|
||||
let x3: i8 = -129; //~ error: literal out of range for `i8`
|
||||
let x3: i8 = -(129); //~ error: literal out of range for `i8`
|
||||
let x3: i8 = -{129}; //~ error: literal out of range for `i8`
|
||||
|
||||
test(1000); //~ error: literal out of range for i8
|
||||
test(1000); //~ error: literal out of range for `i8`
|
||||
|
||||
let x = 128_i8; //~ error: literal out of range for i8
|
||||
let x = 128_i8; //~ error: literal out of range for `i8`
|
||||
let x = 127_i8;
|
||||
let x = -128_i8;
|
||||
let x = -(128_i8);
|
||||
let x = -129_i8; //~ error: literal out of range for i8
|
||||
let x = -129_i8; //~ error: literal out of range for `i8`
|
||||
|
||||
let x: i32 = 2147483647; // should be OK
|
||||
let x = 2147483647_i32; // should be OK
|
||||
let x: i32 = 2147483648; //~ error: literal out of range for i32
|
||||
let x = 2147483648_i32; //~ error: literal out of range for i32
|
||||
let x: i32 = 2147483648; //~ error: literal out of range for `i32`
|
||||
let x = 2147483648_i32; //~ error: literal out of range for `i32`
|
||||
let x: i32 = -2147483648; // should be OK
|
||||
let x = -2147483648_i32; // should be OK
|
||||
let x: i32 = -2147483649; //~ error: literal out of range for i32
|
||||
let x = -2147483649_i32; //~ error: literal out of range for i32
|
||||
let x = 2147483648; //~ error: literal out of range for i32
|
||||
let x: i32 = -2147483649; //~ error: literal out of range for `i32`
|
||||
let x = -2147483649_i32; //~ error: literal out of range for `i32`
|
||||
let x = 2147483648; //~ error: literal out of range for `i32`
|
||||
|
||||
let x = 9223372036854775808_i64; //~ error: literal out of range for i64
|
||||
let x = 9223372036854775808_i64; //~ error: literal out of range for `i64`
|
||||
let x = -9223372036854775808_i64; // should be OK
|
||||
let x = 18446744073709551615_i64; //~ error: literal out of range for i64
|
||||
let x: i64 = -9223372036854775809; //~ error: literal out of range for i64
|
||||
let x = -9223372036854775809_i64; //~ error: literal out of range for i64
|
||||
let x = 18446744073709551615_i64; //~ error: literal out of range for `i64`
|
||||
let x: i64 = -9223372036854775809; //~ error: literal out of range for `i64`
|
||||
let x = -9223372036854775809_i64; //~ error: literal out of range for `i64`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,113 +1,113 @@
|
|||
error: literal out of range for u8
|
||||
--> $DIR/lint-type-overflow.rs:12:18
|
||||
error: literal out of range for `u8`
|
||||
--> $DIR/lint-type-overflow.rs:10:18
|
||||
|
|
||||
LL | let x1: u8 = 256;
|
||||
| ^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/lint-type-overflow.rs:3:9
|
||||
--> $DIR/lint-type-overflow.rs:1:9
|
||||
|
|
||||
LL | #![deny(overflowing_literals)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for u8
|
||||
--> $DIR/lint-type-overflow.rs:15:14
|
||||
error: literal out of range for `u8`
|
||||
--> $DIR/lint-type-overflow.rs:13:14
|
||||
|
|
||||
LL | let x1 = 256_u8;
|
||||
| ^^^^^^
|
||||
|
||||
error: literal out of range for i8
|
||||
--> $DIR/lint-type-overflow.rs:18:18
|
||||
error: literal out of range for `i8`
|
||||
--> $DIR/lint-type-overflow.rs:16:18
|
||||
|
|
||||
LL | let x1: i8 = 128;
|
||||
| ^^^
|
||||
|
||||
error: literal out of range for i8
|
||||
--> $DIR/lint-type-overflow.rs:20:19
|
||||
error: literal out of range for `i8`
|
||||
--> $DIR/lint-type-overflow.rs:18:19
|
||||
|
|
||||
LL | let x3: i8 = -129;
|
||||
| ^^^
|
||||
|
||||
error: literal out of range for i8
|
||||
--> $DIR/lint-type-overflow.rs:21:19
|
||||
error: literal out of range for `i8`
|
||||
--> $DIR/lint-type-overflow.rs:19:19
|
||||
|
|
||||
LL | let x3: i8 = -(129);
|
||||
| ^^^^^
|
||||
|
||||
error: literal out of range for i8
|
||||
--> $DIR/lint-type-overflow.rs:22:20
|
||||
error: literal out of range for `i8`
|
||||
--> $DIR/lint-type-overflow.rs:20:20
|
||||
|
|
||||
LL | let x3: i8 = -{129};
|
||||
| ^^^
|
||||
|
||||
error: literal out of range for i8
|
||||
--> $DIR/lint-type-overflow.rs:24:10
|
||||
error: literal out of range for `i8`
|
||||
--> $DIR/lint-type-overflow.rs:22:10
|
||||
|
|
||||
LL | test(1000);
|
||||
| ^^^^
|
||||
|
||||
error: literal out of range for i8
|
||||
--> $DIR/lint-type-overflow.rs:26:13
|
||||
error: literal out of range for `i8`
|
||||
--> $DIR/lint-type-overflow.rs:24:13
|
||||
|
|
||||
LL | let x = 128_i8;
|
||||
| ^^^^^^
|
||||
|
||||
error: literal out of range for i8
|
||||
--> $DIR/lint-type-overflow.rs:30:14
|
||||
error: literal out of range for `i8`
|
||||
--> $DIR/lint-type-overflow.rs:28:14
|
||||
|
|
||||
LL | let x = -129_i8;
|
||||
| ^^^^^^
|
||||
|
||||
error: literal out of range for i32
|
||||
--> $DIR/lint-type-overflow.rs:34:18
|
||||
error: literal out of range for `i32`
|
||||
--> $DIR/lint-type-overflow.rs:32:18
|
||||
|
|
||||
LL | let x: i32 = 2147483648;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i32
|
||||
--> $DIR/lint-type-overflow.rs:35:13
|
||||
error: literal out of range for `i32`
|
||||
--> $DIR/lint-type-overflow.rs:33:13
|
||||
|
|
||||
LL | let x = 2147483648_i32;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i32
|
||||
--> $DIR/lint-type-overflow.rs:38:19
|
||||
error: literal out of range for `i32`
|
||||
--> $DIR/lint-type-overflow.rs:36:19
|
||||
|
|
||||
LL | let x: i32 = -2147483649;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i32
|
||||
--> $DIR/lint-type-overflow.rs:39:14
|
||||
error: literal out of range for `i32`
|
||||
--> $DIR/lint-type-overflow.rs:37:14
|
||||
|
|
||||
LL | let x = -2147483649_i32;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i32
|
||||
--> $DIR/lint-type-overflow.rs:40:13
|
||||
error: literal out of range for `i32`
|
||||
--> $DIR/lint-type-overflow.rs:38:13
|
||||
|
|
||||
LL | let x = 2147483648;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i64
|
||||
--> $DIR/lint-type-overflow.rs:42:13
|
||||
error: literal out of range for `i64`
|
||||
--> $DIR/lint-type-overflow.rs:40:13
|
||||
|
|
||||
LL | let x = 9223372036854775808_i64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i64
|
||||
--> $DIR/lint-type-overflow.rs:44:13
|
||||
error: literal out of range for `i64`
|
||||
--> $DIR/lint-type-overflow.rs:42:13
|
||||
|
|
||||
LL | let x = 18446744073709551615_i64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i64
|
||||
--> $DIR/lint-type-overflow.rs:45:19
|
||||
error: literal out of range for `i64`
|
||||
--> $DIR/lint-type-overflow.rs:43:19
|
||||
|
|
||||
LL | let x: i64 = -9223372036854775809;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: literal out of range for i64
|
||||
--> $DIR/lint-type-overflow.rs:46:14
|
||||
error: literal out of range for `i64`
|
||||
--> $DIR/lint-type-overflow.rs:44:14
|
||||
|
|
||||
LL | let x = -9223372036854775809_i64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
warning: literal out of range for i8
|
||||
warning: literal out of range for `i8`
|
||||
--> $DIR/lint-type-overflow2.rs:9:20
|
||||
|
|
||||
LL | let x2: i8 = --128;
|
||||
|
|
@ -10,25 +10,25 @@ note: lint level defined here
|
|||
LL | #![warn(overflowing_literals)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: literal out of range for f32
|
||||
warning: literal out of range for `f32`
|
||||
--> $DIR/lint-type-overflow2.rs:11:14
|
||||
|
|
||||
LL | let x = -3.40282357e+38_f32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: literal out of range for f32
|
||||
warning: literal out of range for `f32`
|
||||
--> $DIR/lint-type-overflow2.rs:12:14
|
||||
|
|
||||
LL | let x = 3.40282357e+38_f32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: literal out of range for f64
|
||||
warning: literal out of range for `f64`
|
||||
--> $DIR/lint-type-overflow2.rs:13:14
|
||||
|
|
||||
LL | let x = -1.7976931348623159e+308_f64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: literal out of range for f64
|
||||
warning: literal out of range for `f64`
|
||||
--> $DIR/lint-type-overflow2.rs:14:14
|
||||
|
|
||||
LL | let x = 1.7976931348623159e+308_f64;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
warning: literal out of range for i8
|
||||
warning: literal out of range for `i8`
|
||||
--> $DIR/type-overflow.rs:5:17
|
||||
|
|
||||
LL | let error = 255i8;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue