diff --git a/src/libnative/io/timer_win32.rs b/src/libnative/io/timer_win32.rs index 588ec367d8176..15e6e62421a5b 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 56284984a243c..7f083865d141b 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 c15eb3a9774f9..57fc8f150215a 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 03fc85126a476..2791e79907fe1 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 9000d2c87378b..2032a2a6b58bd 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 36e5728200bcb..672de0bf9e579 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 ca473e9517e45..14a432905b401 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 2a0b9aac667af..87740dcb1355b 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 2cfc5da95e8ba..15b2528e61609 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 30ed13a5952b4..f841a31ee1358 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 6751fdb5d252c..46cb4f448877d 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 8acedb080c2c7..fac8736b92936 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 2d952b2a9db17..9f5986e3dc6b2 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 8cca39a7a257e..1aaf68d7c1ad1 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 +}