From 020ba3473860ef2392cc49d9f860c2dbd678998e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 8 Dec 2019 01:55:14 +0100 Subject: [PATCH 1/2] Ensure that we get a hard error on generic ZST constants if their body causes an error during evaluation --- src/librustc_codegen_ssa/mir/constant.rs | 5 ++++- src/librustc_mir/transform/simplify.rs | 11 ++++++++--- .../ui/consts/assoc_const_generic_impl.rs | 19 +++++++++++++++++++ .../ui/consts/assoc_const_generic_impl.stderr | 8 ++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/consts/assoc_const_generic_impl.rs create mode 100644 src/test/ui/consts/assoc_const_generic_impl.stderr diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index d06359ab0ce89..72d098eb31117 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -23,7 +23,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { instance, promoted: None, }; - self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid)) + self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid)).map_err(|err| { + self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered"); + err + }) }, _ => Ok(self.monomorphize(&constant.literal)), } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 1b90ea78c6450..385fc7ed2cd00 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -363,9 +363,14 @@ impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> { let stmt = &self.body.basic_blocks()[location.block].statements[location.statement_index]; if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(c)))) = &stmt.kind { - if p.as_local().is_some() { - trace!("skipping store of const value {:?} to {:?}", c, local); - return; + match c.literal.val { + // Keep assignments from unevaluated constants around, since the evaluation + // may report errors, even if the use of the constant is dead code. + interpret::ConstValue::Unevaluated(..) => {} + _ => if p.as_local().is_some() { + trace!("skipping store of const value {:?} to {:?}", c, p); + return; + }, } } } diff --git a/src/test/ui/consts/assoc_const_generic_impl.rs b/src/test/ui/consts/assoc_const_generic_impl.rs new file mode 100644 index 0000000000000..cce0cdbf8c559 --- /dev/null +++ b/src/test/ui/consts/assoc_const_generic_impl.rs @@ -0,0 +1,19 @@ +#![allow(const_err)] + +trait ZeroSized: Sized { + const I_AM_ZERO_SIZED: (); + fn requires_zero_size(self); +} + +impl ZeroSized for T { + const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::()]; + fn requires_zero_size(self) { + let () = Self::I_AM_ZERO_SIZED; //~ ERROR erroneous constant encountered + println!("requires_zero_size called"); + } +} + +fn main() { + ().requires_zero_size(); + 42_u32.requires_zero_size(); +} diff --git a/src/test/ui/consts/assoc_const_generic_impl.stderr b/src/test/ui/consts/assoc_const_generic_impl.stderr new file mode 100644 index 0000000000000..3765a3703c7fc --- /dev/null +++ b/src/test/ui/consts/assoc_const_generic_impl.stderr @@ -0,0 +1,8 @@ +error: erroneous constant encountered + --> $DIR/assoc_const_generic_impl.rs:11:18 + | +LL | let () = Self::I_AM_ZERO_SIZED; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From dff7cc499d60a85cced2db9e6a74549af1db6e4f Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 9 Dec 2019 13:05:41 +0100 Subject: [PATCH 2/2] Show const_err lint in addition to the hard error --- src/test/ui/consts/assoc_const_generic_impl.rs | 4 ++-- src/test/ui/consts/assoc_const_generic_impl.stderr | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/assoc_const_generic_impl.rs b/src/test/ui/consts/assoc_const_generic_impl.rs index cce0cdbf8c559..62702a8ec5cb1 100644 --- a/src/test/ui/consts/assoc_const_generic_impl.rs +++ b/src/test/ui/consts/assoc_const_generic_impl.rs @@ -1,4 +1,4 @@ -#![allow(const_err)] +#![warn(const_err)] trait ZeroSized: Sized { const I_AM_ZERO_SIZED: (); @@ -6,7 +6,7 @@ trait ZeroSized: Sized { } impl ZeroSized for T { - const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::()]; + const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::()]; //~ WARN any use of this value fn requires_zero_size(self) { let () = Self::I_AM_ZERO_SIZED; //~ ERROR erroneous constant encountered println!("requires_zero_size called"); diff --git a/src/test/ui/consts/assoc_const_generic_impl.stderr b/src/test/ui/consts/assoc_const_generic_impl.stderr index 3765a3703c7fc..a114d5c6ccd14 100644 --- a/src/test/ui/consts/assoc_const_generic_impl.stderr +++ b/src/test/ui/consts/assoc_const_generic_impl.stderr @@ -1,3 +1,17 @@ +warning: any use of this value will cause an error + --> $DIR/assoc_const_generic_impl.rs:9:34 + | +LL | const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::()]; + | -----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | index out of bounds: the len is 1 but the index is 4 + | +note: lint level defined here + --> $DIR/assoc_const_generic_impl.rs:1:9 + | +LL | #![warn(const_err)] + | ^^^^^^^^^ + error: erroneous constant encountered --> $DIR/assoc_const_generic_impl.rs:11:18 |