Skip to content

Commit

Permalink
[breaking-change] remove negate_unsigned feature gate
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jan 11, 2016
1 parent 69e1f57 commit bac3eec
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 90 deletions.
2 changes: 2 additions & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#![feature(staged_api)]
#![feature(str_char)]

#[macro_use]
extern crate syntax;
#[macro_use]
extern crate rustc;
Expand Down Expand Up @@ -153,4 +154,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");
}
84 changes: 51 additions & 33 deletions src/librustc_lint/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
}
}
Expand Down
5 changes: 1 addition & 4 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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"),
Expand Down
9 changes: 4 additions & 5 deletions src/test/compile-fail/const-eval-overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
100 changes: 100 additions & 0 deletions src/test/compile-fail/const-eval-overflow0.rs
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 0 additions & 1 deletion src/test/compile-fail/enum-discrim-too-small.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
18 changes: 11 additions & 7 deletions src/test/compile-fail/feature-gate-negate-unsigned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
2 changes: 0 additions & 2 deletions src/test/compile-fail/lint-type-limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() { }
Expand Down
6 changes: 2 additions & 4 deletions src/test/run-pass/bitwise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Loading

0 comments on commit bac3eec

Please sign in to comment.