Skip to content

Commit ed08a67

Browse files
committed
Auto merge of #85254 - cjgillot:reveal-mir, r=lcnr
Normalize MIR with RevealAll before optimizations. Fixes #78442
2 parents bdcb528 + 70aeced commit ed08a67

File tree

7 files changed

+207
-5
lines changed

7 files changed

+207
-5
lines changed

compiler/rustc_mir_transform/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ mod remove_storage_markers;
6666
mod remove_unneeded_drops;
6767
mod remove_zsts;
6868
mod required_consts;
69+
mod reveal_all;
6970
mod separate_const_switch;
7071
mod shim;
7172
mod simplify;
@@ -490,6 +491,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
490491
// to them. We run some optimizations before that, because they may be harder to do on the state
491492
// machine than on MIR with async primitives.
492493
let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[
494+
&reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
493495
&lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
494496
&normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
495497
&unreachable_prop::UnreachablePropagation,

compiler/rustc_mir_transform/src/remove_unneeded_drops.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
1313
trace!("Running RemoveUnneededDrops on {:?}", body.source);
1414

1515
let did = body.source.def_id();
16-
let param_env = tcx.param_env(did);
16+
let param_env = tcx.param_env_reveal_all_normalized(did);
1717
let mut should_simplify = false;
1818

1919
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//! Normalizes MIR in RevealAll mode.
2+
3+
use crate::MirPass;
4+
use rustc_middle::mir::visit::*;
5+
use rustc_middle::mir::*;
6+
use rustc_middle::ty::{self, Ty, TyCtxt};
7+
8+
pub struct RevealAll;
9+
10+
impl<'tcx> MirPass<'tcx> for RevealAll {
11+
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
12+
// This pass must run before inlining, since we insert callee bodies in RevealAll mode.
13+
// Do not apply this transformation to generators.
14+
if (tcx.sess.mir_opt_level() >= 3 || !super::inline::is_enabled(tcx))
15+
&& body.generator.is_none()
16+
{
17+
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
18+
RevealAllVisitor { tcx, param_env }.visit_body(body);
19+
}
20+
}
21+
}
22+
23+
struct RevealAllVisitor<'tcx> {
24+
tcx: TyCtxt<'tcx>,
25+
param_env: ty::ParamEnv<'tcx>,
26+
}
27+
28+
impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
29+
#[inline]
30+
fn tcx(&self) -> TyCtxt<'tcx> {
31+
self.tcx
32+
}
33+
34+
#[inline]
35+
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
36+
*ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
37+
}
38+
39+
#[inline]
40+
fn process_projection_elem(
41+
&mut self,
42+
elem: PlaceElem<'tcx>,
43+
_: Location,
44+
) -> Option<PlaceElem<'tcx>> {
45+
match elem {
46+
PlaceElem::Field(field, ty) => {
47+
let new_ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
48+
if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
49+
}
50+
// None of those contain a Ty.
51+
PlaceElem::Index(..)
52+
| PlaceElem::Deref
53+
| PlaceElem::ConstantIndex { .. }
54+
| PlaceElem::Subslice { .. }
55+
| PlaceElem::Downcast(..) => None,
56+
}
57+
}
58+
}

