Rollup merge of #30538 - oli-obk:kill_unsigned_unary_negation, r=pnkfelix

fixes  #29645
This commit is contained in:
Simonas Kazlauskas 2016-01-11 21:17:52 +02:00
commit dd6aa056fc
11 changed files with 179 additions and 90 deletions

View File

@ -38,6 +38,7 @@
#![feature(staged_api)]
#![feature(str_char)]
#[macro_use]
extern crate syntax;
#[macro_use]
extern crate rustc;
@ -154,4 +155,5 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
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");
}

View 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;
@ -24,13 +26,39 @@ use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
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 @@ impl LateLintPass for TypeLimits {
}
}
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();
}
}
}

View File

@ -170,7 +170,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
("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 @@ impl 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"),

View 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_I64: (i64, i64, i64, i64) =
);
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_U8: (u8, u8, u8, u8) =
);
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_U16: (u16, u16, u16, u16) =
);
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_U32: (u32, u32, u32, u32) =
);
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,

View File

@ -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);
}

View 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 {

View 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 @@ impl std::ops::Neg for S {
}
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
}

View 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() { }

View 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() {

View 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);

View 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);
}