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:
parent
bf021ea625
commit
173d1bd36b
13 changed files with 121 additions and 54 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue