about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/remove_unneeded_drops.rs2
-rw-r--r--compiler/rustc_mir_transform/src/reveal_all.rs58
-rw-r--r--src/test/mir-opt/inline/inline_generator.main.Inline.diff8
-rw-r--r--src/test/mir-opt/inline/issue-78442.rs20
-rw-r--r--src/test/mir-opt/inline/issue_78442.bar.Inline.diff67
-rw-r--r--src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff55
7 files changed, 207 insertions, 5 deletions
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 8638cbac049..d6bf2de1668 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -66,6 +66,7 @@ mod remove_storage_markers;
 mod remove_unneeded_drops;
 mod remove_zsts;
 mod required_consts;
+mod reveal_all;
 mod separate_const_switch;
 mod shim;
 mod simplify;
@@ -490,6 +491,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     // to them. We run some optimizations before that, because they may be harder to do on the state
     // machine than on MIR with async primitives.
     let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[
+        &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
         &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
         &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
         &unreachable_prop::UnreachablePropagation,
diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
index 5c9d04a08bf..c71bc512c31 100644
--- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -13,7 +13,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
         trace!("Running RemoveUnneededDrops on {:?}", body.source);
 
         let did = body.source.def_id();
-        let param_env = tcx.param_env(did);
+        let param_env = tcx.param_env_reveal_all_normalized(did);
         let mut should_simplify = false;
 
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
new file mode 100644
index 00000000000..7b4eb4912cb
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -0,0 +1,58 @@
+//! Normalizes MIR in RevealAll mode.
+
+use crate::MirPass;
+use rustc_middle::mir::visit::*;
+use rustc_middle::mir::*;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub struct RevealAll;
+
+impl<'tcx> MirPass<'tcx> for RevealAll {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        // This pass must run before inlining, since we insert callee bodies in RevealAll mode.
+        // Do not apply this transformation to generators.
+        if (tcx.sess.mir_opt_level() >= 3 || !super::inline::is_enabled(tcx))
+            && body.generator.is_none()
+        {
+            let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+            RevealAllVisitor { tcx, param_env }.visit_body(body);
+        }
+    }
+}
+
+struct RevealAllVisitor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+}
+
+impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
+    #[inline]
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    #[inline]
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
+        *ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
+    }
+
+    #[inline]
+    fn process_projection_elem(
+        &mut self,
+        elem: PlaceElem<'tcx>,
+        _: Location,
+    ) -> Option<PlaceElem<'tcx>> {
+        match elem {
+            PlaceElem::Field(field, ty) => {
+                let new_ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
+                if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
+            }
+            // None of those contain a Ty.
+            PlaceElem::Index(..)
+            | PlaceElem::Deref
+            | PlaceElem::ConstantIndex { .. }
+            | PlaceElem::Subslice { .. }
+            | PlaceElem::Downcast(..) => None,
+        }
+    }
+}
diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
index 9035b46f4c6..29243c9aa75 100644
--- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
@@ -3,10 +3,10 @@
   
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/inline-generator.rs:8:11: 8:11
-      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
-      let mut _2: std::pin::Pin<&mut impl std::ops::Generator<bool>>; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:32
-      let mut _3: &mut impl std::ops::Generator<bool>; // in scope 0 at $DIR/inline-generator.rs:9:23: 9:31
-      let mut _4: impl std::ops::Generator<bool>; // in scope 0 at $DIR/inline-generator.rs:9:28: 9:31
+      let _1: std::ops::GeneratorState<i32, bool>; // in scope 0 at $DIR/inline-generator.rs:9:9: 9:11
+      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
+      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
+      let mut _4: [generator@$DIR/inline-generator.rs:15:5: 15:41]; // in scope 0 at $DIR/inline-generator.rs:9:28: 9:31
 +     let mut _7: bool;                    // in scope 0 at $DIR/inline-generator.rs:9:14: 9:46
       scope 1 {
           debug _r => _1;                  // in scope 1 at $DIR/inline-generator.rs:9:9: 9:11
diff --git a/src/test/mir-opt/inline/issue-78442.rs b/src/test/mir-opt/inline/issue-78442.rs
new file mode 100644
index 00000000000..aa8ede2df9e
--- /dev/null
+++ b/src/test/mir-opt/inline/issue-78442.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Z mir-opt-level=3 -Z inline-mir
+// ignore-wasm32-bare compiled with panic=abort by default
+#![crate_type = "lib"]
+
+// EMIT_MIR issue_78442.bar.RevealAll.diff
+// EMIT_MIR issue_78442.bar.Inline.diff
+pub fn bar<P>(
+    // Error won't happen if "bar" is not generic
+    _baz: P,
+) {
+    hide_foo()();
+}
+
+fn hide_foo() -> impl Fn() {
+    // Error won't happen if "iterate" hasn't impl Trait or has generics
+    foo
+}
+
+fn foo() { // Error won't happen if "foo" isn't used in "iterate" or has generics
+}
diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff
new file mode 100644
index 00000000000..4d9e022d825
--- /dev/null
+++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff
@@ -0,0 +1,67 @@
+- // MIR for `bar` before Inline
++ // MIR for `bar` after Inline
+  
+  fn bar(_1: P) -> () {
+      debug _baz => _1;                    // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9
+      let mut _0: ();                      // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3
+      let _2: ();                          // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+      let mut _3: &fn() {foo};             // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+      let _4: fn() {foo};                  // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+      let mut _5: ();                      // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
++     scope 1 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) { // at $DIR/issue-78442.rs:11:5: 11:17
++     }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+          StorageLive(_3);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+          StorageLive(_4);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+-         _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
++         _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+                                           // mir::Constant
+                                           // + span: $DIR/issue-78442.rs:11:5: 11:13
+                                           // + literal: Const { ty: fn() -> impl std::ops::Fn<()> {hide_foo}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+          _3 = &_4;                        // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+          StorageLive(_5);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+-         _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
+-                                          // mir::Constant
+-                                          // + span: $DIR/issue-78442.rs:11:5: 11:15
+-                                          // + 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>)) }
++         _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $DIR/issue-78442.rs:11:5: 11:17
+      }
+  
+      bb2: {
+-         StorageDead(_5);                 // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
+-         StorageDead(_3);                 // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
+-         StorageDead(_4);                 // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
+-         StorageDead(_2);                 // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
+-         _0 = const ();                   // scope 0 at $DIR/issue-78442.rs:10:3: 12:2
+-         drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
++         return;                          // scope 0 at $DIR/issue-78442.rs:12:2: 12:2
+      }
+  
+-     bb3: {
+-         return;                          // scope 0 at $DIR/issue-78442.rs:12:2: 12:2
++     bb3 (cleanup): {
++         drop(_1) -> bb4;                 // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
+      }
+  
+      bb4 (cleanup): {
+-         drop(_1) -> bb5;                 // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
++         resume;                          // scope 0 at $DIR/issue-78442.rs:7:1: 12:2
+      }
+  
+-     bb5 (cleanup): {
+-         resume;                          // scope 0 at $DIR/issue-78442.rs:7:1: 12:2
++     bb5: {
++         StorageDead(_5);                 // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
++         StorageDead(_3);                 // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
++         StorageDead(_4);                 // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
++         StorageDead(_2);                 // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
++         _0 = const ();                   // scope 0 at $DIR/issue-78442.rs:10:3: 12:2
++         drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff
new file mode 100644
index 00000000000..45b552cc634
--- /dev/null
+++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff
@@ -0,0 +1,55 @@
+- // MIR for `bar` before RevealAll
++ // MIR for `bar` after RevealAll
+  
+  fn bar(_1: P) -> () {
+      debug _baz => _1;                    // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9
+      let mut _0: ();                      // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3
+      let _2: ();                          // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+-     let mut _3: &impl std::ops::Fn<()>;  // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+-     let _4: impl std::ops::Fn<()>;       // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
++     let mut _3: &fn() {foo};             // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
++     let _4: fn() {foo};                  // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+      let mut _5: ();                      // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+          StorageLive(_3);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+          StorageLive(_4);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+          _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+                                           // mir::Constant
+                                           // + span: $DIR/issue-78442.rs:11:5: 11:13
+                                           // + literal: Const { ty: fn() -> impl std::ops::Fn<()> {hide_foo}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+          _3 = &_4;                        // scope 0 at $DIR/issue-78442.rs:11:5: 11:15
+          StorageLive(_5);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+          nop;                             // scope 0 at $DIR/issue-78442.rs:11:5: 11:17
+          _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
+                                           // mir::Constant
+                                           // + span: $DIR/issue-78442.rs:11:5: 11:15
+                                           // + 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>)) }
+      }
+  
+      bb2: {
+          StorageDead(_5);                 // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
+          StorageDead(_3);                 // scope 0 at $DIR/issue-78442.rs:11:16: 11:17
+          StorageDead(_4);                 // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
+          StorageDead(_2);                 // scope 0 at $DIR/issue-78442.rs:11:17: 11:18
+          _0 = const ();                   // scope 0 at $DIR/issue-78442.rs:10:3: 12:2
+          drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
+      }
+  
+      bb3: {
+          return;                          // scope 0 at $DIR/issue-78442.rs:12:2: 12:2
+      }
+  
+      bb4 (cleanup): {
+          drop(_1) -> bb5;                 // scope 0 at $DIR/issue-78442.rs:12:1: 12:2
+      }
+  
+      bb5 (cleanup): {
+          resume;                          // scope 0 at $DIR/issue-78442.rs:7:1: 12:2
+      }
+  }
+