]> git.lizzy.rs Git - rust.git/commitdiff
[breaking-change] remove negate_unsigned feature gate
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Mon, 11 Jan 2016 11:31:46 +0000 (12:31 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Mon, 11 Jan 2016 11:31:46 +0000 (12:31 +0100)
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/libsyntax/feature_gate.rs
src/test/compile-fail/const-eval-overflow.rs
src/test/compile-fail/const-eval-overflow0.rs [new file with mode: 0644]
src/test/compile-fail/enum-discrim-too-small.rs
src/test/compile-fail/feature-gate-negate-unsigned.rs
src/test/compile-fail/lint-type-limits.rs
src/test/run-pass/bitwise.rs
src/test/run-pass/intrinsics-integer.rs
src/test/run-pass/unary-minus-suffix-inference.rs

index f2e75960406f188e5e10309212f7c85b3a82053a..a2a5f846f3b510f4856220fe09ecd50eab77feb2 100644 (file)
@@ -38,6 +38,7 @@
 #![feature(staged_api)]
 #![feature(str_char)]
 
+#[macro_use]
 extern crate syntax;
 #[macro_use]
 extern crate rustc;
@@ -153,4 +154,5 @@ macro_rules! add_lint_group {
     store.register_renamed("unknown_features", "unused_features");
 
     store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
+    store.register_removed("negate_unsigned", "cast a signed value instead");
 }
index a1d029025b2fa8c09680dc4ca93f8e7c7462ff77..891c1aebcdf30704afa57221a73bfaf68c4fb7cb 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(non_snake_case)]
+
 use middle::{infer};
 use middle::def_id::DefId;
 use middle::subst::Substs;
 use syntax::{abi, ast};
 use syntax::attr::{self, AttrMetaMethods};
 use syntax::codemap::{self, Span};
-use syntax::feature_gate::{emit_feature_err, GateIssue};
 use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
 
 use rustc_front::hir;
 use rustc_front::intravisit::{self, Visitor};
 use rustc_front::util::is_shift_binop;
 
