1
Fork 0

Rollup merge of #109938 - oli-obk:try_norm, r=compiler-errors

Move a const-prop-lint specific hack from mir interpret to const-prop-lint and make it fallible

fixes #109743

This hack didn't need to live in the mir interpreter. For const-prop-lint it is entirely correct to avoid doing any const prop if normalization fails at this stage. Most likely we couldn't const propagate anything anyway, and if revealing was needed (so opaque types were involved), we wouldn't want to be too smart and leak the hidden type anyway.
This commit is contained in:
Michael Goulet 2023-04-04 09:27:47 -07:00 committed by GitHub
commit b0483e8004
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 12 deletions

View file

@ -612,14 +612,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
span: Option<Span>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
// FIXME(const_prop): normalization needed b/c const prop lint in
// `mir_drops_elaborated_and_const_checked`, which happens before
// optimized MIR. Only after optimizing the MIR can we guarantee
// that the `RevealAll` pass has happened and that the body's consts
// are normalized, so any call to resolve before that needs to be
// manually normalized.
let val = self.tcx.normalize_erasing_regions(self.param_env, *val);
match val {
match *val {
mir::ConstantKind::Ty(ct) => {
let ty = ct.ty();
let valtree = self.eval_ty_constant(ct, span)?;

View file

@ -284,7 +284,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
return None;
}
self.use_ecx(source_info, |this| this.ecx.eval_mir_constant(&c.literal, Some(c.span), None))
// Normalization needed b/c const prop lint runs in
// `mir_drops_elaborated_and_const_checked`, which happens before
// optimized MIR. Only after optimizing the MIR can we guarantee
// that the `RevealAll` pass has happened and that the body's consts
// are normalized, so any call to resolve before that needs to be
// manually normalized.
let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.literal).ok()?;
self.use_ecx(source_info, |this| this.ecx.eval_mir_constant(&val, Some(c.span), None))
}
/// Returns the value, if any, of evaluating `place`.

View file

@ -0,0 +1,51 @@
// build-pass
// compile-flags: --crate-type=lib
use std::marker::PhantomData;
pub trait StreamOnce {
type Token;
}
impl StreamOnce for &str {
type Token = ();
}
pub trait Parser<Input: StreamOnce> {
type PartialState: Default;
fn parse_mode(&self, _state: &Self::PartialState) {}
fn parse_mode_impl() {}
}
pub fn parse_bool<'a>() -> impl Parser<&'a str> {
pub struct TokensCmp<C, Input>
where
Input: StreamOnce,
{
_cmp: C,
_marker: PhantomData<Input>,
}
impl<Input, C> Parser<Input> for TokensCmp<C, Input>
where
C: FnMut(Input::Token),
Input: StreamOnce,
{
type PartialState = ();
}
TokensCmp { _cmp: |_| (), _marker: PhantomData }
}
pub struct ParseBool;
impl<'a> Parser<&'a str> for ParseBool
where
&'a str: StreamOnce,
{
type PartialState = ();
fn parse_mode_impl() {
parse_bool().parse_mode(&Default::default())
}
}