Skip to content

Commit df26968

Browse files
committed
Ensure that we get a hard error on generic ZST constants if their body causes an error during evaluation
1 parent 5c5c8eb commit df26968

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

src/librustc_codegen_ssa/mir/constant.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1616
constant: &mir::Constant<'tcx>,
1717
) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
1818
match constant.literal.val {
19+
// Special case unevaluated statics, because statics have an identity and thus should
20+
// use `get_static` to get at their id.
21+
// FIXME(oli-obk): can we unify this somehow, maybe by making const eval of statics
22+
// always produce `&STATIC`. This may also simplify how const eval works with statics.
1923
ty::ConstKind::Unevaluated(def_id, substs)
2024
if self.cx.tcx().is_static(def_id) => {
2125
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> {
4650
instance,
4751
promoted: None,
4852
};
49-
self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
53+
self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid)).map_err(|err| {
54+
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
55+
err
56+
})
5057
},
5158
_ => Ok(self.monomorphize(&constant.literal)),
5259
}

src/librustc_mir/transform/simplify.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
3030
use rustc_index::bit_set::BitSet;
3131
use rustc_index::vec::{Idx, IndexVec};
32-
use rustc::ty::TyCtxt;
32+
use rustc::ty::{self, TyCtxt};
3333
use rustc::mir::*;
3434
use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext, MutatingUseContext};
3535
use std::borrow::Cow;
@@ -367,9 +367,14 @@ impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> {
367367
if let StatementKind::Assign(
368368
box (p, Rvalue::Use(Operand::Constant(c)))
369369
) = &stmt.kind {
370-
if !p.is_indirect() {
371-
trace!("skipping store of const value {:?} to {:?}", c, p);
372-
return;
370+
match c.literal.val {
371+
// Keep assignments from unevaluated constants around, since the evaluation
372+
// may report errors, even if the use of the constant is dead code.
373+
ty::ConstKind::Unevaluated(..) => {}
374+
_ => if !p.is_indirect() {
375+
trace!("skipping store of const value {:?} to {:?}", c, p);
376+
return;
377+
},
373378
}
374379
}
375380
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![allow(const_err)]
2+
3+
trait ZeroSized: Sized {
4+
const I_AM_ZERO_SIZED: ();
5+
fn requires_zero_size(self);
6+
}
7+
8+
impl<T: Sized> ZeroSized for T {
9+
const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::<Self>()];
10+
fn requires_zero_size(self) {
11+
let () = Self::I_AM_ZERO_SIZED; //~ ERROR erroneous constant encountered
12+
println!("requires_zero_size called");
13+
}
14+
}
15+
16+
fn main() {
17+
().requires_zero_size();
18+
42_u32.requires_zero_size();
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: erroneous constant encountered
2+
--> $DIR/assoc_const_generic_impl.rs:11:18
3+
|
4+
LL | let () = Self::I_AM_ZERO_SIZED;
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)