+register_long_diagnostics! {
+E0519: r##"
+It is not allowed to negate an unsigned integer.
+You can negate a signed integer and cast it to an
+unsigned integer or use the `!` operator.
+
+```
+let x: usize = -1isize as usize;
+let y: usize = !0;
+assert_eq!(x, y);
+```
+
+Alternatively you can use the `Wrapping` newtype
+or the `wrapping_neg` operation that all
+integral types support:
+
+```
+use std::num::Wrapping;
+let x: Wrapping<usize> = -Wrapping(1);
+let Wrapping(x) = x;
+let y: usize = 1.wrapping_neg();
+assert_eq!(x, y);
+```
+
+"##
+}
+
 declare_lint! {
     UNUSED_COMPARISONS,
     Warn,
@@ -73,30 +101,24 @@ impl LateLintPass for TypeLimits {
     fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
         match e.node {
             hir::ExprUnary(hir::UnNeg, ref expr) => {
-                match expr.node  {
-                    hir::ExprLit(ref lit) => {
-                        match lit.node {
-                            ast::LitInt(_, ast::UnsignedIntLit(_)) => {
-                                check_unsigned_negation_feature(cx, e.span);
-                            },
-                            ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
-                                if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty {
-                                    check_unsigned_negation_feature(cx, e.span);
-                                }
-                            },
-                            _ => ()
-                        }
-                    },
-                    _ => {
-                        let t = cx.tcx.node_id_to_type(expr.id);
-                        match t.sty {
-                            ty::TyUint(_) => {
-                                check_unsigned_negation_feature(cx, e.span);
-                            },
-                            _ => ()
-                        }
+                if let hir::ExprLit(ref lit) = expr.node {
+                    match lit.node {
+                        ast::LitInt(_, ast::UnsignedIntLit(_)) => {
+                            forbid_unsigned_negation(cx, e.span);
+                        },
+                        ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
+                            if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty {
+                                forbid_unsigned_negation(cx, e.span);
+                            }
+                        },
+                        _ => ()
                     }
-                };
+                } else {
+                    let t = cx.tcx.node_id_to_type(expr.id);
+                    if let ty::TyUint(_) = t.sty {
+                        forbid_unsigned_negation(cx, e.span);
+                    }
+                }
                 // propagate negation, if the negation itself isn't negated
                 if self.negated_expr_id != e.id {
                     self.negated_expr_id = expr.id;
@@ -322,15 +344,11 @@ fn is_comparison(binop: hir::BinOp) -> bool {
             }
         }
 
-        fn check_unsigned_negation_feature(cx: &LateContext, span: Span) {
-            if !cx.sess().features.borrow().negate_unsigned {
-                emit_feature_err(
-                    &cx.sess().parse_sess.span_diagnostic,
-                    "negate_unsigned",
-                    span,
-                    GateIssue::Language,
-                    "unary negation of unsigned integers may be removed in the future");
-            }
+        fn forbid_unsigned_negation(cx: &LateContext, span: Span) {
+            cx.sess()
+              .struct_span_err_with_code(span, "unary negation of unsigned integer", "E0519")
+              .span_help(span, "use a cast or the `!` operator")
+              .emit();
         }
     }
 }
index c281571305b8bc7de8f4df9c4af3af69a4b368f0..3054c307f36d95cfed856979318c8539571d5883 100644 (file)
     ("slice_patterns", "1.0.0", Some(23121), Active),
 
     // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
-    ("negate_unsigned", "1.0.0", Some(29645), Active),
+    ("negate_unsigned", "1.0.0", Some(29645), Removed),
 
     // Allows the definition of associated constants in `trait` or `impl`
     // blocks.
@@ -548,7 +548,6 @@ pub struct Features {
     pub allow_pushpop_unsafe: bool,
     pub simd_ffi: bool,
     pub unmarked_api: bool,
-    pub negate_unsigned: bool,
     /// spans of #![feature] attrs for stable language features. for error reporting
     pub declared_stable_lang_features: Vec<Span>,
     /// #![feature] attrs for non-language (library) features
@@ -585,7 +584,6 @@ pub fn new() -> Features {
             allow_pushpop_unsafe: false,
             simd_ffi: false,
             unmarked_api: false,
-            negate_unsigned: false,
             declared_stable_lang_features: Vec::new(),
             declared_lib_features: Vec::new(),
             const_fn: false,
@@ -1174,7 +1172,6 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
         allow_pushpop_unsafe: cx.has_feature("pushpop_unsafe"),
         simd_ffi: cx.has_feature("simd_ffi"),
         unmarked_api: cx.has_feature("unmarked_api"),
-        negate_unsigned: cx.has_feature("negate_unsigned"),
         declared_stable_lang_features: accepted_features,
         declared_lib_features: unknown_features,
         const_fn: cx.has_feature("const_fn"),
index daa60955ad88decd4d037bc1fe3299d4d24ec018..2a2fc2ef080dbf30cacd440ff6d482e0c7eda65d 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![allow(unused_imports)]
-#![feature(negate_unsigned)]
 
 // Note: the relevant lint pass here runs before some of the constant
 // evaluation below (e.g. that performed by trans and llvm), so if you
@@ -65,7 +64,7 @@
      );
 
 const VALS_U8: (u8, u8, u8, u8) =
-    (-u8::MIN,
+    (-(u8::MIN as i8) as u8,
      u8::MIN - 1,
      //~^ ERROR attempted to sub with overflow
      u8::MAX + 1,
@@ -75,7 +74,7 @@
      );
 
 const VALS_U16: (u16, u16, u16, u16) =
-    (-u16::MIN,
+    (-(u16::MIN as i16) as u16,
      u16::MIN - 1,
      //~^ ERROR attempted to sub with overflow
      u16::MAX + 1,
@@ -85,7 +84,7 @@
      );
 
 const VALS_U32: (u32, u32, u32, u32) =
-    (-u32::MIN,
+    (-(u32::MIN as i32) as u32,
      u32::MIN - 1,
      //~^ ERROR attempted to sub with overflow
      u32::MAX + 1,
@@ -95,7 +94,7 @@
      );
 
 const VALS_U64: (u64, u64, u64, u64) =
-    (-u64::MIN,
+    (-(u64::MIN as i64) as u64,
      u64::MIN - 1,
      //~^ ERROR attempted to sub with overflow
      u64::MAX + 1,
diff --git a/src/test/compile-fail/const-eval-overflow0.rs b/src/test/compile-fail/const-eval-overflow0.rs
new file mode 100644 (file)
index 0000000..7db7de9
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unused_imports)]
+
+// Note: the relevant lint pass here runs before some of the constant
+// evaluation below (e.g. that performed by trans and llvm), so if you
+// change this warn to a deny, then the compiler will exit before
+// those errors are detected.
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const VALS_I8: (i8, i8, i8, i8) =
+    (-i8::MIN,
+     i8::MIN - 1,
+     i8::MAX + 1,
+     i8::MIN * 2,
+     );
+
+const VALS_I16: (i16, i16, i16, i16) =
+    (-i16::MIN,
+     i16::MIN - 1,
+     i16::MAX + 1,
+     i16::MIN * 2,
+     );
+
+const VALS_I32: (i32, i32, i32, i32) =
+    (-i32::MIN,
+     i32::MIN - 1,
+     i32::MAX + 1,
+     i32::MIN * 2,
+     );
+
+const VALS_I64: (i64, i64, i64, i64) =
+    (-i64::MIN,
+     i64::MIN - 1,
+     i64::MAX + 1,
+     i64::MAX * 2,
+     );
+
+const VALS_U8: (u8, u8, u8, u8) =
+    (-u8::MIN,
+     //~^ ERROR unary negation of unsigned integer
+     //~| HELP use a cast or the `!` operator
+     u8::MIN - 1,
+     u8::MAX + 1,
+     u8::MAX * 2,
+     );
+
+const VALS_U16: (u16, u16, u16, u16) =
+    (-u16::MIN,
+     //~^ ERROR unary negation of unsigned integer
+     //~| HELP use a cast or the `!` operator
+     u16::MIN - 1,
+     u16::MAX + 1,
+     u16::MAX * 2,
+     );
+
+const VALS_U32: (u32, u32, u32, u32) =
+    (-u32::MIN,
+     //~^ ERROR unary negation of unsigned integer
+     //~| HELP use a cast or the `!` operator
+     u32::MIN - 1,
+     u32::MAX + 1,
+     u32::MAX * 2,
+     );
+
+const VALS_U64: (u64, u64, u64, u64) =
+    (-u64::MIN,
+     //~^ ERROR unary negation of unsigned integer
+     //~| HELP use a cast or the `!` operator
+     u64::MIN - 1,
+     u64::MAX + 1,
+     u64::MAX * 2,
+     );
+
+fn main() {
+    foo(VALS_I8);
+    foo(VALS_I16);
+    foo(VALS_I32);
+    foo(VALS_I64);
+
+    foo(VALS_U8);
+    foo(VALS_U16);
+    foo(VALS_U32);
+    foo(VALS_U64);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
index cdf7d026d5eebd4b26039d7b9508496c51b8aad4..84a27a382006988820be6dac882733a5b7b3c9f0 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(negate_unsigned)]
 
 #[repr(u8)] //~ NOTE discriminant type specified here
 enum Eu8 {
index b1c73fab4ffa61f2623ad2128c12c3272c47bef1..15cc17b19db33bfc9bb1b2695d95fa6bdfb3df20 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that negating unsigned integers is gated by `negate_unsigned` feature
-// gate
+// Test that negating unsigned integers doesn't compile
 
 struct S;
 impl std::ops::Neg for S {
@@ -18,21 +17,26 @@ fn neg(self) -> u32 { 0 }
 }
 
 const _MAX: usize = -1;
-//~^ ERROR unary negation of unsigned integers may be removed in the future
+//~^ ERROR unary negation of unsigned integer
+//~| HELP use a cast or the `!` operator
 
 fn main() {
     let a = -1;
-    //~^ ERROR unary negation of unsigned integers may be removed in the future
+    //~^ ERROR unary negation of unsigned integer
+    //~| HELP use a cast or the `!` operator
     let _b : u8 = a; // for infering variable a to u8.
 
     -a;
-    //~^ ERROR unary negation of unsigned integers may be removed in the future
+    //~^ ERROR unary negation of unsigned integer
+    //~| HELP use a cast or the `!` operator
 
     let _d = -1u8;
-    //~^ ERROR unary negation of unsigned integers may be removed in the future
+    //~^ ERROR unary negation of unsigned integer
+    //~| HELP use a cast or the `!` operator
 
     for _ in -10..10u8 {}
-    //~^ ERROR unary negation of unsigned integers may be removed in the future
+    //~^ ERROR unary negation of unsigned integer
+    //~| HELP use a cast or the `!` operator
 
     -S; // should not trigger the gate; issue 26840
 }
index 839d50ae63f90359901ecb01dda7ad1489ecf6a4..0b414ad73db6f9109bd33fc5106102bae088e7e5 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(negate_unsigned)]
 #![allow(dead_code)]
-#![feature(negate_unsigned)]
 
 // compile-flags: -D unused-comparisons
 fn main() { }
index a9f19c12b0278e09b1d0f122028ae1f162671f7d..ac24ed8d9160482dd16b583ae006eb512cd477ab 100644 (file)
@@ -8,16 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(negate_unsigned)]
-
 #[cfg(any(target_arch = "x86", target_arch = "arm"))]
 fn target() {
-    assert_eq!(-1000 as usize >> 3_usize, 536870787_usize);
+    assert_eq!(-1000isize as usize >> 3_usize, 536870787_usize);
 }
 
 #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
 fn target() {
-    assert_eq!(-1000 as usize >> 3_usize, 2305843009213693827_usize);
+    assert_eq!(-1000isize as usize >> 3_usize, 2305843009213693827_usize);
 }
 
 fn general() {
index 170a6c95aa8a8f0dd204c1d34dd7968449751b80..759dc515456de1784a2421661821f348a7b4a16d 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(negate_unsigned)]
 #![feature(intrinsics)]
 
 mod rusti {
@@ -45,10 +43,10 @@ pub fn main() {
         assert_eq!(ctpop(100u32), 3); assert_eq!(ctpop(100i32), 3);
         assert_eq!(ctpop(100u64), 3); assert_eq!(ctpop(100i64), 3);
 
-        assert_eq!(ctpop(-1u8), 8); assert_eq!(ctpop(-1i8), 8);
-        assert_eq!(ctpop(-1u16), 16); assert_eq!(ctpop(-1i16), 16);
-        assert_eq!(ctpop(-1u32), 32); assert_eq!(ctpop(-1i32), 32);
-        assert_eq!(ctpop(-1u64), 64); assert_eq!(ctpop(-1i64), 64);
+        assert_eq!(ctpop(-1i8 as u8), 8); assert_eq!(ctpop(-1i8), 8);
+        assert_eq!(ctpop(-1i16 as u16), 16); assert_eq!(ctpop(-1i16), 16);
+        assert_eq!(ctpop(-1i32 as u32), 32); assert_eq!(ctpop(-1i32), 32);
+        assert_eq!(ctpop(-1i64 as u64), 64); assert_eq!(ctpop(-1i64), 64);
 
         assert_eq!(ctlz(0u8), 8); assert_eq!(ctlz(0i8), 8);
         assert_eq!(ctlz(0u16), 16); assert_eq!(ctlz(0i16), 16);
@@ -70,10 +68,10 @@ pub fn main() {
         assert_eq!(ctlz(100u32), 25); assert_eq!(ctlz(100i32), 25);
         assert_eq!(ctlz(100u64), 57); assert_eq!(ctlz(100i64), 57);
 
-        assert_eq!(cttz(-1u8), 0); assert_eq!(cttz(-1i8), 0);
-        assert_eq!(cttz(-1u16), 0); assert_eq!(cttz(-1i16), 0);
-        assert_eq!(cttz(-1u32), 0); assert_eq!(cttz(-1i32), 0);
-        assert_eq!(cttz(-1u64), 0); assert_eq!(cttz(-1i64), 0);
+        assert_eq!(cttz(-1i8 as u8), 0); assert_eq!(cttz(-1i8), 0);
+        assert_eq!(cttz(-1i16 as u16), 0); assert_eq!(cttz(-1i16), 0);
+        assert_eq!(cttz(-1i32 as u32), 0); assert_eq!(cttz(-1i32), 0);
+        assert_eq!(cttz(-1i64 as u64), 0); assert_eq!(cttz(-1i64), 0);
 
         assert_eq!(cttz(0u8), 8); assert_eq!(cttz(0i8), 8);
         assert_eq!(cttz(0u16), 16); assert_eq!(cttz(0i16), 16);
index fdb70fe248eff1bc456ebbf60557582488d985b0..cff260c3ba63e01f9cafd8dbeffb53d5fe6122f8 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(negate_unsigned)]
-
 pub fn main() {
     let a = 1;
     let a_neg: i8 = -a;
@@ -30,26 +28,4 @@ pub fn main() {
     let e = 1;
     let e_neg: isize = -e;
     println!("{}", e_neg);
-
-    // intentional overflows
-
-    let f = 1;
-    let f_neg: u8 = -f;
-    println!("{}", f_neg);
-
-    let g = 1;
-    let g_neg: u16 = -g;
-    println!("{}", g_neg);
-
-    let h = 1;
-    let h_neg: u32 = -h;
-    println!("{}", h_neg);
-
-    let i = 1;
-    let i_neg: u64 = -i;
-    println!("{}", i_neg);
-
-    let j = 1;
-    let j_neg: usize = -j;
-    println!("{}", j_neg);
 }