src/test/mir-opt/inline/inline_generator.main.Inline.diff

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
fn main() -> () {
55
let mut _0: (); // return place in scope 0 at $DIR/inline-generator.rs:8:11: 8:11
6-
let _1: std::ops::GeneratorState<<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Yield, <impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Return>; // in scope 0 at $DIR/inline-generator.rs:9:9: 9:11
7-
let mut _2: std::pin::Pin<&mut impl std::ops::Generator<bool>>; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:32
8-
let mut _3: &mut impl std::ops::Generator<bool>; // in scope 0 at $DIR/inline-generator.rs:9:23: 9:31
9-
let mut _4: impl std::ops::Generator<bool>; // in scope 0 at $DIR/inline-generator.rs:9:28: 9:31
6+
let _1: std::ops::GeneratorState<i32, bool>; // in scope 0 at $DIR/inline-generator.rs:9:9: 9:11
7+
let mut _2: std::pin::Pin<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41]>; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:32
8+
let mut _3: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 0 at $DIR/inline-generator.rs:9:23: 9:31
9+
let mut _4: [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 0 at $DIR/inline-generator.rs:9:28: 9:31
1010
+ let mut _7: bool; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:46
1111
scope 1 {
1212
debug _r => _1; // in scope 1 at $DIR/inline-generator.rs:9:9: 9:11
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// compile-flags: -Z mir-opt-level=3 -Z inline-mir
2+
// ignore-wasm32-bare compiled with panic=abort by default
3+
#![crate_type = "lib"]
4+
5+
// EMIT_MIR issue_78442.bar.RevealAll.diff
6+
// EMIT_MIR issue_78442.bar.Inline.diff
7+
pub fn bar<P>(
8+
// Error won't happen if "bar" is not generic
9+
_baz: P,
10+
) {
11+
hide_foo()();
12+
}
13+
14+
fn hide_foo() -> impl Fn() {
15+
// Error won't happen if "iterate" hasn't impl Trait or has generics
16+
foo
17+
}
18+
19+
fn foo() { // Error won't happen if "foo" isn't used in "iterate" or has generics
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
- // MIR for `bar` before Inline
2+
+ // MIR for `bar` after Inline
3+
4+
fn bar(_1: P) -> () {
5+
debug _baz => _1; // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9
6+
let mut _0: (); // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3
7+
let _2: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
8+
let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
9+
let _4: fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
10+
let mut _5: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
11+
+ scope 1 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) { // at $DIR/issue-78442.rs:11:5: 11:17
12+
+ }
13+
14+
bb0: {
15+
StorageLive(_2); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
16+
StorageLive(_3); // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
17+
StorageLive(_4); // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
18+
- _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
19+
+ _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
20+
// mir::Constant
21+
// + span: $DIR/issue-78442.rs:11:5: 11:13
22+
// + literal: Const { ty: fn() -> impl std::ops::Fn<()> {hide_foo}, val: Value(Scalar(<ZST>)) }
23+
}
24+
25+
bb1: {
26+
_3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
27+
StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
28+
- _2 = <impl Fn<()> as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
29+
- // mir::Constant
30+
- // + span: $DIR/issue-78442.rs:11:5: 11:15
31+
- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl std::ops::Fn<()>, ()) -> <impl std::ops::Fn<()> as std::ops::FnOnce<()>>::Output {<impl std::ops::Fn<()> as std::ops::Fn<()>>::call}, val: Value(Scalar(<ZST>)) }
32+
+ _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $DIR/issue-78442.rs:11:5: 11:17
33+
}
34+
35+
bb2: {
36+
- StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
37+
- StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
38+
- StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
39+
- StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
40+
- _0 = const (); // scope 0 at $DIR/issue-78442.rs:10:3: 12:2
41+
- drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
42+
+ return; // scope 0 at $DIR/issue-78442.rs:12:2: 12:2
43+
}
44+
45+
- bb3: {
46+
- return; // scope 0 at $DIR/issue-78442.rs:12:2: 12:2
47+
+ bb3 (cleanup): {
48+
+ drop(_1) -> bb4; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
49+
}
50+
51+
bb4 (cleanup): {
52+
- drop(_1) -> bb5; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
53+
+ resume; // scope 0 at $DIR/issue-78442.rs:7:1: 12:2
54+
}
55+
56+
- bb5 (cleanup): {
57+
- resume; // scope 0 at $DIR/issue-78442.rs:7:1: 12:2
58+
+ bb5: {
59+
+ StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
60+
+ StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
61+
+ StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
62+
+ StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
63+
+ _0 = const (); // scope 0 at $DIR/issue-78442.rs:10:3: 12:2
64+
+ drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
65+
}
66+
}
67+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
- // MIR for `bar` before RevealAll
2+
+ // MIR for `bar` after RevealAll
3+
4+
fn bar(_1: P) -> () {
5+
debug _baz => _1; // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9
6+
let mut _0: (); // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3
7+
let _2: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
8+
- let mut _3: &impl std::ops::Fn<()>; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
9+
- let _4: impl std::ops::Fn<()>; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
10+
+ let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
11+
+ let _4: fn() {foo}; // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
12+
let mut _5: (); // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
13+
14+
bb0: {
15+
StorageLive(_2); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
16+
StorageLive(_3); // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
17+
StorageLive(_4); // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
18+
_4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
19+
// mir::Constant
20+
// + span: $DIR/issue-78442.rs:11:5: 11:13
21+
// + literal: Const { ty: fn() -> impl std::ops::Fn<()> {hide_foo}, val: Value(Scalar(<ZST>)) }
22+
}
23+
24+
bb1: {
25+
_3 = &_4; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
26+
StorageLive(_5); // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
27+
nop; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
28+
_2 = <impl Fn<()> as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
29+
// mir::Constant
30+
// + span: $DIR/issue-78442.rs:11:5: 11:15
31+
// + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl std::ops::Fn<()>, ()) -> <impl std::ops::Fn<()> as std::ops::FnOnce<()>>::Output {<impl std::ops::Fn<()> as std::ops::Fn<()>>::call}, val: Value(Scalar(<ZST>)) }
32+
}
33+
34+
bb2: {
35+
StorageDead(_5); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
36+
StorageDead(_3); // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
37+
StorageDead(_4); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
38+
StorageDead(_2); // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
39+
_0 = const (); // scope 0 at $DIR/issue-78442.rs:10:3: 12:2
40+
drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
41+
}
42+
43+
bb3: {
44+
return; // scope 0 at $DIR/issue-78442.rs:12:2: 12:2
45+
}
46+
47+
bb4 (cleanup): {
48+
drop(_1) -> bb5; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
49+
}
50+
51+
bb5 (cleanup): {
52+
resume; // scope 0 at $DIR/issue-78442.rs:7:1: 12:2
53+
}
54+
}
55+

0 commit comments

Comments
 (0)