From 0c9e3dc75cf2b2d122af0596225594240ed254eb Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Tue, 14 Jul 2015 01:03:24 +0300 Subject: [PATCH 1/3] Fix negate_unsigned feature gate check This commit fixes the negate_unsigned feature gate to appropriately account for infered variables. This is technically a [breaking-change]. --- src/libcore/fmt/num.rs | 2 -- src/libcore/ops.rs | 1 - src/libcoretest/fmt/num.rs | 2 -- src/librand/isaac.rs | 1 - src/librustc/middle/const_eval.rs | 9 ----- src/librustc_lint/builtin.rs | 34 +++++++++++-------- src/librustc_trans/trans/adt.rs | 2 -- src/librustc_typeck/check/mod.rs | 10 ------ src/libstd/num/f32.rs | 1 - src/libstd/num/uint_macros.rs | 1 - src/test/compile-fail/const-eval-overflow.rs | 9 ----- .../feature-gate-negate-unsigned.rs | 25 ++++++++++++-- src/test/compile-fail/lint-type-limits.rs | 11 ------ 13 files changed, 42 insertions(+), 66 deletions(-) diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index fc49f87d10769..ccdd23b868d24 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -12,8 +12,6 @@ // FIXME: #6220 Implement floating point formatting -#![allow(unsigned_negation)] - use prelude::*; use fmt; diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 76d3c1df15998..c2a9b8c8308cd 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -517,7 +517,6 @@ pub trait Neg { macro_rules! neg_impl_core { ($id:ident => $body:expr, $($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - #[allow(unsigned_negation)] impl Neg for $t { #[stable(feature = "rust1", since = "1.0.0")] type Output = $t; diff --git a/src/libcoretest/fmt/num.rs b/src/libcoretest/fmt/num.rs index cab2175f89781..247c3dcb9c705 100644 --- a/src/libcoretest/fmt/num.rs +++ b/src/libcoretest/fmt/num.rs @@ -7,8 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unsigned_negation)] - use core::fmt::radix; #[test] diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index ec9aa2d16d24a..1b2210c89edcb 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -126,7 +126,6 @@ impl IsaacRng { /// Refills the output buffer (`self.rsl`) #[inline] - #[allow(unsigned_negation)] fn isaac(&mut self) { self.c = self.c + w(1); // abbreviations diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 7d54b8c284f1f..0f16c06a9dbbc 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -9,7 +9,6 @@ // except according to those terms. #![allow(non_camel_case_types)] -#![allow(unsigned_negation)] use self::ConstVal::*; @@ -27,7 +26,6 @@ use util::num::ToPrimitive; use syntax::ast::{self, Expr}; use syntax::ast_util; use syntax::codemap::Span; -use syntax::feature_gate; use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::{codemap, visit}; @@ -745,13 +743,6 @@ pub fn eval_const_expr_with_substs<'tcx, S>(tcx: &ty::ctxt<'tcx>, Float(f) => Float(-f), Int(n) => try!(const_int_checked_neg(n, e, expr_int_type)), Uint(i) => { - if !tcx.sess.features.borrow().negate_unsigned { - feature_gate::emit_feature_err( - &tcx.sess.parse_sess.span_diagnostic, - "negate_unsigned", - e.span, - "unary negation of unsigned integers may be removed in the future"); - } try!(const_uint_checked_neg(i, e, expr_uint_type)) } Str(_) => signal!(e, NegateOnString), diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 1574080b313b5..d158307478788 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -53,7 +53,7 @@ use syntax::{abi, ast}; use syntax::ast_util::{self, is_shift_binop, local_def}; use syntax::attr::{self, AttrMetaMethods}; use syntax::codemap::{self, Span}; -use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType}; +use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType, emit_feature_err}; use syntax::parse::token; use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; use syntax::ptr::P; @@ -88,12 +88,6 @@ impl LintPass for WhileTrue { } } -declare_lint! { - UNSIGNED_NEGATION, - Warn, - "using an unary minus operator on unsigned type" -} - declare_lint! { UNUSED_COMPARISONS, Warn, @@ -128,8 +122,7 @@ impl TypeLimits { impl LintPass for TypeLimits { fn get_lints(&self) -> LintArray { - lint_array!(UNSIGNED_NEGATION, UNUSED_COMPARISONS, OVERFLOWING_LITERALS, - EXCEEDING_BITSHIFTS) + lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS) } fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { @@ -139,9 +132,12 @@ impl LintPass for TypeLimits { ast::ExprLit(ref lit) => { match lit.node { ast::LitInt(_, ast::UnsignedIntLit(_)) => { - cx.span_lint(UNSIGNED_NEGATION, e.span, - "negation of unsigned int literal may \ - be unintentional"); + check_unsigned_negation_feature(cx, e.span); + }, + ast::LitInt(_, ast::UnsuffixedIntLit(_)) => { + if let ty::TyUint(_) = cx.tcx.expr_ty(e).sty { + check_unsigned_negation_feature(cx, e.span); + } }, _ => () } @@ -150,9 +146,7 @@ impl LintPass for TypeLimits { let t = cx.tcx.expr_ty(&**expr); match t.sty { ty::TyUint(_) => { - cx.span_lint(UNSIGNED_NEGATION, e.span, - "negation of unsigned int variable may \ - be unintentional"); + check_unsigned_negation_feature(cx, e.span); }, _ => () } @@ -385,6 +379,16 @@ impl LintPass for TypeLimits { _ => false } } + + fn check_unsigned_negation_feature(cx: &Context, span: Span) { + if !cx.sess().features.borrow().negate_unsigned { + emit_feature_err( + &cx.sess().parse_sess.span_diagnostic, + "negate_unsigned", + span, + "unary negation of unsigned integers may be removed in the future"); + } + } } } diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 2b480abe3f1f3..7b2bdee50fe78 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -41,8 +41,6 @@ //! used unboxed and any field can have pointers (including mutable) //! taken to it, implementing them for Rust seems difficult. -#![allow(unsigned_negation)] - pub use self::Repr::*; use std::rc::Rc; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5a71d1ed0b5bd..887d01b439b4c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -114,7 +114,6 @@ use syntax::attr::AttrMetaMethods; use syntax::ast::{self, DefId, Visibility}; use syntax::ast_util::{self, local_def}; use syntax::codemap::{self, Span}; -use syntax::feature_gate; use syntax::owned_slice::OwnedSlice; use syntax::parse::token; use syntax::print::pprust; @@ -3074,15 +3073,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, tcx.lang_items.neg_trait(), expr, &**oprnd, oprnd_t, unop); } - if let ty::TyUint(_) = oprnd_t.sty { - if !tcx.sess.features.borrow().negate_unsigned { - feature_gate::emit_feature_err( - &tcx.sess.parse_sess.span_diagnostic, - "negate_unsigned", - expr.span, - "unary negation of unsigned integers may be removed in the future"); - } - } } } } diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index c2fb2fa417598..10cdc0c583377 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -12,7 +12,6 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] -#![allow(unsigned_negation)] #![doc(primitive = "f32")] use prelude::v1::*; diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 555a5cc3e20e9..902c78c0a46f8 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -9,7 +9,6 @@ // except according to those terms. #![doc(hidden)] -#![allow(unsigned_negation)] macro_rules! uint_module { ($T:ident) => ( diff --git a/src/test/compile-fail/const-eval-overflow.rs b/src/test/compile-fail/const-eval-overflow.rs index 19b5f9b094c13..f991e5328c104 100644 --- a/src/test/compile-fail/const-eval-overflow.rs +++ b/src/test/compile-fail/const-eval-overflow.rs @@ -17,7 +17,6 @@ // 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. -#![warn(unsigned_negation)] use std::fmt; use std::{i8, i16, i32, i64, isize}; @@ -69,8 +68,6 @@ const VALS_I64: (i64, i64, i64, i64) = const VALS_U8: (u8, u8, u8, u8) = (-u8::MIN, - //~^ WARNING negation of unsigned int variable may be unintentional - // (The above is separately linted; unsigned negation is defined to be !x+1.) u8::MIN - 1, //~^ ERROR attempted to sub with overflow u8::MAX + 1, @@ -81,8 +78,6 @@ const VALS_U8: (u8, u8, u8, u8) = const VALS_U16: (u16, u16, u16, u16) = (-u16::MIN, - //~^ WARNING negation of unsigned int variable may be unintentional - // (The above is separately linted; unsigned negation is defined to be !x+1.) u16::MIN - 1, //~^ ERROR attempted to sub with overflow u16::MAX + 1, @@ -93,8 +88,6 @@ const VALS_U16: (u16, u16, u16, u16) = const VALS_U32: (u32, u32, u32, u32) = (-u32::MIN, - //~^ WARNING negation of unsigned int variable may be unintentional - // (The above is separately linted; unsigned negation is defined to be !x+1.) u32::MIN - 1, //~^ ERROR attempted to sub with overflow u32::MAX + 1, @@ -105,8 +98,6 @@ const VALS_U32: (u32, u32, u32, u32) = const VALS_U64: (u64, u64, u64, u64) = (-u64::MIN, - //~^ WARNING negation of unsigned int variable may be unintentional - // (The above is separately linted; unsigned negation is defined to be !x+1.) u64::MIN - 1, //~^ ERROR attempted to sub with overflow u64::MAX + 1, diff --git a/src/test/compile-fail/feature-gate-negate-unsigned.rs b/src/test/compile-fail/feature-gate-negate-unsigned.rs index 7dc654fe1c8d5..b1c73fab4ffa6 100644 --- a/src/test/compile-fail/feature-gate-negate-unsigned.rs +++ b/src/test/compile-fail/feature-gate-negate-unsigned.rs @@ -11,7 +11,28 @@ // Test that negating unsigned integers is gated by `negate_unsigned` feature // gate -const MAX: usize = -1; +struct S; +impl std::ops::Neg for S { + type Output = u32; + fn neg(self) -> u32 { 0 } +} + +const _MAX: usize = -1; //~^ ERROR unary negation of unsigned integers may be removed in the future -fn main() {} +fn main() { + let a = -1; + //~^ ERROR unary negation of unsigned integers may be removed in the future + let _b : u8 = a; // for infering variable a to u8. + + -a; + //~^ ERROR unary negation of unsigned integers may be removed in the future + + let _d = -1u8; + //~^ ERROR unary negation of unsigned integers may be removed in the future + + for _ in -10..10u8 {} + //~^ ERROR unary negation of unsigned integers may be removed in the future + + -S; // should not trigger the gate; issue 26840 +} diff --git a/src/test/compile-fail/lint-type-limits.rs b/src/test/compile-fail/lint-type-limits.rs index 42515e0f00c76..839d50ae63f90 100644 --- a/src/test/compile-fail/lint-type-limits.rs +++ b/src/test/compile-fail/lint-type-limits.rs @@ -50,14 +50,3 @@ fn qux() { i += 1; } } - -fn quy() { - let i = -23_usize; //~ WARNING negation of unsigned int literal may be unintentional - //~^ WARNING unused variable -} - -fn quz() { - let i = 23_usize; - let j = -i; //~ WARNING negation of unsigned int variable may be unintentional - //~^ WARNING unused variable -} From 22502154e6c1aee835554216d4b5054fd8f570f8 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 15 Jul 2015 20:12:30 +0300 Subject: [PATCH 2/3] =?UTF-8?q?Implement=20lint=20deprecation/removal?= =?UTF-8?q?=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and deprecate/remove unsigned_negation lint. This is useful to avoid causing breaking changes in case #![deny(unknown_lints)] is used and lint is removed. --- src/librustc/lint/context.rs | 42 +++++++++++++++++++++++++++--------- src/librustc_lint/lib.rs | 2 ++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 567be56b17f29..6d29a1031c6bc 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -75,6 +75,15 @@ enum TargetLint { /// Temporary renaming, used for easing migration pain; see #16545 Renamed(String, LintId), + + /// Lint with this name existed previously, but has been removed/deprecated. + /// The string argument is the reason for removal. + Removed(String), +} + +enum FindLintError { + NotFound, + Removed } impl LintStore { @@ -166,12 +175,16 @@ impl LintStore { self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target)); } + pub fn register_removed(&mut self, name: &str, reason: &str) { + self.by_name.insert(name.into(), Removed(reason.into())); + } + #[allow(unused_variables)] fn find_lint(&self, lint_name: &str, sess: &Session, span: Option) - -> Option + -> Result { match self.by_name.get(lint_name) { - Some(&Id(lint_id)) => Some(lint_id), + Some(&Id(lint_id)) => Ok(lint_id), Some(&Renamed(ref new_name, lint_id)) => { let warning = format!("lint {} has been renamed to {}", lint_name, new_name); @@ -179,17 +192,25 @@ impl LintStore { Some(span) => sess.span_warn(span, &warning[..]), None => sess.warn(&warning[..]), }; - Some(lint_id) - } - None => None + Ok(lint_id) + }, + Some(&Removed(ref reason)) => { + let warning = format!("lint {} has been removed: {}", lint_name, reason); + match span { + Some(span) => sess.span_warn(span, &warning[..]), + None => sess.warn(&warning[..]) + } + Err(FindLintError::Removed) + }, + None => Err(FindLintError::NotFound) } } pub fn process_command_line(&mut self, sess: &Session) { for &(ref lint_name, level) in &sess.opts.lint_opts { match self.find_lint(&lint_name[..], sess, None) { - Some(lint_id) => self.set_level(lint_id, (level, CommandLine)), - None => { + Ok(lint_id) => self.set_level(lint_id, (level, CommandLine)), + Err(_) => { match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone())) .collect::>>() @@ -398,8 +419,8 @@ impl<'a, 'tcx> Context<'a, 'tcx> { } Ok((lint_name, level, span)) => { match self.lints.find_lint(&lint_name, &self.tcx.sess, Some(span)) { - Some(lint_id) => vec![(lint_id, level, span)], - None => { + Ok(lint_id) => vec![(lint_id, level, span)], + Err(FindLintError::NotFound) => { match self.lints.lint_groups.get(&lint_name[..]) { Some(&(ref v, _)) => v.iter() .map(|lint_id: &LintId| @@ -412,7 +433,8 @@ impl<'a, 'tcx> Context<'a, 'tcx> { continue; } } - } + }, + Err(FindLintError::Removed) => { continue; } } } }; diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index c680906dd135b..54c1a79e10a9b 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -134,4 +134,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_renamed("raw_pointer_deriving", "raw_pointer_derive"); store.register_renamed("unknown_features", "unused_features"); + + store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate"); } From 0ca8e4994ee43ba9dfbded6e129b30ff5fe7a994 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 20 Jul 2015 12:17:55 +0300 Subject: [PATCH 3/3] Convert negate_unsigned feature gate to a warning --- src/librustc_lint/builtin.rs | 14 ++++++++------ .../feature-gate-negate-unsigned.rs | 10 +++++----- 2 files changed, 13 insertions(+), 11 deletions(-) rename src/test/{compile-fail => run-pass}/feature-gate-negate-unsigned.rs (67%) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d158307478788..e82e0d790e1bb 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -53,7 +53,7 @@ use syntax::{abi, ast}; use syntax::ast_util::{self, is_shift_binop, local_def}; use syntax::attr::{self, AttrMetaMethods}; use syntax::codemap::{self, Span}; -use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType, emit_feature_err}; +use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType}; use syntax::parse::token; use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; use syntax::ptr::P; @@ -382,11 +382,13 @@ impl LintPass for TypeLimits { fn check_unsigned_negation_feature(cx: &Context, span: Span) { if !cx.sess().features.borrow().negate_unsigned { - emit_feature_err( - &cx.sess().parse_sess.span_diagnostic, - "negate_unsigned", - span, - "unary negation of unsigned integers may be removed in the future"); + // FIXME(#27141): change this to syntax::feature_gate::emit_feature_err… + cx.sess().span_warn(span, + "unary negation of unsigned integers will be feature gated in the future"); + // …and remove following two expressions. + if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; } + cx.sess().fileline_help(span, "add #![feature(negate_unsigned)] to the \ + crate attributes to enable the gate in advance"); } } } diff --git a/src/test/compile-fail/feature-gate-negate-unsigned.rs b/src/test/run-pass/feature-gate-negate-unsigned.rs similarity index 67% rename from src/test/compile-fail/feature-gate-negate-unsigned.rs rename to src/test/run-pass/feature-gate-negate-unsigned.rs index b1c73fab4ffa6..95c8e62be53bc 100644 --- a/src/test/compile-fail/feature-gate-negate-unsigned.rs +++ b/src/test/run-pass/feature-gate-negate-unsigned.rs @@ -18,21 +18,21 @@ impl std::ops::Neg for S { } const _MAX: usize = -1; -//~^ ERROR unary negation of unsigned integers may be removed in the future +//~^ WARN unary negation of unsigned integers will be feature gated in the future fn main() { let a = -1; - //~^ ERROR unary negation of unsigned integers may be removed in the future + //~^ WARN unary negation of unsigned integers will be feature gated in the future let _b : u8 = a; // for infering variable a to u8. -a; - //~^ ERROR unary negation of unsigned integers may be removed in the future + //~^ WARN unary negation of unsigned integers will be feature gated in the future let _d = -1u8; - //~^ ERROR unary negation of unsigned integers may be removed in the future + //~^ WARN unary negation of unsigned integers will be feature gated in the future for _ in -10..10u8 {} - //~^ ERROR unary negation of unsigned integers may be removed in the future + //~^ WARN unary negation of unsigned integers will be feature gated in the future -S; // should not trigger the gate; issue 26840 }