interpret: sanity-check that required_consts captures all consts that can fail
This commit is contained in:
parent
b2b617a88e
commit
bf021ea625
7 changed files with 62 additions and 34 deletions
|
@ -720,18 +720,8 @@ impl<'tcx> Inliner<'tcx> {
|
|||
kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) },
|
||||
});
|
||||
|
||||
// Copy only unevaluated constants from the callee_body into the caller_body.
|
||||
// Although we are only pushing `ConstKind::Unevaluated` consts to
|
||||
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
|
||||
// because we are calling `instantiate_and_normalize_erasing_regions`.
|
||||
caller_body.required_consts.extend(callee_body.required_consts.iter().copied().filter(
|
||||
|&ct| match ct.const_ {
|
||||
Const::Ty(_) => {
|
||||
bug!("should never encounter ty::UnevaluatedConst in `required_consts`")
|
||||
}
|
||||
Const::Val(..) | Const::Unevaluated(..) => true,
|
||||
},
|
||||
));
|
||||
// Copy required constants from the callee_body into the caller_body.
|
||||
caller_body.required_consts.extend(callee_body.required_consts);
|
||||
// Now that we incorporated the callee's `required_consts`, we can remove the callee from
|
||||
// `mentioned_items` -- but we have to take their `mentioned_items` in return. This does
|
||||
// some extra work here to save the monomorphization collector work later. It helps a lot,
|
||||
|
@ -747,8 +737,9 @@ impl<'tcx> Inliner<'tcx> {
|
|||
caller_body.mentioned_items.remove(idx);
|
||||
caller_body.mentioned_items.extend(callee_body.mentioned_items);
|
||||
} else {
|
||||
// If we can't find the callee, there's no point in adding its items.
|
||||
// Probably it already got removed by being inlined elsewhere in the same function.
|
||||
// If we can't find the callee, there's no point in adding its items. Probably it
|
||||
// already got removed by being inlined elsewhere in the same function, so we already
|
||||
// took its items.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{Const, ConstOperand, Location};
|
||||
use rustc_middle::ty::ConstKind;
|
||||
use rustc_middle::ty;
|
||||
|
||||
pub struct RequiredConstsVisitor<'a, 'tcx> {
|
||||
required_consts: &'a mut Vec<ConstOperand<'tcx>>,
|
||||
|
@ -14,14 +14,22 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
|
|||
|
||||
impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
|
||||
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
|
||||
let const_ = constant.const_;
|
||||
match const_ {
|
||||
// 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() {
|
||||
ConstKind::Param(_) | ConstKind::Error(_) | ConstKind::Value(_) => {}
|
||||
_ => bug!("only ConstKind::Param/Value should be encountered here, got {:#?}", c),
|
||||
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(..) => self.required_consts.push(*constant),
|
||||
Const::Val(..) => {}
|
||||
Const::Unevaluated(..) => true,
|
||||
Const::Val(..) => false, // already a value, cannot error
|
||||
};
|
||||
if is_required {
|
||||
self.required_consts.push(*constant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue