Skip to content

Commit

Permalink
Auto merge of #50224 - pietroalbini:beta-backports, r=alexcrichton
Browse files Browse the repository at this point in the history
[beta] Process backports

* #49779: Don't report compile-time errors for promoteds
* #50110: Warn on all erroneous constants
  • Loading branch information
bors committed Apr 25, 2018
2 parents 5181002 + 656d825 commit 1861fb5
Show file tree
Hide file tree
Showing 27 changed files with 357 additions and 100 deletions.
68 changes: 68 additions & 0 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1430,3 +1430,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
),
_ => {},
}
}
}
1 change: 1 addition & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
UnionsWithDropFields,
UnreachablePub,
TypeAliasBounds,
UnusedBrokenConst,
);

add_builtin_with_new!(sess,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/interpret/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub fn mk_eval_cx<'a, 'tcx>(
Ok(ecx)
}

pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
pub fn eval_promoted<'a, 'mir, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
cid: GlobalId<'tcx>,
mir: &'mir mir::Mir<'tcx>,
Expand All @@ -66,7 +66,7 @@ pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
match res {
Ok(val) => Some(val),
Err(mut err) => {
ecx.report(&mut err, true, None);
ecx.report(&mut err, false, None);
None
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub use self::place::{Place, PlaceExtra};
pub use self::memory::{Memory, MemoryKind, HasMemory};

pub use self::const_eval::{
eval_body_with_mir,
eval_promoted,
mk_borrowck_eval_cx,
eval_body,
CompileTimeEvaluator,
Expand Down
6 changes: 2 additions & 4 deletions src/librustc_mir/monomorphize/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1146,17 +1146,15 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_substs: instance.substs,
}.visit_mir(&mir);
let param_env = ty::ParamEnv::reveal_all();
for (i, promoted) in mir.promoted.iter().enumerate() {
for i in 0..mir.promoted.len() {
use rustc_data_structures::indexed_vec::Idx;
let cid = GlobalId {
instance,
promoted: Some(Promoted::new(i)),
};
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => collect_const(tcx, val, instance.substs, output),
Err(err) => {
err.report(tcx, promoted.span, "promoted");
}
Err(_) => {},
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rustc::mir::visit::{Visitor, PlaceContext};
use rustc::middle::const_val::ConstVal;
use rustc::ty::{TyCtxt, self, Instance};
use rustc::mir::interpret::{Value, PrimVal, GlobalId};
use interpret::{eval_body_with_mir, mk_borrowck_eval_cx, ValTy};
use interpret::{eval_promoted, mk_borrowck_eval_cx, ValTy};
use transform::{MirPass, MirSource};
use syntax::codemap::Span;
use rustc::ty::subst::Substs;
Expand Down Expand Up @@ -161,7 +161,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
};
// cannot use `const_eval` here, because that would require having the MIR
// for the current function available, but we're producing said MIR right now
let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, self.param_env)?;
let (value, _, ty) = eval_promoted(self.tcx, cid, self.mir, self.param_env)?;
let val = (value, ty, c.span);
trace!("evaluated {:?} to {:?}", c, val);
Some(val)
Expand Down
9 changes: 8 additions & 1 deletion src/librustc_trans/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,14 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
self.mir_constant_to_miri_value(bx, constant)
.and_then(|c| OperandRef::from_const(bx, c, ty))
.unwrap_or_else(|err| {
err.report(bx.tcx(), constant.span, "const operand");
match constant.literal {
mir::Literal::Promoted { .. } => {
// don't report errors inside promoteds, just warnings.
},
mir::Literal::Value { .. } => {
err.report(bx.tcx(), constant.span, "const operand")
},
}
// We've errored, so we don't have to produce working code.
let layout = bx.cx.layout_of(ty);
PlaceRef::new_sized(
Expand Down
1 change: 1 addition & 0 deletions src/test/compile-fail/array_const_index-0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/test/compile-fail/array_const_index-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 9 additions & 9 deletions src/test/compile-fail/const-err-early.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 4 additions & 3 deletions src/test/compile-fail/const-err-multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
32 changes: 16 additions & 16 deletions src/test/compile-fail/const-eval-overflow2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
32 changes: 16 additions & 16 deletions src/test/compile-fail/const-eval-overflow2b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Loading

0 comments on commit 1861fb5

Please sign in to comment.