Skip to content

Commit 918dcf2

Browse files
Find potential const-eval cycles during const-checking
1 parent 15f95b1 commit 918dcf2

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

src/librustc_mir/transform/check_consts/validation.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -406,14 +406,31 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
406406
);
407407
}
408408

409-
fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
410-
self.super_operand(op, location);
411-
if let Operand::Constant(c) = op {
412-
if let Some(def_id) = c.check_static_ptr(self.tcx) {
413-
self.check_static(def_id, self.span);
409+
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
410+
self.super_constant(constant, location);
411+
412+
if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val {
413+
assert!(promoted.is_none(), "Const-checking should run before promotion");
414+
415+
// If a cyclic data dependency exists within a const initializer, try to find
416+
// it during const-checking. This is important because MIR optimizations could
417+
// eliminate a cycle before const-eval runs. See #71078 for an example of this.
418+
//
419+
// FIXME: This means we don't look for cycles involving associated constants, but we
420+
// should handle fully monomorphized ones here at least.
421+
if self.tcx.trait_of_item(def_id).is_none() {
422+
let _ = self.tcx.at(self.span).mir_const_qualif(def_id);
414423
}
415424
}
425+
426+
if let Some(def_id) = constant.check_static_ptr(self.tcx) {
427+
self.check_static(def_id, self.span);
428+
429+
// NOTE: Because we are allowed to refer to the address of a static within its
430+
// initializer, we don't try to trigger cycle errors every time we see a static.
431+
}
416432
}
433+
417434
fn visit_projection_elem(
418435
&mut self,
419436
place_local: Local,

0 commit comments

Comments
 (0)