diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 20a0df2a171..87fb0a6b70a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -13,44 +13,44 @@ //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html use graphviz::IntoCow; -use middle::region; -use rustc_data_structures::sync::{Lrc}; -use rustc_data_structures::indexed_vec::{IndexVec, Idx}; -use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators}; -use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors}; -use rustc_data_structures::control_flow_graph::ControlFlowGraph; -use rustc_data_structures::small_vec::SmallVec; -use rustc_serialize as serialize; use hir::def::CtorKind; use hir::def_id::DefId; -use mir::visit::MirVisitable; -use mir::interpret::{Value, Scalar, EvalErrorKind}; -use ty::subst::{Subst, Substs}; -use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt}; -use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use util::ppaux; -use std::slice; use hir::{self, InlineAsm}; -use std::borrow::{Cow}; +use middle::region; +use mir::interpret::{EvalErrorKind, Scalar, Value}; +use mir::visit::MirVisitable; +use rustc_apfloat::ieee::{Double, Single}; +use rustc_apfloat::Float; +use rustc_data_structures::control_flow_graph::dominators::{dominators, Dominators}; +use rustc_data_structures::control_flow_graph::ControlFlowGraph; +use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::small_vec::SmallVec; +use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::ReadGuard; +use rustc_serialize as serialize; +use std::borrow::Cow; use std::fmt::{self, Debug, Formatter, Write}; -use std::{iter, mem, option, u32}; use std::ops::{Index, IndexMut}; +use std::slice; use std::vec::IntoIter; +use std::{iter, mem, option, u32}; use syntax::ast::{self, Name}; use syntax::symbol::InternedString; use syntax_pos::{Span, DUMMY_SP}; -use rustc_apfloat::ieee::{Single, Double}; -use rustc_apfloat::Float; +use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use ty::subst::{Subst, Substs}; +use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt}; +use util::ppaux; pub use mir::interpret::AssertMessage; mod cache; -pub mod tcx; -pub mod visit; -pub mod traversal; pub mod interpret; pub mod mono; +pub mod tcx; +pub mod traversal; +pub mod visit; /// Types for locals type LocalDecls<'tcx> = IndexVec>; @@ -129,27 +129,31 @@ pub struct Mir<'tcx> { pub span: Span, /// A cache for various calculations - cache: cache::Cache + cache: cache::Cache, } /// where execution begins pub const START_BLOCK: BasicBlock = BasicBlock(0); impl<'tcx> Mir<'tcx> { - pub fn new(basic_blocks: IndexVec>, - source_scopes: IndexVec, - source_scope_local_data: ClearCrossCrate>, - promoted: IndexVec>, - yield_ty: Option>, - local_decls: IndexVec>, - arg_count: usize, - upvar_decls: Vec, - span: Span) -> Self - { + pub fn new( + basic_blocks: IndexVec>, + source_scopes: IndexVec, + source_scope_local_data: ClearCrossCrate>, + promoted: IndexVec>, + yield_ty: Option>, + local_decls: IndexVec>, + arg_count: usize, + upvar_decls: Vec, + span: Span, + ) -> Self { // We need `arg_count` locals, and one for the return place - assert!(local_decls.len() >= arg_count + 1, - "expected at least {} locals, got {}", arg_count + 1, local_decls.len()); + assert!( + local_decls.len() >= arg_count + 1, + "expected at least {} locals, got {}", + arg_count + 1, + local_decls.len() + ); Mir { basic_blocks, @@ -164,7 +168,7 @@ impl<'tcx> Mir<'tcx> { upvar_decls, spread_arg: None, span, - cache: cache::Cache::new() + cache: cache::Cache::new(), } } @@ -180,7 +184,9 @@ impl<'tcx> Mir<'tcx> { } #[inline] - pub fn basic_blocks_and_local_decls_mut(&mut self) -> ( + pub fn basic_blocks_and_local_decls_mut( + &mut self, + ) -> ( &mut IndexVec>, &mut LocalDecls<'tcx>, ) { @@ -207,8 +213,10 @@ impl<'tcx> Mir<'tcx> { pub fn local_kind(&self, local: Local) -> LocalKind { let index = local.0 as usize; if index == 0 { - debug_assert!(self.local_decls[local].mutability == Mutability::Mut, - "return place should be mutable"); + debug_assert!( + self.local_decls[local].mutability == Mutability::Mut, + "return place should be mutable" + ); LocalKind::ReturnPointer } else if index < self.arg_count + 1 { @@ -216,8 +224,10 @@ impl<'tcx> Mir<'tcx> { } else if self.local_decls[local].name.is_some() { LocalKind::Var } else { - debug_assert!(self.local_decls[local].mutability == Mutability::Mut, - "temp should be mutable"); + debug_assert!( + self.local_decls[local].mutability == Mutability::Mut, + "temp should be mutable" + ); LocalKind::Temp } @@ -225,8 +235,8 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all temporaries. #[inline] - pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { - (self.arg_count+1..self.local_decls.len()).filter_map(move |index| { + pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { + (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); if self.local_decls[local].is_user_variable.is_some() { None @@ -238,8 +248,8 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all user-declared locals. #[inline] - pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { - (self.arg_count+1..self.local_decls.len()).filter_map(move |index| { + pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { + (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); if self.local_decls[local].is_user_variable.is_some() { Some(local) @@ -251,12 +261,12 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all user-declared mutable arguments and locals. #[inline] - pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator + 'a { (1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); let decl = &self.local_decls[local]; if (decl.is_user_variable.is_some() || index < self.arg_count + 1) - && decl.mutability == Mutability::Mut + && decl.mutability == Mutability::Mut { Some(local) } else { @@ -267,18 +277,18 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all function arguments. #[inline] - pub fn args_iter(&self) -> impl Iterator { + pub fn args_iter(&self) -> impl Iterator { let arg_count = self.arg_count; - (1..arg_count+1).map(Local::new) + (1..arg_count + 1).map(Local::new) } /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all /// locals that are neither arguments nor the return place). #[inline] - pub fn vars_and_temps_iter(&self) -> impl Iterator { + pub fn vars_and_temps_iter(&self) -> impl Iterator { let arg_count = self.arg_count; let local_count = self.local_decls.len(); - (arg_count+1..local_count).map(Local::new) + (arg_count + 1..local_count).map(Local::new) } /// Changes a statement to a nop. This is both faster than deleting instructions and avoids @@ -302,6 +312,19 @@ impl<'tcx> Mir<'tcx> { } } + /// Check if `sub` is a sub scope of `sup` + pub fn is_sub_scope(&self, mut sub: SourceScope, sup: SourceScope) -> bool { + loop { + if sub == sup { + return true; + } + match self.source_scopes[sub].parent_scope { + None => return false, + Some(p) => sub = p, + } + } + } + /// Return the return type, it always return first element from `local_decls` array pub fn return_ty(&self) -> Ty<'tcx> { self.local_decls[RETURN_PLACE].ty @@ -316,7 +339,7 @@ pub enum Safety { /// Unsafe because of an unsafe fn FnUnsafe, /// Unsafe because of an `unsafe` block - ExplicitUnsafe(ast::NodeId) + ExplicitUnsafe(ast::NodeId), } impl_stable_hash_for!(struct Mir<'tcx> { @@ -354,7 +377,7 @@ impl<'tcx> IndexMut for Mir<'tcx> { #[derive(Copy, Clone, Debug)] pub enum ClearCrossCrate { Clear, - Set(T) + Set(T), } impl serialize::UseSpecializedEncodable for ClearCrossCrate {} @@ -370,7 +393,7 @@ pub struct SourceInfo { /// The source scope, keeping track of which bindings can be /// seen by debuginfo, active lint levels, `unsafe {...}`, etc. - pub scope: SourceScope + pub scope: SourceScope, } /////////////////////////////////////////////////////////////////////////// @@ -391,7 +414,6 @@ impl From for hir::Mutability { } } - #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. @@ -438,15 +460,17 @@ pub enum BorrowKind { Mut { /// True if this borrow arose from method-call auto-ref /// (i.e. `adjustment::Adjust::Borrow`) - allow_two_phase_borrow: bool - } + allow_two_phase_borrow: bool, + }, } impl BorrowKind { pub fn allows_two_phase_borrow(&self) -> bool { match *self { BorrowKind::Shared | BorrowKind::Unique => false, - BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, + BorrowKind::Mut { + allow_two_phase_borrow, + } => allow_two_phase_borrow, } } } @@ -641,8 +665,7 @@ impl<'tcx> LocalDecl<'tcx> { /// - `fn foo(x: Type) { ... }`, /// - `let x = ...`, /// - or `match ... { C(x) => ... }` - pub fn can_be_made_mutable(&self) -> bool - { + pub fn can_be_made_mutable(&self) -> bool { match self.is_user_variable { Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), @@ -660,8 +683,7 @@ impl<'tcx> LocalDecl<'tcx> { /// Returns true if local is definitely not a `ref ident` or /// `ref mut ident` binding. (Such bindings cannot be made into /// mutable bindings, but the inverse does not necessarily hold). - pub fn is_nonref_binding(&self) -> bool - { + pub fn is_nonref_binding(&self) -> bool { match self.is_user_variable { Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), @@ -683,7 +705,7 @@ impl<'tcx> LocalDecl<'tcx> { name: None, source_info: SourceInfo { span, - scope: OUTERMOST_SOURCE_SCOPE + scope: OUTERMOST_SOURCE_SCOPE, }, visibility_scope: OUTERMOST_SOURCE_SCOPE, internal: false, @@ -700,7 +722,7 @@ impl<'tcx> LocalDecl<'tcx> { name: None, source_info: SourceInfo { span, - scope: OUTERMOST_SOURCE_SCOPE + scope: OUTERMOST_SOURCE_SCOPE, }, visibility_scope: OUTERMOST_SOURCE_SCOPE, internal: true, @@ -718,11 +740,11 @@ impl<'tcx> LocalDecl<'tcx> { ty: return_ty, source_info: SourceInfo { span, - scope: OUTERMOST_SOURCE_SCOPE + scope: OUTERMOST_SOURCE_SCOPE, }, visibility_scope: OUTERMOST_SOURCE_SCOPE, internal: false, - name: None, // FIXME maybe we do want some name here? + name: None, // FIXME maybe we do want some name here? is_user_variable: None, } } @@ -781,15 +803,13 @@ pub struct BasicBlockData<'tcx> { #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct Terminator<'tcx> { pub source_info: SourceInfo, - pub kind: TerminatorKind<'tcx> + pub kind: TerminatorKind<'tcx>, } #[derive(Clone, RustcEncodable, RustcDecodable)] pub enum TerminatorKind<'tcx> { /// block should have one successor in the graph; we jump there - Goto { - target: BasicBlock, - }, + Goto { target: BasicBlock }, /// operand evaluates to an integer; jump depending on its value /// to one of the targets, and otherwise fallback to `otherwise` @@ -837,7 +857,7 @@ pub enum TerminatorKind<'tcx> { Drop { location: Place<'tcx>, target: BasicBlock, - unwind: Option + unwind: Option, }, /// Drop the Place and assign the new value over it. This ensures @@ -885,7 +905,7 @@ pub enum TerminatorKind<'tcx> { /// Destination for the return value. If some, the call is converging. destination: Option<(Place<'tcx>, BasicBlock)>, /// Cleanups to be done if the call unwinds. - cleanup: Option + cleanup: Option, }, /// Jump to the target if the condition has the expected value, @@ -895,7 +915,7 @@ pub enum TerminatorKind<'tcx> { expected: bool, msg: AssertMessage<'tcx>, target: BasicBlock, - cleanup: Option + cleanup: Option, }, /// A suspend point @@ -956,8 +976,12 @@ impl<'tcx> Terminator<'tcx> { } impl<'tcx> TerminatorKind<'tcx> { - pub fn if_<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, cond: Operand<'tcx>, - t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> { + pub fn if_<'a, 'gcx>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + cond: Operand<'tcx>, + t: BasicBlock, + f: BasicBlock, + ) -> TerminatorKind<'tcx> { static BOOL_SWITCH_FALSE: &'static [u128] = &[0]; TerminatorKind::SwitchInt { discr: cond, @@ -970,91 +994,199 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn successors(&self) -> Successors { use self::TerminatorKind::*; match *self { - Resume | Abort | GeneratorDrop | Return | Unreachable | - Call { destination: None, cleanup: None, .. } => { - None.into_iter().chain(&[]) + Resume + | Abort + | GeneratorDrop + | Return + | Unreachable + | Call { + destination: None, + cleanup: None, + .. + } => None.into_iter().chain(&[]), + Goto { target: ref t } + | Call { + destination: None, + cleanup: Some(ref t), + .. } - Goto { target: ref t } | - Call { destination: None, cleanup: Some(ref t), .. } | - Call { destination: Some((_, ref t)), cleanup: None, .. } | - Yield { resume: ref t, drop: None, .. } | - DropAndReplace { target: ref t, unwind: None, .. } | - Drop { target: ref t, unwind: None, .. } | - Assert { target: ref t, cleanup: None, .. } | - FalseUnwind { real_target: ref t, unwind: None } => { - Some(t).into_iter().chain(&[]) + | Call { + destination: Some((_, ref t)), + cleanup: None, + .. } - Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } | - Yield { resume: ref t, drop: Some(ref u), .. } | - DropAndReplace { target: ref t, unwind: Some(ref u), .. } | - Drop { target: ref t, unwind: Some(ref u), .. } | - Assert { target: ref t, cleanup: Some(ref u), .. } | - FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { - Some(t).into_iter().chain(slice::from_ref(u)) + | Yield { + resume: ref t, + drop: None, + .. } - SwitchInt { ref targets, .. } => { - None.into_iter().chain(&targets[..]) + | DropAndReplace { + target: ref t, + unwind: None, + .. } - FalseEdges { ref real_target, ref imaginary_targets } => { - Some(real_target).into_iter().chain(&imaginary_targets[..]) + | Drop { + target: ref t, + unwind: None, + .. } + | Assert { + target: ref t, + cleanup: None, + .. + } + | FalseUnwind { + real_target: ref t, + unwind: None, + } => Some(t).into_iter().chain(&[]), + Call { + destination: Some((_, ref t)), + cleanup: Some(ref u), + .. + } + | Yield { + resume: ref t, + drop: Some(ref u), + .. + } + | DropAndReplace { + target: ref t, + unwind: Some(ref u), + .. + } + | Drop { + target: ref t, + unwind: Some(ref u), + .. + } + | Assert { + target: ref t, + cleanup: Some(ref u), + .. + } + | FalseUnwind { + real_target: ref t, + unwind: Some(ref u), + } => Some(t).into_iter().chain(slice::from_ref(u)), + SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]), + FalseEdges { + ref real_target, + ref imaginary_targets, + } => Some(real_target).into_iter().chain(&imaginary_targets[..]), } } pub fn successors_mut(&mut self) -> SuccessorsMut { use self::TerminatorKind::*; match *self { - Resume | Abort | GeneratorDrop | Return | Unreachable | - Call { destination: None, cleanup: None, .. } => { - None.into_iter().chain(&mut []) + Resume + | Abort + | GeneratorDrop + | Return + | Unreachable + | Call { + destination: None, + cleanup: None, + .. + } => None.into_iter().chain(&mut []), + Goto { target: ref mut t } + | Call { + destination: None, + cleanup: Some(ref mut t), + .. } - Goto { target: ref mut t } | - Call { destination: None, cleanup: Some(ref mut t), .. } | - Call { destination: Some((_, ref mut t)), cleanup: None, .. } | - Yield { resume: ref mut t, drop: None, .. } | - DropAndReplace { target: ref mut t, unwind: None, .. } | - Drop { target: ref mut t, unwind: None, .. } | - Assert { target: ref mut t, cleanup: None, .. } | - FalseUnwind { real_target: ref mut t, unwind: None } => { - Some(t).into_iter().chain(&mut []) + | Call { + destination: Some((_, ref mut t)), + cleanup: None, + .. } - Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } | - Yield { resume: ref mut t, drop: Some(ref mut u), .. } | - DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } | - Drop { target: ref mut t, unwind: Some(ref mut u), .. } | - Assert { target: ref mut t, cleanup: Some(ref mut u), .. } | - FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { - Some(t).into_iter().chain(slice::from_mut(u)) + | Yield { + resume: ref mut t, + drop: None, + .. } - SwitchInt { ref mut targets, .. } => { - None.into_iter().chain(&mut targets[..]) + | DropAndReplace { + target: ref mut t, + unwind: None, + .. } - FalseEdges { ref mut real_target, ref mut imaginary_targets } => { - Some(real_target).into_iter().chain(&mut imaginary_targets[..]) + | Drop { + target: ref mut t, + unwind: None, + .. } + | Assert { + target: ref mut t, + cleanup: None, + .. + } + | FalseUnwind { + real_target: ref mut t, + unwind: None, + } => Some(t).into_iter().chain(&mut []), + Call { + destination: Some((_, ref mut t)), + cleanup: Some(ref mut u), + .. + } + | Yield { + resume: ref mut t, + drop: Some(ref mut u), + .. + } + | DropAndReplace { + target: ref mut t, + unwind: Some(ref mut u), + .. + } + | Drop { + target: ref mut t, + unwind: Some(ref mut u), + .. + } + | Assert { + target: ref mut t, + cleanup: Some(ref mut u), + .. + } + | FalseUnwind { + real_target: ref mut t, + unwind: Some(ref mut u), + } => Some(t).into_iter().chain(slice::from_mut(u)), + SwitchInt { + ref mut targets, .. + } => None.into_iter().chain(&mut targets[..]), + FalseEdges { + ref mut real_target, + ref mut imaginary_targets, + } => Some(real_target) + .into_iter() + .chain(&mut imaginary_targets[..]), } } pub fn unwind_mut(&mut self) -> Option<&mut Option> { match *self { - TerminatorKind::Goto { .. } | - TerminatorKind::Resume | - TerminatorKind::Abort | - TerminatorKind::Return | - TerminatorKind::Unreachable | - TerminatorKind::GeneratorDrop | - TerminatorKind::Yield { .. } | - TerminatorKind::SwitchInt { .. } | - TerminatorKind::FalseEdges { .. } => { - None - }, - TerminatorKind::Call { cleanup: ref mut unwind, .. } | - TerminatorKind::Assert { cleanup: ref mut unwind, .. } | - TerminatorKind::DropAndReplace { ref mut unwind, .. } | - TerminatorKind::Drop { ref mut unwind, .. } | - TerminatorKind::FalseUnwind { ref mut unwind, .. } => { - Some(unwind) + TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::GeneratorDrop + | TerminatorKind::Yield { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::FalseEdges { .. } => None, + TerminatorKind::Call { + cleanup: ref mut unwind, + .. } + | TerminatorKind::Assert { + cleanup: ref mut unwind, + .. + } + | TerminatorKind::DropAndReplace { ref mut unwind, .. } + | TerminatorKind::Drop { ref mut unwind, .. } + | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind), } } } @@ -1080,7 +1212,10 @@ impl<'tcx> BasicBlockData<'tcx> { self.terminator.as_mut().expect("invalid terminator state") } - pub fn retain_statements(&mut self, mut f: F) where F: FnMut(&mut Statement) -> bool { + pub fn retain_statements(&mut self, mut f: F) + where + F: FnMut(&mut Statement) -> bool, + { for s in &mut self.statements { if !f(s) { s.make_nop(); @@ -1089,8 +1224,9 @@ impl<'tcx> BasicBlockData<'tcx> { } pub fn expand_statements(&mut self, mut f: F) - where F: FnMut(&mut Statement<'tcx>) -> Option, - I: iter::TrustedLen> + where + F: FnMut(&mut Statement<'tcx>) -> Option, + I: iter::TrustedLen>, { // Gather all the iterators we'll need to splice in, and their positions. let mut splices: Vec<(usize, I)> = vec![]; @@ -1119,14 +1255,17 @@ impl<'tcx> BasicBlockData<'tcx> { // splicing adding new elements to the end of that gap and moving // existing elements from before the gap to the end of the gap. // For now, this is safe code, emulating a gap but initializing it. - let mut gap = self.statements.len()..self.statements.len()+extra_stmts; - self.statements.resize(gap.end, Statement { - source_info: SourceInfo { - span: DUMMY_SP, - scope: OUTERMOST_SOURCE_SCOPE + let mut gap = self.statements.len()..self.statements.len() + extra_stmts; + self.statements.resize( + gap.end, + Statement { + source_info: SourceInfo { + span: DUMMY_SP, + scope: OUTERMOST_SOURCE_SCOPE, + }, + kind: StatementKind::Nop, }, - kind: StatementKind::Nop - }); + ); for (splice_start, new_stmts) in splices.into_iter().rev() { let splice_end = splice_start + new_stmts.size_hint().0; while gap.end > splice_end { @@ -1170,7 +1309,6 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { } write!(fmt, "]") } - } } } @@ -1183,7 +1321,9 @@ impl<'tcx> TerminatorKind<'tcx> { use self::TerminatorKind::*; match *self { Goto { .. } => write!(fmt, "goto"), - SwitchInt { discr: ref place, .. } => write!(fmt, "switchInt({:?})", place), + SwitchInt { + discr: ref place, .. + } => write!(fmt, "switchInt({:?})", place), Return => write!(fmt, "return"), GeneratorDrop => write!(fmt, "generator_drop"), Resume => write!(fmt, "resume"), @@ -1191,9 +1331,17 @@ impl<'tcx> TerminatorKind<'tcx> { Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value), Unreachable => write!(fmt, "unreachable"), Drop { ref location, .. } => write!(fmt, "drop({:?})", location), - DropAndReplace { ref location, ref value, .. } => - write!(fmt, "replace({:?} <- {:?})", location, value), - Call { ref func, ref args, ref destination, .. } => { + DropAndReplace { + ref location, + ref value, + .. + } => write!(fmt, "replace({:?} <- {:?})", location, value), + Call { + ref func, + ref args, + ref destination, + .. + } => { if let Some((ref destination, _)) = *destination { write!(fmt, "{:?} = ", destination)?; } @@ -1206,13 +1354,18 @@ impl<'tcx> TerminatorKind<'tcx> { } write!(fmt, ")") } - Assert { ref cond, expected, ref msg, .. } => { + Assert { + ref cond, + expected, + ref msg, + .. + } => { write!(fmt, "assert(")?; if !expected { write!(fmt, "!")?; } write!(fmt, "{:?}, \"{:?}\")", cond, msg) - }, + } FalseEdges { .. } => write!(fmt, "falseEdges"), FalseUnwind { .. } => write!(fmt, "falseUnwind"), } @@ -1224,48 +1377,77 @@ impl<'tcx> TerminatorKind<'tcx> { match *self { Return | Resume | Abort | Unreachable | GeneratorDrop => vec![], Goto { .. } => vec!["".into()], - SwitchInt { ref values, switch_ty, .. } => { + SwitchInt { + ref values, + switch_ty, + .. + } => { let size = ty::tls::with(|tcx| { let param_env = ty::ParamEnv::empty(); let switch_ty = tcx.lift_to_global(&switch_ty).unwrap(); tcx.layout_of(param_env.and(switch_ty)).unwrap().size }); - values.iter() - .map(|&u| { - let mut s = String::new(); - print_miri_value( - Value::Scalar(Scalar::Bits { bits: u, defined: size.bits() as u8 }), - switch_ty, - &mut s, - ).unwrap(); - s.into() - }) - .chain(iter::once(String::from("otherwise").into())) - .collect() + values + .iter() + .map(|&u| { + let mut s = String::new(); + print_miri_value( + Value::Scalar(Scalar::Bits { + bits: u, + defined: size.bits() as u8, + }), + switch_ty, + &mut s, + ).unwrap(); + s.into() + }) + .chain(iter::once(String::from("otherwise").into())) + .collect() } - Call { destination: Some(_), cleanup: Some(_), .. } => - vec!["return".into_cow(), "unwind".into_cow()], - Call { destination: Some(_), cleanup: None, .. } => vec!["return".into_cow()], - Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into_cow()], - Call { destination: None, cleanup: None, .. } => vec![], - Yield { drop: Some(_), .. } => - vec!["resume".into_cow(), "drop".into_cow()], + Call { + destination: Some(_), + cleanup: Some(_), + .. + } => vec!["return".into_cow(), "unwind".into_cow()], + Call { + destination: Some(_), + cleanup: None, + .. + } => vec!["return".into_cow()], + Call { + destination: None, + cleanup: Some(_), + .. + } => vec!["unwind".into_cow()], + Call { + destination: None, + cleanup: None, + .. + } => vec![], + Yield { drop: Some(_), .. } => vec!["resume".into_cow(), "drop".into_cow()], Yield { drop: None, .. } => vec!["resume".into_cow()], - DropAndReplace { unwind: None, .. } | - Drop { unwind: None, .. } => vec!["return".into_cow()], - DropAndReplace { unwind: Some(_), .. } | - Drop { unwind: Some(_), .. } => { - vec!["return".into_cow(), "unwind".into_cow()] + DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { + vec!["return".into_cow()] } + DropAndReplace { + unwind: Some(_), .. + } + | Drop { + unwind: Some(_), .. + } => vec!["return".into_cow(), "unwind".into_cow()], Assert { cleanup: None, .. } => vec!["".into()], - Assert { .. } => - vec!["success".into_cow(), "unwind".into_cow()], - FalseEdges { ref imaginary_targets, .. } => { + Assert { .. } => vec!["success".into_cow(), "unwind".into_cow()], + FalseEdges { + ref imaginary_targets, + .. + } => { let mut l = vec!["real".into()]; l.resize(imaginary_targets.len() + 1, "imaginary".into()); l } - FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()], + FalseUnwind { + unwind: Some(_), .. + } => vec!["real".into(), "cleanup".into()], FalseUnwind { unwind: None, .. } => vec!["real".into()], } } @@ -1291,7 +1473,7 @@ impl<'tcx> Statement<'tcx> { pub fn replace_nop(&mut self) -> Self { Statement { source_info: self.source_info, - kind: mem::replace(&mut self.kind, StatementKind::Nop) + kind: mem::replace(&mut self.kind, StatementKind::Nop), } } } @@ -1306,7 +1488,10 @@ pub enum StatementKind<'tcx> { ReadForMatch(Place<'tcx>), /// Write the discriminant for a variant to the enum Place. - SetDiscriminant { place: Place<'tcx>, variant_index: usize }, + SetDiscriminant { + place: Place<'tcx>, + variant_index: usize, + }, /// Start a live range for the storage of the local. StorageLive(Local), @@ -1318,7 +1503,7 @@ pub enum StatementKind<'tcx> { InlineAsm { asm: Box, outputs: Vec>, - inputs: Vec> + inputs: Vec>, }, /// Assert the given places to be valid inhabitants of their type. These statements are @@ -1413,14 +1598,18 @@ impl<'tcx> Debug for Statement<'tcx> { Validate(ref op, ref places) => write!(fmt, "Validate({:?}, {:?})", op, places), StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place), StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place), - SetDiscriminant { ref place, variant_index } => { - write!(fmt, "discriminant({:?}) = {:?}", place, variant_index) - }, - InlineAsm { ref asm, ref outputs, ref inputs } => { - write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs) - }, - UserAssertTy(ref c_ty, ref local) => write!(fmt, "UserAssertTy({:?}, {:?})", - c_ty, local), + SetDiscriminant { + ref place, + variant_index, + } => write!(fmt, "discriminant({:?}) = {:?}", place, variant_index), + InlineAsm { + ref asm, + ref outputs, + ref inputs, + } => write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs), + UserAssertTy(ref c_ty, ref local) => { + write!(fmt, "UserAssertTy({:?}, {:?})", c_ty, local) + } Nop => write!(fmt, "nop"), } } @@ -1532,10 +1721,7 @@ impl<'tcx> Place<'tcx> { } pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> { - Place::Projection(Box::new(PlaceProjection { - base: self, - elem, - })) + Place::Projection(Box::new(PlaceProjection { base: self, elem })) } } @@ -1545,31 +1731,41 @@ impl<'tcx> Debug for Place<'tcx> { match *self { Local(id) => write!(fmt, "{:?}", id), - Static(box self::Static { def_id, ty }) => - write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.item_path_str(def_id)), ty), - Projection(ref data) => - match data.elem { - ProjectionElem::Downcast(ref adt_def, index) => - write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name), - ProjectionElem::Deref => - write!(fmt, "(*{:?})", data.base), - ProjectionElem::Field(field, ty) => - write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty), - ProjectionElem::Index(ref index) => - write!(fmt, "{:?}[{:?}]", data.base, index), - ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => - write!(fmt, "{:?}[{:?} of {:?}]", data.base, offset, min_length), - ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => - write!(fmt, "{:?}[-{:?} of {:?}]", data.base, offset, min_length), - ProjectionElem::Subslice { from, to } if to == 0 => - write!(fmt, "{:?}[{:?}:]", data.base, from), - ProjectionElem::Subslice { from, to } if from == 0 => - write!(fmt, "{:?}[:-{:?}]", data.base, to), - ProjectionElem::Subslice { from, to } => - write!(fmt, "{:?}[{:?}:-{:?}]", data.base, - from, to), - - }, + Static(box self::Static { def_id, ty }) => write!( + fmt, + "({}: {:?})", + ty::tls::with(|tcx| tcx.item_path_str(def_id)), + ty + ), + Projection(ref data) => match data.elem { + ProjectionElem::Downcast(ref adt_def, index) => { + write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name) + } + ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base), + ProjectionElem::Field(field, ty) => { + write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty) + } + ProjectionElem::Index(ref index) => write!(fmt, "{:?}[{:?}]", data.base, index), + ProjectionElem::ConstantIndex { + offset, + min_length, + from_end: false, + } => write!(fmt, "{:?}[{:?} of {:?}]", data.base, offset, min_length), + ProjectionElem::ConstantIndex { + offset, + min_length, + from_end: true, + } => write!(fmt, "{:?}[-{:?} of {:?}]", data.base, offset, min_length), + ProjectionElem::Subslice { from, to } if to == 0 => { + write!(fmt, "{:?}[{:?}:]", data.base, from) + } + ProjectionElem::Subslice { from, to } if from == 0 => { + write!(fmt, "{:?}[:-{:?}]", data.base, to) + } + ProjectionElem::Subslice { from, to } => { + write!(fmt, "{:?}[{:?}:-{:?}]", data.base, from, to) + } + }, } } } @@ -1650,7 +1846,7 @@ impl<'tcx> Operand<'tcx> { pub fn to_copy(&self) -> Self { match *self { Operand::Copy(_) | Operand::Constant(_) => self.clone(), - Operand::Move(ref place) => Operand::Copy(place.clone()) + Operand::Move(ref place) => Operand::Copy(place.clone()), } } } @@ -1775,7 +1971,7 @@ impl BinOp { use self::BinOp::*; match self { Add | Sub | Mul | Shl | Shr => true, - _ => false + _ => false, } } } @@ -1823,7 +2019,9 @@ impl<'tcx> Debug for Rvalue<'tcx> { // When printing regions, add trailing space if necessary. let region = if ppaux::verbose() || ppaux::identify_regions() { let mut region = format!("{}", region); - if region.len() > 0 { region.push(' '); } + if region.len() > 0 { + region.push(' '); + } region } else { // Do not even print 'static @@ -1844,13 +2042,11 @@ impl<'tcx> Debug for Rvalue<'tcx> { match **kind { AggregateKind::Array(_) => write!(fmt, "{:?}", places), - AggregateKind::Tuple => { - match places.len() { - 0 => write!(fmt, "()"), - 1 => write!(fmt, "({:?},)", places[0]), - _ => fmt_tuple(fmt, places), - } - } + AggregateKind::Tuple => match places.len() { + 0 => write!(fmt, "()"), + 1 => write!(fmt, "({:?},)", places[0]), + _ => fmt_tuple(fmt, places), + }, AggregateKind::Adt(adt_def, variant, substs, _) => { let variant_def = &adt_def.variants[variant]; @@ -1904,8 +2100,8 @@ impl<'tcx> Debug for Rvalue<'tcx> { } struct_fmt.field("$state", &places[freevars.len()]); for i in (freevars.len() + 1)..places.len() { - struct_fmt.field(&format!("${}", i - freevars.len() - 1), - &places[i]); + struct_fmt + .field(&format!("${}", i - freevars.len() - 1), &places[i]); } }); @@ -1936,7 +2132,6 @@ pub struct Constant<'tcx> { newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" }); - #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum Literal<'tcx> { Value { @@ -1944,7 +2139,7 @@ pub enum Literal<'tcx> { }, Promoted { // Index into the `promoted` vector of `Mir`. - index: Promoted + index: Promoted, }, } @@ -1962,9 +2157,7 @@ impl<'tcx> Debug for Literal<'tcx> { write!(fmt, "const ")?; fmt_const_val(fmt, value) } - Promoted { index } => { - write!(fmt, "{:?}", index) - } + Promoted { index } => write!(fmt, "{:?}", index), } } } @@ -1980,7 +2173,7 @@ pub fn fmt_const_val(fmt: &mut W, const_val: &ty::Const) -> fmt::Resul } else { write!(fmt, "{:?}:{}", val, const_val.ty) } - }, + } } } @@ -1989,38 +2182,40 @@ pub fn print_miri_value(value: Value, ty: Ty, f: &mut W) -> fmt::Resul match (value, &ty.sty) { (Value::Scalar(Scalar::Bits { bits: 0, .. }), &TyBool) => write!(f, "false"), (Value::Scalar(Scalar::Bits { bits: 1, .. }), &TyBool) => write!(f, "true"), - (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F32)) => - write!(f, "{}f32", Single::from_bits(bits)), - (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F64)) => - write!(f, "{}f64", Double::from_bits(bits)), + (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F32)) => { + write!(f, "{}f32", Single::from_bits(bits)) + } + (Value::Scalar(Scalar::Bits { bits, .. }), &TyFloat(ast::FloatTy::F64)) => { + write!(f, "{}f64", Double::from_bits(bits)) + } (Value::Scalar(Scalar::Bits { bits, .. }), &TyUint(ui)) => write!(f, "{:?}{}", bits, ui), (Value::Scalar(Scalar::Bits { bits, .. }), &TyInt(i)) => { let bit_width = ty::tls::with(|tcx| { - let ty = tcx.lift_to_global(&ty).unwrap(); - tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size.bits() + let ty = tcx.lift_to_global(&ty).unwrap(); + tcx.layout_of(ty::ParamEnv::empty().and(ty)) + .unwrap() + .size + .bits() }); let shift = 128 - bit_width; write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i) - }, - (Value::Scalar(Scalar::Bits { bits, .. }), &TyChar) => - write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()), - (_, &TyFnDef(did, _)) => - write!(f, "{}", item_path_str(did)), - (Value::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: len, .. }), - &TyRef(_, &ty::TyS { sty: TyStr, .. }, _)) => { - ty::tls::with(|tcx| { - match tcx.alloc_map.lock().get(ptr.alloc_id) { - Some(interpret::AllocType::Memory(alloc)) => { - assert_eq!(len as usize as u128, len); - let slice = &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)]; - let s = ::std::str::from_utf8(slice) - .expect("non utf8 str from miri"); - write!(f, "{:?}", s) - } - _ => write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len), - } - }) - }, + } + (Value::Scalar(Scalar::Bits { bits, .. }), &TyChar) => { + write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()) + } + (_, &TyFnDef(did, _)) => write!(f, "{}", item_path_str(did)), + ( + Value::ScalarPair(Scalar::Ptr(ptr), Scalar::Bits { bits: len, .. }), + &TyRef(_, &ty::TyS { sty: TyStr, .. }, _), + ) => ty::tls::with(|tcx| match tcx.alloc_map.lock().get(ptr.alloc_id) { + Some(interpret::AllocType::Memory(alloc)) => { + assert_eq!(len as usize as u128, len); + let slice = &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)]; + let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); + write!(f, "{:?}", s) + } + _ => write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len), + }), _ => write!(f, "{:?}:{}", value, ty), } } @@ -2030,21 +2225,26 @@ fn item_path_str(def_id: DefId) -> String { } impl<'tcx> ControlFlowGraph for Mir<'tcx> { - type Node = BasicBlock; - fn num_nodes(&self) -> usize { self.basic_blocks.len() } + fn num_nodes(&self) -> usize { + self.basic_blocks.len() + } - fn start_node(&self) -> Self::Node { START_BLOCK } + fn start_node(&self) -> Self::Node { + START_BLOCK + } - fn predecessors<'graph>(&'graph self, node: Self::Node) - -> >::Iter - { + fn predecessors<'graph>( + &'graph self, + node: Self::Node, + ) -> >::Iter { self.predecessors_for(node).clone().into_iter() } - fn successors<'graph>(&'graph self, node: Self::Node) - -> >::Iter - { + fn successors<'graph>( + &'graph self, + node: Self::Node, + ) -> >::Iter { self.basic_blocks[node].terminator().successors().cloned() } } @@ -2054,7 +2254,7 @@ impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> { type Iter = IntoIter; } -impl<'a, 'b> GraphSuccessors<'b> for Mir<'a> { +impl<'a, 'b> GraphSuccessors<'b> for Mir<'a> { type Item = BasicBlock; type Iter = iter::Cloned>; } @@ -2086,7 +2286,10 @@ impl Location { /// Note that if this location represents a terminator, then the /// resulting location would be out of bounds and invalid. pub fn successor_within_block(&self) -> Location { - Location { block: self.block, statement_index: self.statement_index + 1 } + Location { + block: self.block, + statement_index: self.statement_index + 1, + } } pub fn dominates(&self, other: Location, dominators: &Dominators) -> bool { @@ -2326,32 +2529,55 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { let kind = match self.kind { Goto { target } => Goto { target: target }, - SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt { + SwitchInt { + ref discr, + switch_ty, + ref values, + ref targets, + } => SwitchInt { discr: discr.fold_with(folder), switch_ty: switch_ty.fold_with(folder), values: values.clone(), - targets: targets.clone() + targets: targets.clone(), }, - Drop { ref location, target, unwind } => Drop { + Drop { + ref location, + target, + unwind, + } => Drop { location: location.fold_with(folder), target, unwind, }, - DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace { + DropAndReplace { + ref location, + ref value, + target, + unwind, + } => DropAndReplace { location: location.fold_with(folder), value: value.fold_with(folder), target, unwind, }, - Yield { ref value, resume, drop } => Yield { + Yield { + ref value, + resume, + drop, + } => Yield { value: value.fold_with(folder), resume: resume, drop: drop, }, - Call { ref func, ref args, ref destination, cleanup } => { - let dest = destination.as_ref().map(|&(ref loc, dest)| { - (loc.fold_with(folder), dest) - }); + Call { + ref func, + ref args, + ref destination, + cleanup, + } => { + let dest = destination + .as_ref() + .map(|&(ref loc, dest)| (loc.fold_with(folder), dest)); Call { func: func.fold_with(folder), @@ -2359,8 +2585,14 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { destination: dest, cleanup, } - }, - Assert { ref cond, expected, ref msg, target, cleanup } => { + } + Assert { + ref cond, + expected, + ref msg, + target, + cleanup, + } => { let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg { EvalErrorKind::BoundsCheck { len: len.fold_with(folder), @@ -2376,15 +2608,26 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { target, cleanup, } - }, + } GeneratorDrop => GeneratorDrop, Resume => Resume, Abort => Abort, Return => Return, Unreachable => Unreachable, - FalseEdges { real_target, ref imaginary_targets } => - FalseEdges { real_target, imaginary_targets: imaginary_targets.clone() }, - FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, + FalseEdges { + real_target, + ref imaginary_targets, + } => FalseEdges { + real_target, + imaginary_targets: imaginary_targets.clone(), + }, + FalseUnwind { + real_target, + unwind, + } => FalseUnwind { + real_target, + unwind, + }, }; Terminator { source_info: self.source_info, @@ -2396,20 +2639,34 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { use mir::TerminatorKind::*; match self.kind { - SwitchInt { ref discr, switch_ty, .. } => - discr.visit_with(visitor) || switch_ty.visit_with(visitor), - Drop { ref location, ..} => location.visit_with(visitor), - DropAndReplace { ref location, ref value, ..} => - location.visit_with(visitor) || value.visit_with(visitor), - Yield { ref value, ..} => - value.visit_with(visitor), - Call { ref func, ref args, ref destination, .. } => { + SwitchInt { + ref discr, + switch_ty, + .. + } => discr.visit_with(visitor) || switch_ty.visit_with(visitor), + Drop { ref location, .. } => location.visit_with(visitor), + DropAndReplace { + ref location, + ref value, + .. + } => location.visit_with(visitor) || value.visit_with(visitor), + Yield { ref value, .. } => value.visit_with(visitor), + Call { + ref func, + ref args, + ref destination, + .. + } => { let dest = if let Some((ref loc, _)) = *destination { loc.visit_with(visitor) - } else { false }; + } else { + false + }; dest || func.visit_with(visitor) || args.visit_with(visitor) - }, - Assert { ref cond, ref msg, .. } => { + } + Assert { + ref cond, ref msg, .. + } => { if cond.visit_with(visitor) { if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg { len.visit_with(visitor) || index.visit_with(visitor) @@ -2419,15 +2676,15 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } else { false } - }, - Goto { .. } | - Resume | - Abort | - Return | - GeneratorDrop | - Unreachable | - FalseEdges { .. } | - FalseUnwind { .. } => false + } + Goto { .. } + | Resume + | Abort + | Return + | GeneratorDrop + | Unreachable + | FalseEdges { .. } + | FalseUnwind { .. } => false, } } } @@ -2436,7 +2693,7 @@ impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match self { &Place::Projection(ref p) => Place::Projection(p.fold_with(folder)), - _ => self.clone() + _ => self.clone(), } } @@ -2455,14 +2712,17 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { match *self { Use(ref op) => Use(op.fold_with(folder)), Repeat(ref op, len) => Repeat(op.fold_with(folder), len), - Ref(region, bk, ref place) => - Ref(region.fold_with(folder), bk, place.fold_with(folder)), + Ref(region, bk, ref place) => { + Ref(region.fold_with(folder), bk, place.fold_with(folder)) + } Len(ref place) => Len(place.fold_with(folder)), Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), - BinaryOp(op, ref rhs, ref lhs) => - BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)), - CheckedBinaryOp(op, ref rhs, ref lhs) => - CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)), + BinaryOp(op, ref rhs, ref lhs) => { + BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) + } + CheckedBinaryOp(op, ref rhs, ref lhs) => { + CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) + } UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)), Discriminant(ref place) => Discriminant(place.fold_with(folder)), NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), @@ -2470,12 +2730,15 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { let kind = box match **kind { AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), AggregateKind::Tuple => AggregateKind::Tuple, - AggregateKind::Adt(def, v, substs, n) => - AggregateKind::Adt(def, v, substs.fold_with(folder), n), - AggregateKind::Closure(id, substs) => - AggregateKind::Closure(id, substs.fold_with(folder)), - AggregateKind::Generator(id, substs, movablity) => - AggregateKind::Generator(id, substs.fold_with(folder), movablity), + AggregateKind::Adt(def, v, substs, n) => { + AggregateKind::Adt(def, v, substs.fold_with(folder), n) + } + AggregateKind::Closure(id, substs) => { + AggregateKind::Closure(id, substs.fold_with(folder)) + } + AggregateKind::Generator(id, substs, movablity) => { + AggregateKind::Generator(id, substs.fold_with(folder), movablity) + } }; Aggregate(kind, fields.fold_with(folder)) } @@ -2490,9 +2753,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor), Len(ref place) => place.visit_with(visitor), Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor), - BinaryOp(_, ref rhs, ref lhs) | - CheckedBinaryOp(_, ref rhs, ref lhs) => - rhs.visit_with(visitor) || lhs.visit_with(visitor), + BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => { + rhs.visit_with(visitor) || lhs.visit_with(visitor) + } UnaryOp(_, ref val) => val.visit_with(visitor), Discriminant(ref place) => place.visit_with(visitor), NullaryOp(_, ty) => ty.visit_with(visitor), @@ -2520,15 +2783,17 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { - Operand::Copy(ref place) | - Operand::Move(ref place) => place.visit_with(visitor), - Operand::Constant(ref c) => c.visit_with(visitor) + Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor), + Operand::Constant(ref c) => c.visit_with(visitor), } } } impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T> - where B: TypeFoldable<'tcx>, V: TypeFoldable<'tcx>, T: TypeFoldable<'tcx> +where + B: TypeFoldable<'tcx>, + V: TypeFoldable<'tcx>, + T: TypeFoldable<'tcx>, { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { use mir::ProjectionElem::*; @@ -2538,24 +2803,20 @@ impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T> Deref => Deref, Field(f, ref ty) => Field(f, ty.fold_with(folder)), Index(ref v) => Index(v.fold_with(folder)), - ref elem => elem.clone() + ref elem => elem.clone(), }; - Projection { - base, - elem, - } + Projection { base, elem } } fn super_visit_with>(&self, visitor: &mut Vs) -> bool { use mir::ProjectionElem::*; - self.base.visit_with(visitor) || - match self.elem { - Field(_, ref ty) => ty.visit_with(visitor), - Index(ref v) => v.visit_with(visitor), - _ => false - } + self.base.visit_with(visitor) || match self.elem { + Field(_, ref ty) => ty.visit_with(visitor), + Index(ref v) => v.visit_with(visitor), + _ => false, + } } } @@ -2573,7 +2834,7 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { Constant { span: self.span.clone(), ty: self.ty.fold_with(folder), - literal: self.literal.fold_with(folder) + literal: self.literal.fold_with(folder), } } fn super_visit_with>(&self, visitor: &mut V) -> bool { @@ -2585,15 +2846,15 @@ impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { Literal::Value { value } => Literal::Value { - value: value.fold_with(folder) + value: value.fold_with(folder), }, - Literal::Promoted { index } => Literal::Promoted { index } + Literal::Promoted { index } => Literal::Promoted { index }, } } fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { Literal::Value { value } => value.visit_with(visitor), - Literal::Promoted { .. } => false + Literal::Promoted { .. } => false, } } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 38d1ac2cb4a..320b933c23e 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -8,20 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax_pos::Span; +use borrow_check::WriteKind; use rustc::middle::region::ScopeTree; use rustc::mir::{BorrowKind, Field, Local, LocalKind, Location, Operand}; use rustc::mir::{Place, ProjectionElem, Rvalue, Statement, StatementKind}; use rustc::ty::{self, RegionKind}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; +use syntax_pos::Span; +use super::borrow_set::BorrowData; use super::{Context, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; -use super::borrow_set::BorrowData; -use dataflow::{FlowAtLocation, MovingOutStatements}; use dataflow::move_paths::MovePathIndex; +use dataflow::{FlowAtLocation, MovingOutStatements}; use util::borrowck_errors::{BorrowckErrors, Origin}; impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { @@ -39,13 +40,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .collect::>(); if mois.is_empty() { - let root_place = self.prefixes(&place, PrefixSet::All) - .last() - .unwrap(); + let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap(); - if self.moved_error_reported - .contains(&root_place.clone()) - { + if self.moved_error_reported.contains(&root_place.clone()) { debug!( "report_use_of_moved_or_uninitialized place: error about {:?} suppressed", root_place @@ -53,8 +50,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { return; } - self.moved_error_reported - .insert(root_place.clone()); + self.moved_error_reported.insert(root_place.clone()); let item_msg = match self.describe_place(place) { Some(name) => format!("`{}`", name), @@ -162,7 +158,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { format!("borrow of {} occurs here", borrow_msg), ); err.span_label(span, format!("move out of {} occurs here", value_msg)); - self.explain_why_borrow_contains_point(context, borrow, &mut err); + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); err.emit(); } @@ -177,12 +173,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span, &self.describe_place(place).unwrap_or("_".to_owned()), self.retrieve_borrow_span(borrow), - &self.describe_place(&borrow.borrowed_place) + &self + .describe_place(&borrow.borrowed_place) .unwrap_or("_".to_owned()), Origin::Mir, ); - self.explain_why_borrow_contains_point(context, borrow, &mut err); + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); err.emit(); } @@ -286,8 +283,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "mutable", ) { (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) - | (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => { - tcx.cannot_reborrow_already_borrowed( + | (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => tcx + .cannot_reborrow_already_borrowed( span, &desc_place, "", @@ -298,11 +295,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "", None, Origin::Mir, - ) - } + ), - (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => { - tcx.cannot_mutably_borrow_multiply( + (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => tcx + .cannot_mutably_borrow_multiply( span, &desc_place, "", @@ -310,18 +306,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "", None, Origin::Mir, - ) - } + ), - (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => { - tcx.cannot_uniquely_borrow_by_two_closures( + (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => tcx + .cannot_uniquely_borrow_by_two_closures( span, &desc_place, issued_span, None, Origin::Mir, - ) - } + ), (BorrowKind::Unique, _, _, _, _, _) => tcx.cannot_uniquely_borrow_by_one_closure( span, @@ -334,8 +328,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Origin::Mir, ), - (BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => { - tcx.cannot_reborrow_already_uniquely_borrowed( + (BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => tcx + .cannot_reborrow_already_uniquely_borrowed( span, &desc_place, "", @@ -344,11 +338,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "", None, Origin::Mir, - ) - } + ), - (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => { - tcx.cannot_reborrow_already_uniquely_borrowed( + (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => tcx + .cannot_reborrow_already_uniquely_borrowed( span, &desc_place, "", @@ -357,8 +350,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "", None, Origin::Mir, - ) - } + ), (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => unreachable!(), }; @@ -380,7 +372,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - self.explain_why_borrow_contains_point(context, issued_borrow, &mut err); + self.explain_why_borrow_contains_point(context, issued_borrow, None, &mut err); err.emit(); } @@ -389,10 +381,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &mut self, context: Context, borrow: &BorrowData<'tcx>, - drop_span: Span, + place_span: (&Place<'tcx>, Span), + kind: Option, ) { + let drop_span = place_span.1; let scope_tree = self.tcx.region_scope_tree(self.mir_def_id); - let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) + let root_place = self + .prefixes(&borrow.borrowed_place, PrefixSet::All) .last() .unwrap(); @@ -402,7 +397,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => drop_span, }; - if self.access_place_error_reported + if self + .access_place_error_reported .contains(&(root_place.clone(), borrow_span)) { debug!( @@ -450,6 +446,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, borrow_span, proper_span, + kind.map(|k| (k, place_span.0)), ); } (RegionKind::ReEarlyBound(_), None) @@ -471,8 +468,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { | (RegionKind::ReClosureBound(_), _) | (RegionKind::ReCanonical(_), _) | (RegionKind::ReErased, _) => { - span_bug!(drop_span, "region {:?} does not make sense in this context", - borrow.region); + span_bug!( + drop_span, + "region {:?} does not make sense in this context", + borrow.region + ); } } } @@ -495,7 +495,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, format!("`{}` dropped here while still borrowed", name), ); - self.explain_why_borrow_contains_point(context, borrow, &mut err); + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); err.emit(); } @@ -517,7 +517,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "temporary value dropped here while still borrowed", ); err.note("consider using a `let` binding to increase its lifetime"); - self.explain_why_borrow_contains_point(context, borrow, &mut err); + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); err.emit(); } @@ -530,6 +530,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span: Span, borrow_span: Span, _proper_span: Span, + kind_place: Option<(WriteKind, &Place<'tcx>)>, ) { debug!( "report_unscoped_local_value_does_not_live_long_enough(\ @@ -544,7 +545,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, "borrowed value only lives until here"); - self.explain_why_borrow_contains_point(context, borrow, &mut err); + self.explain_why_borrow_contains_point(context, borrow, kind_place, &mut err); err.emit(); } @@ -570,7 +571,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(proper_span, "temporary value does not live long enough"); err.span_label(drop_span, "temporary value only lives until here"); - self.explain_why_borrow_contains_point(context, borrow, &mut err); + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); err.emit(); } @@ -588,7 +589,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Origin::Mir, ); - self.explain_why_borrow_contains_point(context, loan, &mut err); + self.explain_why_borrow_contains_point(context, loan, None, &mut err); err.emit(); } @@ -759,9 +760,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Place::Static(ref static_) => self.describe_field_from_ty(&static_.ty, field), Place::Projection(ref proj) => match proj.elem { ProjectionElem::Deref => self.describe_field(&proj.base, field), - ProjectionElem::Downcast(def, variant_index) => { - format!("{}", def.variants[variant_index].fields[field.index()].ident) - } + ProjectionElem::Downcast(def, variant_index) => format!( + "{}", + def.variants[variant_index].fields[field.index()].ident + ), ProjectionElem::Field(_, field_type) => { self.describe_field_from_ty(&field_type, field) } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 122b2df4766..3d3275a6b17 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1050,7 +1050,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { this.report_borrowed_value_does_not_live_long_enough( context, borrow, - place_span.1, + place_span, + Some(kind), ); } WriteKind::Mutate => { @@ -1328,7 +1329,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.report_borrowed_value_does_not_live_long_enough( context, borrow, - span, + (place, span), + None, ) } } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 2807a4e8857..4f37b338e92 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::nll::region_infer::{Cause, RegionInferenceContext}; -use borrow_check::{Context, MirBorrowckCtxt}; use borrow_check::borrow_set::BorrowData; +use borrow_check::nll::region_infer::{Cause, RegionInferenceContext}; +use borrow_check::{Context, MirBorrowckCtxt, WriteKind}; use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor}; -use rustc::mir::{Local, Location, Mir}; +use rustc::mir::{Local, Location, Mir, Place}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::DiagnosticBuilder; use util::liveness::{self, DefUse, LivenessMode}; @@ -22,11 +22,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// point from `context`. This is key for the "3-point errors" /// [described in the NLL RFC][d]. /// + /// # Parameters + /// + /// - `borrow`: the borrow in question + /// - `context`: where the borrow occurs + /// - `kind_place`: if Some, this describes the statement that triggered the error. + /// - first half is the kind of write, if any, being performed + /// - second half is the place being accessed + /// - `err`: where the error annotations are going to be added + /// /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points pub(in borrow_check) fn explain_why_borrow_contains_point( &mut self, context: Context, borrow: &BorrowData<'tcx>, + kind_place: Option<(WriteKind, &Place<'tcx>)>, err: &mut DiagnosticBuilder<'_>, ) { let regioncx = &&self.nonlexical_regioncx; @@ -35,58 +45,68 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let borrow_region_vid = regioncx.to_region_vid(borrow.region); if let Some(cause) = regioncx.why_region_contains_point(borrow_region_vid, context.loc) { match cause { - Cause::LiveVar(local, location) => { - match find_regular_use(mir, regioncx, borrow, location, local) { - Some(p) => { + Cause::LiveVar(local, location) => match find_regular_use( + mir, regioncx, borrow, location, local, + ) { + Some(p) => { + err.span_label(mir.source_info(p).span, format!("borrow later used here")); + } + + None => { + span_bug!( + mir.source_info(context.loc).span, + "Cause should end in a LiveVar" + ); + } + }, + + Cause::DropVar(local, location) => match find_drop_use( + mir, regioncx, borrow, location, local, + ) { + Some(p) => match &mir.local_decls[local].name { + Some(local_name) => { err.span_label( mir.source_info(p).span, - format!("borrow later used here"), + format!("borrow later used here, when `{}` is dropped", local_name), ); - } - None => { - span_bug!( - mir.source_info(context.loc).span, - "Cause should end in a LiveVar" - ); - } - } - } + if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place { + if let Place::Local(borrowed_local) = place { + let dropped_local_scope = + mir.local_decls[local].visibility_scope; + let borrowed_local_scope = + mir.local_decls[*borrowed_local].visibility_scope; - Cause::DropVar(local, location) => { - match find_drop_use(mir, regioncx, borrow, location, local) { - Some(p) => match &mir.local_decls[local].name { - Some(local_name) => { - err.span_label( - mir.source_info(p).span, - format!( - "borrow later used here, when `{}` is dropped", - local_name - ), - ); + if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) { + err.note( + "values in a scope are dropped \ + in the opposite order they are defined", + ); + } + } } - None => { - err.span_label( - mir.local_decls[local].source_info.span, - "borrow may end up in a temporary, created here", - ); - - err.span_label( - mir.source_info(p).span, - "temporary later dropped here, \ - potentially using the reference", - ); - } - }, - + } None => { - span_bug!( - mir.source_info(context.loc).span, - "Cause should end in a DropVar" + err.span_label( + mir.local_decls[local].source_info.span, + "borrow may end up in a temporary, created here", + ); + + err.span_label( + mir.source_info(p).span, + "temporary later dropped here, \ + potentially using the reference", ); } + }, + + None => { + span_bug!( + mir.source_info(context.loc).span, + "Cause should end in a DropVar" + ); } - } + }, Cause::UniversalRegion(region_vid) => { if let Some(region) = regioncx.to_error_region(region_vid) { @@ -185,15 +205,12 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> { ..p }); } else { - stack.extend( - block_data - .terminator() - .successors() - .map(|&basic_block| Location { - statement_index: 0, - block: basic_block, - }), - ); + stack.extend(block_data.terminator().successors().map(|&basic_block| { + Location { + statement_index: 0, + block: basic_block, + } + })); } } } diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr index 008ecfeabcb..730ace7858b 100644 --- a/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `dt` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr index 233ff198af4..f0df7109ba4 100644 --- a/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `dt` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/dropck/dropck-eyepatch.nll.stderr b/src/test/ui/dropck/dropck-eyepatch.nll.stderr index 7b27ff01f92..2072bc6a756 100644 --- a/src/test/ui/dropck/dropck-eyepatch.nll.stderr +++ b/src/test/ui/dropck/dropck-eyepatch.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `dt` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0597.nll.stderr b/src/test/ui/error-codes/E0597.nll.stderr index 459de1bc00b..172db9ced82 100644 --- a/src/test/ui/error-codes/E0597.nll.stderr +++ b/src/test/ui/error-codes/E0597.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `x` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/generator/dropck.nll.stderr b/src/test/ui/generator/dropck.nll.stderr index 7b68c167d4a..01a53cdd6dd 100644 --- a/src/test/ui/generator/dropck.nll.stderr +++ b/src/test/ui/generator/dropck.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `gen` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `ref_` does not live long enough --> $DIR/dropck.rs:22:11 @@ -26,6 +28,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `gen` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to 2 previous errors diff --git a/src/test/ui/span/dropck-object-cycle.nll.stderr b/src/test/ui/span/dropck-object-cycle.nll.stderr index 64a76399da3..b268f6e3ab0 100644 --- a/src/test/ui/span/dropck-object-cycle.nll.stderr +++ b/src/test/ui/span/dropck-object-cycle.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `m` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr index 2a8ef24307d..86a4f0e13b5 100644 --- a/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr +++ b/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `d1` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `d2` does not live long enough --> $DIR/dropck_direct_cycle_with_drop.rs:46:19 @@ -21,6 +23,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `d1` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to 2 previous errors diff --git a/src/test/ui/span/dropck_misc_variants.nll.stderr b/src/test/ui/span/dropck_misc_variants.nll.stderr index 0eeec8e51be..0eb84e4a7d0 100644 --- a/src/test/ui/span/dropck_misc_variants.nll.stderr +++ b/src/test/ui/span/dropck_misc_variants.nll.stderr @@ -8,6 +8,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `_w` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `v` does not live long enough --> $DIR/dropck_misc_variants.rs:41:27 @@ -20,6 +22,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `_w` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr index 3f18f4d025a..ec1df8aeca1 100644 --- a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr +++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `_d` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr index 79e607bb392..288c196b27b 100644 --- a/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr +++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr @@ -8,6 +8,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `_d` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `d1` does not live long enough --> $DIR/issue-24805-dropck-trait-has-items.rs:53:33 @@ -19,6 +21,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `_d` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `d1` does not live long enough --> $DIR/issue-24805-dropck-trait-has-items.rs:59:20 @@ -30,6 +34,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `_d` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr index 550f9d8b60d..c89e68bcd0a 100644 --- a/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr +++ b/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr @@ -8,6 +8,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `d2` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/span/issue-26656.nll.stderr b/src/test/ui/span/issue-26656.nll.stderr index 64bb83fc782..bea6dc6b3f6 100644 --- a/src/test/ui/span/issue-26656.nll.stderr +++ b/src/test/ui/span/issue-26656.nll.stderr @@ -8,6 +8,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `zook` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/span/issue28498-reject-ex1.nll.stderr b/src/test/ui/span/issue28498-reject-ex1.nll.stderr index c5e7a93c763..3ed13f2653c 100644 --- a/src/test/ui/span/issue28498-reject-ex1.nll.stderr +++ b/src/test/ui/span/issue28498-reject-ex1.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `foo` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr index 25708219bd1..ce9e75b4483 100644 --- a/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr +++ b/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `foo1` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr index 66157096394..fcdc1c3f945 100644 --- a/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr +++ b/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `foo1` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr b/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr index bb9d67983de..6300bb3eacd 100644 --- a/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr +++ b/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `foo1` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to previous error diff --git a/src/test/ui/span/send-is-not-static-std-sync.nll.stderr b/src/test/ui/span/send-is-not-static-std-sync.nll.stderr index d411f0d26f4..6ebbf3e1ec4 100644 --- a/src/test/ui/span/send-is-not-static-std-sync.nll.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync.nll.stderr @@ -63,6 +63,8 @@ LL | } ... LL | } | - borrow later used here, when `tx` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to 6 previous errors diff --git a/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr index 6074199b89a..9d89fac08ff 100644 --- a/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr +++ b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr @@ -9,6 +9,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `v` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `x` does not live long enough --> $DIR/vec_refs_data_with_early_death.rs:27:12 @@ -21,6 +23,8 @@ LL | } | | | borrowed value only lives until here | borrow later used here, when `v` is dropped + | + = note: values in a scope are dropped in the opposite order they are defined error: aborting due to 2 previous errors