diff options
| author | Yuki Okushi <huyuumi.dev@gmail.com> | 2019-12-11 04:32:57 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-12-11 04:32:57 +0900 |
| commit | a7f930748cefc33808686b7f748a503a445579f1 (patch) | |
| tree | 2fec156a29995f117e1b33468f2e93de9f09c6c7 | |
| parent | 9b1b12b94ac115cefd39fe9e4a6c24edfcecd4f1 (diff) | |
| parent | c1434716c1dc67f8c96b488121a9b91163516aa3 (diff) | |
| download | rust-a7f930748cefc33808686b7f748a503a445579f1.tar.gz rust-a7f930748cefc33808686b7f748a503a445579f1.zip | |
Rollup merge of #67134 - oli-obk:const_prop_zst, r=wesleywiser
Ensure that we get a hard error on generic ZST constants if their bod… …y causes an error during evaluation cc #67083 (does not fix because we still need the beta backport) r? @wesleywiser cc @RalfJung
| -rw-r--r-- | src/librustc_codegen_ssa/mir/constant.rs | 9 | ||||
| -rw-r--r-- | src/librustc_mir/transform/simplify.rs | 13 | ||||
| -rw-r--r-- | src/test/ui/consts/assoc_const_generic_impl.rs | 19 | ||||
| -rw-r--r-- | src/test/ui/consts/assoc_const_generic_impl.stderr | 22 |
4 files changed, 58 insertions, 5 deletions
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 27891be6b82..fb8f504d04b 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -16,6 +16,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { constant: &mir::Constant<'tcx>, ) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> { match constant.literal.val { + // Special case unevaluated statics, because statics have an identity and thus should + // use `get_static` to get at their id. + // FIXME(oli-obk): can we unify this somehow, maybe by making const eval of statics + // always produce `&STATIC`. This may also simplify how const eval works with statics. ty::ConstKind::Unevaluated(def_id, substs) if self.cx.tcx().is_static(def_id) => { assert!(substs.is_empty(), "we don't support generic statics yet"); @@ -46,7 +50,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 eef39f8040e..628ac721adc 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -29,7 +29,7 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; -use rustc::ty::TyCtxt; +use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext, MutatingUseContext}; use std::borrow::Cow; @@ -367,9 +367,14 @@ impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> { if let StatementKind::Assign( box (p, Rvalue::Use(Operand::Constant(c))) ) = &stmt.kind { - if !p.is_indirect() { - trace!("skipping store of const value {:?} to {:?}", c, p); - 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. + ty::ConstKind::Unevaluated(..) => {} + _ => if !p.is_indirect() { + 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 00000000000..62702a8ec5c --- /dev/null +++ b/src/test/ui/consts/assoc_const_generic_impl.rs @@ -0,0 +1,19 @@ +#![warn(const_err)] + +trait ZeroSized: Sized { + const I_AM_ZERO_SIZED: (); + fn requires_zero_size(self); +} + +impl<T: Sized> ZeroSized for T { + const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::<Self>()]; //~ 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"); + } +} + +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 00000000000..a114d5c6ccd --- /dev/null +++ b/src/test/ui/consts/assoc_const_generic_impl.stderr @@ -0,0 +1,22 @@ +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::<Self>()]; + | -----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | 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 + | +LL | let () = Self::I_AM_ZERO_SIZED; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + |
