1
Fork 0

properly fill a promoted's required_consts

then we can also make all_required_consts_are_checked a constant instead of a function
This commit is contained in:
Ralf Jung 2024-03-21 13:53:00 +01:00
parent bf021ea625
commit 173d1bd36b
13 changed files with 121 additions and 54 deletions

View file

@ -951,6 +951,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
*local = self.promote_temp(*local);
}
}
fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, _location: Location) {
if constant.const_.is_required_const() {
self.promoted.required_consts.push(*constant);
}
// Skipping `super_constant` as the visitor is otherwise only looking for locals.
}
}
fn promote_candidates<'tcx>(
@ -995,11 +1003,6 @@ fn promote_candidates<'tcx>(
None,
body.tainted_by_errors,
);
// We keep `required_consts` of the new MIR body empty. All consts mentioned here have
// already been added to the parent MIR's `required_consts` (that is computed before
// promotion), and no matter where this promoted const ends up, our parent MIR must be
// somewhere in the reachable dependency chain so we can rely on its required consts being
// evaluated.
promoted.phase = MirPhase::Analysis(AnalysisPhase::Initial);
let promoter = Promoter {
@ -1012,6 +1015,7 @@ fn promote_candidates<'tcx>(
add_to_required: false,
};
// `required_consts` of the promoted itself gets filled while building the MIR body.
let mut promoted = promoter.promote_candidate(candidate, promotions.len());
promoted.source.promoted = Some(promotions.next_index());
promotions.push(promoted);

View file

@ -1,6 +1,5 @@
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{Const, ConstOperand, Location};
use rustc_middle::ty;
use rustc_middle::mir::{ConstOperand, Location};
pub struct RequiredConstsVisitor<'a, 'tcx> {
required_consts: &'a mut Vec<ConstOperand<'tcx>>,
@ -14,21 +13,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
// Only unevaluated consts have to be added to `required_consts` as only those can possibly
// still have latent const-eval errors.
let is_required = match constant.const_ {
Const::Ty(c) => match c.kind() {
ty::ConstKind::Value(_) => false, // already a value, cannot error
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) => true, // these are errors or could be replaced by errors
_ => bug!(
"only ConstKind::Param/Value/Error should be encountered here, got {:#?}",
c
),
},
Const::Unevaluated(..) => true,
Const::Val(..) => false, // already a value, cannot error
};
if is_required {
if constant.const_.is_required_const() {
self.required_consts.push(*constant);
}
}