From 6c26cbb6026194a280fa0f33c794d4397ad426da Mon Sep 17 00:00:00 2001 From: Falco Hirschenberger Date: Sat, 3 May 2014 00:13:26 +0200 Subject: [PATCH] Add lint check for negating uint literals and variables. See #11273 and #13318 --- src/libnative/io/timer_win32.rs | 6 ++--- src/librustc/middle/const_eval.rs | 1 + src/librustc/middle/lint.rs | 31 +++++++++++++++++++++++ src/librustc/middle/trans/adt.rs | 2 ++ src/libstd/fmt/num.rs | 2 ++ src/libstd/num/f32.rs | 1 + src/libstd/num/u16.rs | 1 + src/libstd/num/u32.rs | 1 + src/libstd/num/u64.rs | 1 + src/libstd/num/u8.rs | 1 + src/libstd/num/uint.rs | 1 + src/libstd/num/uint_macros.rs | 1 + src/libstd/rt/thread.rs | 1 + src/test/compile-fail/lint-type-limits.rs | 11 ++++++++ 14 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/libnative/io/timer_win32.rs b/src/libnative/io/timer_win32.rs index 588ec367d81..15e6e62421a 100644 --- a/src/libnative/io/timer_win32.rs +++ b/src/libnative/io/timer_win32.rs @@ -137,7 +137,7 @@ impl rtio::RtioTimer for Timer { // there are 10^6 nanoseconds in a millisecond, and the parameter is in // 100ns intervals, so we multiply by 10^4. - let due = -(msecs * 10000) as libc::LARGE_INTEGER; + let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER; assert_eq!(unsafe { imp::SetWaitableTimer(self.obj, &due, 0, ptr::null(), ptr::mut_null(), 0) @@ -151,7 +151,7 @@ impl rtio::RtioTimer for Timer { let (tx, rx) = channel(); // see above for the calculation - let due = -(msecs * 10000) as libc::LARGE_INTEGER; + let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER; assert_eq!(unsafe { imp::SetWaitableTimer(self.obj, &due, 0, ptr::null(), ptr::mut_null(), 0) @@ -167,7 +167,7 @@ impl rtio::RtioTimer for Timer { let (tx, rx) = channel(); // see above for the calculation - let due = -(msecs * 10000) as libc::LARGE_INTEGER; + let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER; assert_eq!(unsafe { imp::SetWaitableTimer(self.obj, &due, msecs as libc::LONG, ptr::null(), ptr::mut_null(), 0) diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 56284984a24..7f083865d14 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -9,6 +9,7 @@ // except according to those terms. #![allow(non_camel_case_types)] +#![allow(unsigned_negate)] use metadata::csearch; use middle::astencode; diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index c15eb3a9774..57fc8f15021 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -91,6 +91,7 @@ pub enum Lint { AttributeUsage, UnknownFeatures, UnknownCrateType, + UnsignedNegate, ManagedHeapMemory, OwnedHeapMemory, @@ -390,6 +391,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[ default: deny, }), + ("unsigned_negate", + LintSpec { + lint: UnsignedNegate, + desc: "using an unary minus operator on unsigned type", + default: warn + }), + ("unused_must_use", LintSpec { lint: UnusedMustUse, @@ -704,6 +712,29 @@ fn check_unused_casts(cx: &Context, e: &ast::Expr) { fn check_type_limits(cx: &Context, e: &ast::Expr) { return match e.node { + ast::ExprUnary(ast::UnNeg, ex) => { + match ex.node { + ast::ExprLit(lit) => { + match lit.node { + ast::LitUint(..) => { + cx.span_lint(UnsignedNegate, e.span, + "negation of unsigned int literal may be unintentional"); + }, + _ => () + } + }, + _ => { + let t = ty::expr_ty(cx.tcx, ex); + match ty::get(t).sty { + ty::ty_uint(_) => { + cx.span_lint(UnsignedNegate, e.span, + "negation of unsigned int variable may be unintentional"); + }, + _ => () + } + } + } + }, ast::ExprBinary(binop, l, r) => { if is_comparison(binop) && !check_limits(cx.tcx, binop, l, r) { cx.span_lint(TypeLimits, e.span, diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 03fc85126a4..2791e79907f 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -43,6 +43,8 @@ * taken to it, implementing them for Rust seems difficult. */ +#![allow(unsigned_negate)] + use std::container::Map; use libc::c_ulonglong; use std::num::{Bitwise}; diff --git a/src/libstd/fmt/num.rs b/src/libstd/fmt/num.rs index 9000d2c8737..2032a2a6b58 100644 --- a/src/libstd/fmt/num.rs +++ b/src/libstd/fmt/num.rs @@ -12,6 +12,8 @@ // FIXME: #6220 Implement floating point formatting +#![allow(unsigned_negate)] + use container::Container; use fmt; use iter::{Iterator, DoubleEndedIterator}; diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 36e5728200b..672de0bf9e5 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -11,6 +11,7 @@ //! Operations and constants for 32-bits floats (`f32` type) #![allow(missing_doc)] +#![allow(unsigned_negate)] use prelude::*; diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs index ca473e9517e..14a432905b4 100644 --- a/src/libstd/num/u16.rs +++ b/src/libstd/num/u16.rs @@ -11,6 +11,7 @@ //! Operations and constants for unsigned 16-bits integers (`u16` type) #![allow(non_uppercase_statics)] +#![allow(unsigned_negate)] use prelude::*; diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs index 2a0b9aac667..87740dcb135 100644 --- a/src/libstd/num/u32.rs +++ b/src/libstd/num/u32.rs @@ -11,6 +11,7 @@ //! Operations and constants for unsigned 32-bits integers (`u32` type) #![allow(non_uppercase_statics)] +#![allow(unsigned_negate)] use prelude::*; diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs index 2cfc5da95e8..15b2528e616 100644 --- a/src/libstd/num/u64.rs +++ b/src/libstd/num/u64.rs @@ -11,6 +11,7 @@ //! Operations and constants for unsigned 64-bits integer (`u64` type) #![allow(non_uppercase_statics)] +#![allow(unsigned_negate)] use prelude::*; diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs index 30ed13a5952..f841a31ee13 100644 --- a/src/libstd/num/u8.rs +++ b/src/libstd/num/u8.rs @@ -11,6 +11,7 @@ //! Operations and constants for unsigned 8-bits integers (`u8` type) #![allow(non_uppercase_statics)] +#![allow(unsigned_negate)] use prelude::*; diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index 6751fdb5d25..46cb4f44887 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -11,6 +11,7 @@ //! Operations and constants for architecture-sized unsigned integers (`uint` type) #![allow(non_uppercase_statics)] +#![allow(unsigned_negate)] use prelude::*; diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 8acedb080c2..fac8736b929 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -10,6 +10,7 @@ #![macro_escape] #![doc(hidden)] +#![allow(unsigned_negate)] macro_rules! uint_module (($T:ty, $T_SIGNED:ty, $bits:expr) => ( diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs index 2d952b2a9db..9f5986e3dc6 100644 --- a/src/libstd/rt/thread.rs +++ b/src/libstd/rt/thread.rs @@ -15,6 +15,7 @@ //! which are not used for scheduling in any way. #![allow(non_camel_case_types)] +#![allow(unsigned_negate)] use cast; use kinds::Send; diff --git a/src/test/compile-fail/lint-type-limits.rs b/src/test/compile-fail/lint-type-limits.rs index 8cca39a7a25..1aaf68d7c1a 100644 --- a/src/test/compile-fail/lint-type-limits.rs +++ b/src/test/compile-fail/lint-type-limits.rs @@ -36,3 +36,14 @@ fn qux() { i += 1; } } + +fn quy() { + let i = -23u; //~ WARNING negation of unsigned int literal may be unintentional + //~^ WARNING unused variable +} + +fn quz() { + let i = 23u; + let j = -i; //~ WARNING negation of unsigned int variable may be unintentional + //~^ WARNING unused variable +}