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;
/// * [`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`
predecessor_cache: PredecessorCache,
switch_source_cache: SwitchSourceCache,
is_cyclic: GraphIsCyclicCache,
+ postorder_cache: PostorderCache,
pub tainted_by_errors: Option<ErrorGuaranteed>,
}
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();
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();
self.predecessor_cache.invalidate();
self.switch_source_cache.invalidate();
self.is_cyclic.invalidate();
+ self.postorder_cache.invalidate();
&mut self.basic_blocks
}
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)
}
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)
}
/// 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`.
/// 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
/// ```
/// fn foo(x: &str) {
/// match {
- /// match x.parse().unwrap() {
+ /// match x.parse::<u32>().unwrap() {
/// y => y + 2
/// }
/// } {
/// 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:
///
/// 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 },
/// 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.
/// 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>),
}
///
/// An example:
///
-/// ```rust
+/// ```ignore (illustrative)
/// struct S<'a>((i32, &'a str), String);
/// let S((_, w): (i32, &'static str), _): S = ...;
/// // ------ ^^^^^^^^^^^^^^^^^^^ (1)