Skip to content

Commit

Permalink
Rollup merge of #109938 - oli-obk:try_norm, r=compiler-errors
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
compiler-errors committed Apr 4, 2023
2 parents d984671 + b5d96d5 commit b0483e8
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 12 deletions.
9 changes: 1 addition & 8 deletions compiler/rustc_const_eval/src/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
let arg = self.param_env.and(arg);

self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!(
"Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
arg.value
))
"Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
arg.value
))
}
}

Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_mir_transform/src/const_prop_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
51 changes: 51 additions & 0 deletions tests/ui/mir/issue-109743.rs
Original file line number Diff line number Diff line change
@@ -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())
}
}

0 comments on commit b0483e8

Please sign in to comment.