diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 6f2c51b0f1899..af0620b00051f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1441,3 +1441,71 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { } } } + +/// Lint constants that are erroneous. +/// Without this lint, we might not get any diagnostic if the constant is +/// unused within this crate, even though downstream crates can't use it +/// without producing an error. +pub struct UnusedBrokenConst; + +impl LintPass for UnusedBrokenConst { + fn get_lints(&self) -> LintArray { + lint_array!() + } +} + +fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) { + let def_id = cx.tcx.hir.body_owner_def_id(body_id); + let param_env = cx.tcx.param_env(def_id); + let cid = ::rustc::mir::interpret::GlobalId { + instance: ty::Instance::mono(cx.tcx, def_id), + promoted: None + }; + if let Err(err) = cx.tcx.const_eval(param_env.and(cid)) { + let span = cx.tcx.def_span(def_id); + let mut diag = cx.struct_span_lint( + CONST_ERR, + span, + &format!("this {} cannot be used", what), + ); + use rustc::middle::const_val::ConstEvalErrDescription; + match err.description() { + ConstEvalErrDescription::Simple(message) => { + diag.span_label(span, message); + } + ConstEvalErrDescription::Backtrace(miri, frames) => { + diag.span_label(span, format!("{}", miri)); + for frame in frames { + diag.span_label(frame.span, format!("inside call to `{}`", frame.location)); + } + } + } + diag.emit() + } +} + +struct UnusedBrokenConstVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>); + +impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UnusedBrokenConstVisitor<'a, 'tcx> { + fn visit_nested_body(&mut self, id: hir::BodyId) { + check_const(self.0, id, "array length"); + } + fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'v> { + hir::intravisit::NestedVisitorMap::None + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { + match it.node { + hir::ItemConst(_, body_id) => { + check_const(cx, body_id, "constant"); + }, + hir::ItemTy(ref ty, _) => hir::intravisit::walk_ty( + &mut UnusedBrokenConstVisitor(cx), + ty + ), + _ => {}, + } + } +} diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 16e8600f2d89b..634b22e4ed7e0 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -136,6 +136,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UnionsWithDropFields, UnreachablePub, TypeAliasBounds, + UnusedBrokenConst, ); add_builtin_with_new!(sess, diff --git a/src/test/compile-fail/array_const_index-0.rs b/src/test/compile-fail/array_const_index-0.rs index 501c66e75cded..9b9deb4ca8d9d 100644 --- a/src/test/compile-fail/array_const_index-0.rs +++ b/src/test/compile-fail/array_const_index-0.rs @@ -12,6 +12,7 @@ const A: &'static [i32] = &[]; const B: i32 = (&A)[1]; //~^ ERROR constant evaluation error //~| index out of bounds: the len is 0 but the index is 1 +//~| WARN this constant cannot be used fn main() { let _ = B; diff --git a/src/test/compile-fail/array_const_index-1.rs b/src/test/compile-fail/array_const_index-1.rs index d3b43e83bfe52..46feb20cf11dd 100644 --- a/src/test/compile-fail/array_const_index-1.rs +++ b/src/test/compile-fail/array_const_index-1.rs @@ -12,6 +12,7 @@ const A: [i32; 0] = []; const B: i32 = A[1]; //~^ ERROR constant evaluation error //~| index out of bounds: the len is 0 but the index is 1 +//~| WARN this constant cannot be used fn main() { let _ = B; diff --git a/src/test/compile-fail/const-err-early.rs b/src/test/compile-fail/const-err-early.rs index 3de0f1ff61e1c..6caec159d019c 100644 --- a/src/test/compile-fail/const-err-early.rs +++ b/src/test/compile-fail/const-err-early.rs @@ -10,17 +10,17 @@ #![deny(const_err)] -pub const A: i8 = -std::i8::MIN; //~ ERROR E0080 -//~^ ERROR attempt to negate with overflow +pub const A: i8 = -std::i8::MIN; //~ ERROR const_err +//~^ ERROR this constant cannot be used //~| ERROR constant evaluation error -pub const B: u8 = 200u8 + 200u8; //~ ERROR E0080 -//~^ ERROR attempt to add with overflow -pub const C: u8 = 200u8 * 4; //~ ERROR E0080 -//~^ ERROR attempt to multiply with overflow -pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR E0080 -//~^ ERROR attempt to subtract with overflow +pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err +//~^ ERROR this constant cannot be used +pub const C: u8 = 200u8 * 4; //~ ERROR const_err +//~^ ERROR this constant cannot be used +pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR const_err +//~^ ERROR this constant cannot be used pub const E: u8 = [5u8][1]; -//~^ ERROR E0080 +//~^ ERROR const_err fn main() { let _a = A; diff --git a/src/test/compile-fail/const-err-multi.rs b/src/test/compile-fail/const-err-multi.rs index d2355f57f1729..6f0281b8bd0ca 100644 --- a/src/test/compile-fail/const-err-multi.rs +++ b/src/test/compile-fail/const-err-multi.rs @@ -14,12 +14,13 @@ pub const A: i8 = -std::i8::MIN; //~^ ERROR E0080 //~| ERROR attempt to negate with overflow //~| ERROR constant evaluation error +//~| ERROR this constant cannot be used pub const B: i8 = A; -//~^ ERROR E0080 +//~^ ERROR const_err pub const C: u8 = A as u8; -//~^ ERROR E0080 +//~^ ERROR const_err pub const D: i8 = 50 - A; -//~^ ERROR E0080 +//~^ ERROR const_err fn main() { let _ = (A, B, C, D); diff --git a/src/test/compile-fail/const-eval-overflow2.rs b/src/test/compile-fail/const-eval-overflow2.rs index a0d8f9672c05e..faa8c3039b78c 100644 --- a/src/test/compile-fail/const-eval-overflow2.rs +++ b/src/test/compile-fail/const-eval-overflow2.rs @@ -22,57 +22,57 @@ use std::{i8, i16, i32, i64, isize}; use std::{u8, u16, u32, u64, usize}; const VALS_I8: (i8,) = + //~^ ERROR this constant cannot be used ( i8::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_I16: (i16,) = + //~^ ERROR this constant cannot be used ( i16::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_I32: (i32,) = + //~^ ERROR this constant cannot be used ( i32::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_I64: (i64,) = + //~^ ERROR this constant cannot be used ( i64::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_U8: (u8,) = + //~^ ERROR this constant cannot be used ( u8::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_U16: (u16,) = ( + //~^ ERROR this constant cannot be used u16::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_U32: (u32,) = ( + //~^ ERROR this constant cannot be used u32::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); const VALS_U64: (u64,) = + //~^ ERROR this constant cannot be used ( u64::MIN - 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to subtract with overflow + //~^ ERROR attempt to subtract with overflow ); fn main() { diff --git a/src/test/compile-fail/const-eval-overflow2b.rs b/src/test/compile-fail/const-eval-overflow2b.rs index 08128f90e532f..d827e680c5bbb 100644 --- a/src/test/compile-fail/const-eval-overflow2b.rs +++ b/src/test/compile-fail/const-eval-overflow2b.rs @@ -22,57 +22,57 @@ use std::{i8, i16, i32, i64, isize}; use std::{u8, u16, u32, u64, usize}; const VALS_I8: (i8,) = + //~^ ERROR this constant cannot be used ( i8::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_I16: (i16,) = + //~^ ERROR this constant cannot be used ( i16::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_I32: (i32,) = + //~^ ERROR this constant cannot be used ( i32::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_I64: (i64,) = + //~^ ERROR this constant cannot be used ( i64::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_U8: (u8,) = + //~^ ERROR this constant cannot be used ( u8::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_U16: (u16,) = ( + //~^ ERROR this constant cannot be used u16::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_U32: (u32,) = ( + //~^ ERROR this constant cannot be used u32::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); const VALS_U64: (u64,) = + //~^ ERROR this constant cannot be used ( u64::MAX + 1, - //~^ ERROR constant evaluation error - //~| ERROR attempt to add with overflow + //~^ ERROR attempt to add with overflow ); fn main() { diff --git a/src/test/compile-fail/const-eval-overflow2c.rs b/src/test/compile-fail/const-eval-overflow2c.rs index 31a1638cade17..2fd46b038ef28 100644 --- a/src/test/compile-fail/const-eval-overflow2c.rs +++ b/src/test/compile-fail/const-eval-overflow2c.rs @@ -22,57 +22,57 @@ use std::{i8, i16, i32, i64, isize}; use std::{u8, u16, u32, u64, usize}; const VALS_I8: (i8,) = + //~^ ERROR this constant cannot be used ( i8::MIN * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_I16: (i16,) = + //~^ ERROR this constant cannot be used ( i16::MIN * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_I32: (i32,) = + //~^ ERROR this constant cannot be used ( i32::MIN * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_I64: (i64,) = + //~^ ERROR this constant cannot be used ( i64::MIN * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_U8: (u8,) = + //~^ ERROR this constant cannot be used ( u8::MAX * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_U16: (u16,) = ( + //~^ ERROR this constant cannot be used u16::MAX * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_U32: (u32,) = ( + //~^ ERROR this constant cannot be used u32::MAX * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); const VALS_U64: (u64,) = + //~^ ERROR this constant cannot be used ( u64::MAX * 2, - //~^ ERROR constant evaluation error - //~| ERROR attempt to multiply with overflow + //~^ ERROR attempt to multiply with overflow ); fn main() { diff --git a/src/test/compile-fail/const-slice-oob.rs b/src/test/compile-fail/const-slice-oob.rs index 179ea9e853f3a..7da5a2f17eaf9 100644 --- a/src/test/compile-fail/const-slice-oob.rs +++ b/src/test/compile-fail/const-slice-oob.rs @@ -14,6 +14,7 @@ const FOO: &'static[u32] = &[1, 2, 3]; const BAR: u32 = FOO[5]; //~^ ERROR constant evaluation error [E0080] //~| index out of bounds: the len is 3 but the index is 5 +//~| WARN this constant cannot be used fn main() { let _ = BAR; diff --git a/src/test/ui/const-eval/conditional_array_execution.rs b/src/test/ui/const-eval/conditional_array_execution.rs index e059c354d65a7..dbddee862e022 100644 --- a/src/test/ui/const-eval/conditional_array_execution.rs +++ b/src/test/ui/const-eval/conditional_array_execution.rs @@ -14,6 +14,7 @@ const X: u32 = 5; const Y: u32 = 6; const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; //~^ WARN attempt to subtract with overflow +//~| WARN this constant cannot be used fn main() { println!("{}", FOO); diff --git a/src/test/ui/const-eval/conditional_array_execution.stderr b/src/test/ui/const-eval/conditional_array_execution.stderr index fd29990fec295..713b1b36c08b1 100644 --- a/src/test/ui/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.stderr @@ -6,8 +6,14 @@ LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; | = note: #[warn(const_err)] on by default +warning: this constant cannot be used + --> $DIR/conditional_array_execution.rs:15:1 + | +LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + warning: constant evaluation error - --> $DIR/conditional_array_execution.rs:19:20 + --> $DIR/conditional_array_execution.rs:20:20 | LL | println!("{}", FOO); | ^^^ referenced constant has errors diff --git a/src/test/ui/const-eval/issue-43197.rs b/src/test/ui/const-eval/issue-43197.rs index b27791ef5337b..097fba4d3c450 100644 --- a/src/test/ui/const-eval/issue-43197.rs +++ b/src/test/ui/const-eval/issue-43197.rs @@ -19,8 +19,10 @@ const fn foo(x: u32) -> u32 { fn main() { const X: u32 = 0-1; //~^ WARN attempt to subtract with overflow + //~| WARN this constant cannot be used const Y: u32 = foo(0-1); //~^ WARN attempt to subtract with overflow + //~| WARN this constant cannot be used println!("{} {}", X, Y); //~^ WARN constant evaluation error //~| WARN constant evaluation error diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr index 5da47a85eb803..a22e8016296c4 100644 --- a/src/test/ui/const-eval/issue-43197.stderr +++ b/src/test/ui/const-eval/issue-43197.stderr @@ -6,20 +6,32 @@ LL | const X: u32 = 0-1; | = note: #[warn(const_err)] on by default -warning: constant evaluation error - --> $DIR/issue-43197.rs:24:23 +warning: this constant cannot be used + --> $DIR/issue-43197.rs:20:5 | -LL | println!("{} {}", X, Y); - | ^ referenced constant has errors +LL | const X: u32 = 0-1; + | ^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow warning: attempt to subtract with overflow - --> $DIR/issue-43197.rs:22:24 + --> $DIR/issue-43197.rs:23:24 | LL | const Y: u32 = foo(0-1); | ^^^ +warning: this constant cannot be used + --> $DIR/issue-43197.rs:23:5 + | +LL | const Y: u32 = foo(0-1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +warning: constant evaluation error + --> $DIR/issue-43197.rs:26:23 + | +LL | println!("{} {}", X, Y); + | ^ referenced constant has errors + warning: constant evaluation error - --> $DIR/issue-43197.rs:24:26 + --> $DIR/issue-43197.rs:26:26 | LL | println!("{} {}", X, Y); | ^ referenced constant has errors diff --git a/src/test/ui/const-eval/pub_const_err.rs b/src/test/ui/const-eval/pub_const_err.rs index bdb9f5b19a885..c6bf07649af38 100644 --- a/src/test/ui/const-eval/pub_const_err.rs +++ b/src/test/ui/const-eval/pub_const_err.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(const_err)] +// compile-pass #![crate_type = "lib"] pub const Z: u32 = 0 - 1; -//~^ ERROR attempt to subtract with overflow +//~^ WARN attempt to subtract with overflow +//~| WARN this constant cannot be used + +pub type Foo = [i32; 0 - 1]; +//~^ WARN attempt to subtract with overflow +//~| WARN this array length cannot be used diff --git a/src/test/ui/const-eval/pub_const_err.stderr b/src/test/ui/const-eval/pub_const_err.stderr index b77ec38ca1679..2981ac20cd981 100644 --- a/src/test/ui/const-eval/pub_const_err.stderr +++ b/src/test/ui/const-eval/pub_const_err.stderr @@ -1,14 +1,26 @@ -error: attempt to subtract with overflow +warning: attempt to subtract with overflow --> $DIR/pub_const_err.rs:15:20 | LL | pub const Z: u32 = 0 - 1; | ^^^^^ | -note: lint level defined here - --> $DIR/pub_const_err.rs:11:9 + = note: #[warn(const_err)] on by default + +warning: this constant cannot be used + --> $DIR/pub_const_err.rs:15:1 | -LL | #![deny(const_err)] - | ^^^^^^^^^ +LL | pub const Z: u32 = 0 - 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow -error: aborting due to previous error +warning: attempt to subtract with overflow + --> $DIR/pub_const_err.rs:19:22 + | +LL | pub type Foo = [i32; 0 - 1]; + | ^^^^^ + +warning: this array length cannot be used + --> $DIR/pub_const_err.rs:19:22 + | +LL | pub type Foo = [i32; 0 - 1]; + | ^^^^^ attempt to subtract with overflow diff --git a/src/test/ui/const-eval/pub_const_err_bin.rs b/src/test/ui/const-eval/pub_const_err_bin.rs new file mode 100644 index 0000000000000..d87cb7ed77079 --- /dev/null +++ b/src/test/ui/const-eval/pub_const_err_bin.rs @@ -0,0 +1,21 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +pub const Z: u32 = 0 - 1; +//~^ WARN attempt to subtract with overflow +//~| WARN this constant cannot be used + +pub type Foo = [i32; 0 - 1]; +//~^ WARN attempt to subtract with overflow +//~| WARN this array length cannot be used + +fn main() {} diff --git a/src/test/ui/const-eval/pub_const_err_bin.stderr b/src/test/ui/const-eval/pub_const_err_bin.stderr new file mode 100644 index 0000000000000..3e8966d854bf0 --- /dev/null +++ b/src/test/ui/const-eval/pub_const_err_bin.stderr @@ -0,0 +1,26 @@ +warning: attempt to subtract with overflow + --> $DIR/pub_const_err_bin.rs:13:20 + | +LL | pub const Z: u32 = 0 - 1; + | ^^^^^ + | + = note: #[warn(const_err)] on by default + +warning: this constant cannot be used + --> $DIR/pub_const_err_bin.rs:13:1 + | +LL | pub const Z: u32 = 0 - 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +warning: attempt to subtract with overflow + --> $DIR/pub_const_err_bin.rs:17:22 + | +LL | pub type Foo = [i32; 0 - 1]; + | ^^^^^ + +warning: this array length cannot be used + --> $DIR/pub_const_err_bin.rs:17:22 + | +LL | pub type Foo = [i32; 0 - 1]; + | ^^^^^ attempt to subtract with overflow +