Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ pub trait Visitor<'v>: Sized {
fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
walk_pat_expr(self, expr)
}
fn visit_lit(&mut self, _hir_id: HirId, _lit: Lit, _negated: bool) -> Self::Result {
fn visit_lit(&mut self, _hir_id: HirId, _lit: Lit, _is_negated_pat: bool) -> Self::Result {
Self::Result::output()
}
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
hir_visit::walk_pat(self, p);
}

fn visit_lit(&mut self, hir_id: HirId, lit: hir::Lit, negated: bool) {
lint_callback!(self, check_lit, hir_id, lit, negated);
fn visit_lit(&mut self, hir_id: HirId, lit: hir::Lit, is_negated_pat: bool) {
lint_callback!(self, check_lit, hir_id, lit, is_negated_pat);
}

fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ macro_rules! late_lint_methods {
fn check_stmt(a: &'tcx rustc_hir::Stmt<'tcx>);
fn check_arm(a: &'tcx rustc_hir::Arm<'tcx>);
fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>);
fn check_lit(hir_id: rustc_hir::HirId, a: rustc_hir::Lit, negated: bool);
fn check_lit(hir_id: rustc_hir::HirId, a: rustc_hir::Lit, is_negated_pat: bool);
fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>);
fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>);
fn check_ty(a: &'tcx rustc_hir::Ty<'tcx, rustc_hir::AmbigArg>);
Expand Down
47 changes: 31 additions & 16 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,15 @@ declare_lint! {

#[derive(Copy, Clone, Default)]
pub(crate) struct TypeLimits {
/// Id of the last visited negated expression
negated_expr_id: Option<hir::HirId>,
/// Span of the last visited negated expression
negated_expr_span: Option<Span>,
last_visited_negation: Option<NegationInfo>,
}

#[derive(Copy, Clone)]
struct NegationInfo {
/// A negation expression (a `rustc_hir::ExprKind::Unary`)
negation_span: Span,
/// The operand of the negation expression.
negated_id: hir::HirId,
}

impl_lint_pass!(TypeLimits => [
Expand All @@ -210,7 +215,7 @@ impl_lint_pass!(TypeLimits => [

impl TypeLimits {
pub(crate) fn new() -> TypeLimits {
TypeLimits { negated_expr_id: None, negated_expr_span: None }
TypeLimits { last_visited_negation: None }
}
}

Expand Down Expand Up @@ -539,22 +544,32 @@ fn lint_fn_pointer<'tcx>(
}

impl<'tcx> LateLintPass<'tcx> for TypeLimits {
fn check_lit(&mut self, cx: &LateContext<'tcx>, hir_id: HirId, lit: hir::Lit, negated: bool) {
if negated {
self.negated_expr_id = Some(hir_id);
self.negated_expr_span = Some(lit.span);
}
lint_literal(cx, self, hir_id, lit.span, &lit, negated);
fn check_lit(
&mut self,
cx: &LateContext<'tcx>,
hir_id: HirId,
lit: hir::Lit,
is_negated_pat: bool,
) {
let surrounding_negation = if is_negated_pat {
// In this case, lit.span refers to a `rustc_hir::hir::PatExprKind::Lit`,
// which includes the minus sign in front.
Some(lit.span)
} else if let Some(negation_info) = self.last_visited_negation
&& negation_info.negated_id == hir_id
{
Some(negation_info.negation_span)
} else {
None
};
lint_literal(cx, hir_id, lit.span, &lit, surrounding_negation);
}

fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
match e.kind {
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
// Propagate negation, if the negation itself isn't negated
if self.negated_expr_id != Some(e.hir_id) {
self.negated_expr_id = Some(expr.hir_id);
self.negated_expr_span = Some(e.span);
}
self.last_visited_negation =
Some(NegationInfo { negation_span: e.span, negated_id: expr.hir_id });
}
hir::ExprKind::Binary(binop, ref l, ref r) => {
if is_comparison(binop.node) {
Expand Down
15 changes: 7 additions & 8 deletions compiler/rustc_lint/src/types/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::lints::{
OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
RangeEndpointOutOfRange, SurrogateCharCast, TooLargeCharCast, UseInclusiveRange,
};
use crate::types::{OVERFLOWING_LITERALS, TypeLimits};
use crate::types::OVERFLOWING_LITERALS;

/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint (`expr..MAX+1`).
/// Returns `true` iff the lint was emitted.
Expand Down Expand Up @@ -260,17 +260,17 @@ fn literal_to_i128(val: u128, negative: bool) -> Option<i128> {

fn lint_int_literal<'tcx>(
cx: &LateContext<'tcx>,
type_limits: &TypeLimits,
hir_id: HirId,
span: Span,
lit: &hir::Lit,
t: ty::IntTy,
v: u128,
surrounding_negation: Option<Span>,
) {
let int_type = t.normalize(cx.sess().target.pointer_width);
let (min, max) = int_ty_range(int_type);
let max = max as u128;
let negative = type_limits.negated_expr_id == Some(hir_id);
let negative = surrounding_negation.is_some();

// Detect literal value out of range [min, max] inclusive
// avoiding use of -min to prevent overflow/panic
Expand All @@ -294,7 +294,7 @@ fn lint_int_literal<'tcx>(
return;
}

let span = if negative { type_limits.negated_expr_span.unwrap() } else { span };
let span = surrounding_negation.unwrap_or(span);
let lit = cx
.sess()
.source_map()
Expand Down Expand Up @@ -400,23 +400,22 @@ fn float_is_infinite<S: Semantics>(v: Symbol) -> Option<bool> {

pub(crate) fn lint_literal<'tcx>(
cx: &LateContext<'tcx>,
type_limits: &TypeLimits,
hir_id: HirId,
span: Span,
lit: &hir::Lit,
negated: bool,
surrounding_negation: Option<Span>,
) {
match *cx.typeck_results().node_type(hir_id).kind() {
ty::Int(t) => {
match lit.node {
ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => {
lint_int_literal(cx, type_limits, hir_id, span, lit, t, v.get())
lint_int_literal(cx, hir_id, span, lit, t, v.get(), surrounding_negation)
}
_ => bug!(),
};
}
ty::Uint(t) => {
assert!(!negated);
assert!(surrounding_negation.is_none());
lint_uint_literal(cx, hir_id, span, lit, t)
}
ty::Float(t) => {
Expand Down
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/approx_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl ApproxConstant {
}

impl LateLintPass<'_> for ApproxConstant {
fn check_lit(&mut self, cx: &LateContext<'_>, _hir_id: HirId, lit: Lit, _negated: bool) {
fn check_lit(&mut self, cx: &LateContext<'_>, _hir_id: HirId, lit: Lit, _is_negated_pat: bool) {
match lit.node {
LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
FloatTy::F16 => self.check_known_consts(cx, lit.span, s, "f16"),
Expand Down
3 changes: 0 additions & 3 deletions tests/ui/lint/lint-type-overflow2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
#![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`
Expand Down
49 changes: 13 additions & 36 deletions tests/ui/lint/lint-type-overflow2.stderr
Original file line number Diff line number Diff line change
@@ -1,94 +1,71 @@
warning: use of a double negation
--> $DIR/lint-type-overflow2.rs:8:18
|
LL | let x2: i8 = --128;
| ^^^^^
|
= note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
= note: use `-= 1` if you meant to decrement the value
= note: `#[warn(double_negations)]` on by default
help: add parentheses for clarity
|
LL | let x2: i8 = -(-128);
| + +

error: literal out of range for `i8`
--> $DIR/lint-type-overflow2.rs:8:20
error: literal out of range for `f16`
--> $DIR/lint-type-overflow2.rs:8:14
|
LL | let x2: i8 = --128;
| ^^^
LL | let x = -65520.0_f16;
| ^^^^^^^^^^^
|
= 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 literal `65520.0_f16` does not fit into the type `f16` and will be converted to `f16::INFINITY`
note: the lint level is defined here
--> $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
--> $DIR/lint-type-overflow2.rs:9: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:13:14
--> $DIR/lint-type-overflow2.rs:10:14
|
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:14:14
--> $DIR/lint-type-overflow2.rs:11:14
|
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:15:14
--> $DIR/lint-type-overflow2.rs:12: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: literal out of range for `f64`
--> $DIR/lint-type-overflow2.rs:16:14
--> $DIR/lint-type-overflow2.rs:13: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: literal out of range for `f128`
--> $DIR/lint-type-overflow2.rs:17:14
--> $DIR/lint-type-overflow2.rs:14: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
--> $DIR/lint-type-overflow2.rs:15: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
error: aborting due to 8 previous errors

21 changes: 21 additions & 0 deletions tests/ui/lint/lint-type-overflow3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ compile-flags: --emit link
// The above flags (which are passed in `cargo build`) are required for
// the `arithmetic_overflow` lint to function.

#![deny(overflowing_literals, arithmetic_overflow)]

fn main() {
let x: i8 = 128;
//~^ ERROR literal out of range for `i8`
let x: i8 = -128;
let x: i8 = --128; //~ WARN use of a double negation
//~^ ERROR this arithmetic operation will overflow
let x: i8 = ---128; //~ WARN use of a double negation
//~^ ERROR this arithmetic operation will overflow
let x: i8 = ----128; //~ WARN use of a double negation
//~^ ERROR this arithmetic operation will overflow
let x: i8 = -----128; //~ WARN use of a double negation
//~^ ERROR this arithmetic operation will overflow
let x: i8 = ------128; //~ WARN use of a double negation
//~^ ERROR this arithmetic operation will overflow
}
Loading
Loading