]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_middle/src/mir/mod.rs
fix most compiler/ doctests
[rust.git] / compiler / rustc_middle / src / mir / mod.rs
index 4f4b6cf704fa9d75e147c0a5462ef21dcfcab541..b357a657b5981de15a7752bfd3fd2457a8aaae37 100644 (file)
@@ -62,7 +62,9 @@
 mod switch_sources;
 pub mod tcx;
 pub mod terminator;
+use crate::mir::traversal::PostorderCache;
 pub use terminator::*;
+
 pub mod traversal;
 mod type_foldable;
 pub mod visit;
@@ -166,7 +168,8 @@ pub enum MirPhase {
     /// * [`StatementKind::Retag`]
     ///
     /// Furthermore, `Drop` now uses explicit drop flags visible in the MIR and reaching a `Drop`
-    /// terminator means that the auto-generated drop glue will be invoked.
+    /// terminator means that the auto-generated drop glue will be invoked. Also, `Copy` operands
+    /// are allowed for non-`Copy` types.
     DropsLowered = 3,
     /// Beginning with this phase, the following variant is disallowed:
     /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
@@ -322,6 +325,7 @@ pub struct Body<'tcx> {
     predecessor_cache: PredecessorCache,
     switch_source_cache: SwitchSourceCache,
     is_cyclic: GraphIsCyclicCache,
+    postorder_cache: PostorderCache,
 
     pub tainted_by_errors: Option<ErrorGuaranteed>,
 }
@@ -371,6 +375,7 @@ pub fn new(
             predecessor_cache: PredecessorCache::new(),
             switch_source_cache: SwitchSourceCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
+            postorder_cache: PostorderCache::new(),
             tainted_by_errors,
         };
         body.is_polymorphic = body.has_param_types_or_consts();
@@ -400,6 +405,7 @@ pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) ->
             predecessor_cache: PredecessorCache::new(),
             switch_source_cache: SwitchSourceCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
+            postorder_cache: PostorderCache::new(),
             tainted_by_errors: None,
         };
         body.is_polymorphic = body.has_param_types_or_consts();
@@ -421,6 +427,7 @@ pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'
         self.predecessor_cache.invalidate();
         self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
+        self.postorder_cache.invalidate();
         &mut self.basic_blocks
     }
 
@@ -431,6 +438,7 @@ pub fn basic_blocks_and_local_decls_mut(
         self.predecessor_cache.invalidate();
         self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
+        self.postorder_cache.invalidate();
         (&mut self.basic_blocks, &mut self.local_decls)
     }
 
@@ -445,6 +453,7 @@ pub fn basic_blocks_local_decls_mut_and_var_debug_info(
         self.predecessor_cache.invalidate();
         self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
+        self.postorder_cache.invalidate();
         (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
     }
 
@@ -728,14 +737,14 @@ pub enum BorrowKind {
     /// This is used when lowering matches: when matching on a place we want to
     /// ensure that place have the same value from the start of the match until
     /// an arm is selected. This prevents this code from compiling:
-    ///
-    ///     let mut x = &Some(0);
-    ///     match *x {
-    ///         None => (),
-    ///         Some(_) if { x = &None; false } => (),
-    ///         Some(_) => (),
-    ///     }
-    ///
+    /// ```compile_fail,E0510
+    /// let mut x = &Some(0);
+    /// match *x {
+    ///     None => (),
+    ///     Some(_) if { x = &None; false } => (),
+    ///     Some(_) => (),
+    /// }
+    /// ```
     /// This can't be a shared borrow because mutably borrowing (*x as Some).0
     /// should not prevent `if let None = x { ... }`, for example, because the
     /// mutating `(*x as Some).0` can't affect the discriminant of `x`.
@@ -746,27 +755,30 @@ pub enum BorrowKind {
     /// cannot currently be expressed by the user and is used only in
     /// implicit closure bindings. It is needed when the closure is
     /// borrowing or mutating a mutable referent, e.g.:
-    ///
-    ///     let x: &mut isize = ...;
-    ///     let y = || *x += 5;
-    ///
+    /// ```
+    /// let mut z = 3;
+    /// let x: &mut isize = &mut z;
+    /// let y = || *x += 5;
+    /// ```
     /// If we were to try to translate this closure into a more explicit
     /// form, we'd encounter an error with the code as written:
-    ///
-    ///     struct Env { x: & &mut isize }
-    ///     let x: &mut isize = ...;
-    ///     let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
-    ///     fn fn_ptr(env: &mut Env) { **env.x += 5; }
-    ///
+    /// ```compile_fail,E0594
+    /// struct Env<'a> { x: &'a &'a mut isize }
+    /// let mut z = 3;
+    /// let x: &mut isize = &mut z;
+    /// let y = (&mut Env { x: &x }, fn_ptr);  // Closure is pair of env and fn
+    /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
+    /// ```
     /// This is then illegal because you cannot mutate an `&mut` found
     /// in an aliasable location. To solve, you'd have to translate with
     /// an `&mut` borrow:
-    ///
-    ///     struct Env { x: &mut &mut isize }
-    ///     let x: &mut isize = ...;
-    ///     let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
-    ///     fn fn_ptr(env: &mut Env) { **env.x += 5; }
-    ///
+    /// ```compile_fail,E0596
+    /// struct Env<'a> { x: &'a mut &'a mut isize }
+    /// let mut z = 3;
+    /// let x: &mut isize = &mut z;
+    /// let y = (&mut Env { x: &mut x }, fn_ptr); // changed from &x to &mut x
+    /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
+    /// ```
     /// Now the assignment to `**env.x` is legal, but creating a
     /// mutable pointer to `x` is not because `x` is not mutable. We
     /// could fix this by declaring `x` as `let mut x`. This is ok in
@@ -1007,7 +1019,7 @@ pub struct LocalDecl<'tcx> {
     /// ```
     /// fn foo(x: &str) {
     ///     match {
-    ///         match x.parse().unwrap() {
+    ///         match x.parse::<u32>().unwrap() {
     ///             y => y + 2
     ///         }
     ///     } {
@@ -1681,9 +1693,9 @@ pub enum StatementKind<'tcx> {
 
     /// Encodes a user's type ascription. These need to be preserved
     /// intact so that NLL can respect them. For example:
-    ///
-    ///     let a: T = y;
-    ///
+    /// ```ignore (illustrative)
+    /// let a: T = y;
+    /// ```
     /// The effect of this annotation is to relate the type `T_y` of the place `y`
     /// to the user-given type `T`. The effect depends on the specified variance:
     ///
@@ -1976,7 +1988,7 @@ pub enum ProjectionElem<V, T> {
     /// These indices are generated by slice patterns. Easiest to explain
     /// by example:
     ///
-    /// ```
+    /// ```ignore (illustrative)
     /// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
     /// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
     /// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
@@ -2330,7 +2342,10 @@ pub struct SourceScopeLocalData {
 /// validator.
 #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
 pub enum Operand<'tcx> {
-    /// Creates a value by loading the given place. The type of the place must be `Copy`
+    /// Creates a value by loading the given place.
+    ///
+    /// Before drop elaboration, the type of the place must be `Copy`. After drop elaboration there
+    /// is no such requirement.
     Copy(Place<'tcx>),
 
     /// Creates a value by performing loading the place, just like the `Copy` operand.
@@ -2577,8 +2592,6 @@ pub enum Rvalue<'tcx> {
     /// This is different from a normal transmute because dataflow analysis will treat the box as
     /// initialized but its content as uninitialized. Like other pointer casts, this in general
     /// affects alias analysis.
-    ///
-    /// Disallowed after drop elaboration.
     ShallowInitBox(Operand<'tcx>, Ty<'tcx>),
 }
 
@@ -3169,7 +3182,7 @@ fn from_opt_const_arg_anon_const(
 ///
 /// An example:
 ///
-/// ```rust
+/// ```ignore (illustrative)
 /// struct S<'a>((i32, &'a str), String);
 /// let S((_, w): (i32, &'static str), _): S = ...;
 /// //    ------  ^^^^^^^^^^^^^^^^^^^ (1)