diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 684fd10c8c6..500903c1c3b 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -680,7 +680,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { let mut err = self.cannot_act_on_moved_value(use_span, verb, msg, - &format!("{}", nl), + Some(format!("{}", nl)), Origin::Ast); let need_note = match lp.ty.sty { ty::TypeVariants::TyClosure(id, _) => { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 30be87199eb..44fc67dfa43 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -52,7 +52,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.moved_error_reported.insert(root_place.clone()); - let item_msg = match self.describe_place(place) { + let item_msg = match self.describe_place_with_options(place, IncludingDowncast(true)) { Some(name) => format!("`{}`", name), None => "value".to_owned(), }; @@ -60,7 +60,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .cannot_act_on_uninitialized_variable( span, desired_action.as_noun(), - &self.describe_place(place).unwrap_or("_".to_owned()), + &self + .describe_place_with_options(place, IncludingDowncast(true)) + .unwrap_or("_".to_owned()), Origin::Mir, ) .span_label(span, format!("use of possibly uninitialized {}", item_msg)) @@ -72,14 +74,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span, desired_action.as_noun(), msg, - &self.describe_place(place).unwrap_or("_".to_owned()), + self.describe_place_with_options(&place, IncludingDowncast(true)), Origin::Mir, ); let mut is_loop_move = false; - for moi in mois { + for moi in &mois { let move_msg = ""; //FIXME: add " (into closure)" - let move_span = self.mir.source_info(self.move_data.moves[*moi].source).span; + let move_span = self + .mir + .source_info(self.move_data.moves[**moi].source) + .span; if span == move_span { err.span_label( span, @@ -116,16 +121,23 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }; if needs_note { - let note_msg = match self.describe_place(place) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; + let mpi = self.move_data.moves[*mois[0]].path; + let place = &self.move_data.move_paths[mpi].place; - err.note(&format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty - )); + if let Some(ty) = self.retrieve_type_for_place(place) { + let note_msg = match self + .describe_place_with_options(place, IncludingDowncast(true)) + { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + + err.note(&format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty + )); + } } } @@ -644,8 +656,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let local_decl = &self.mir.local_decls[*local]; if let Some(name) = local_decl.name { if local_decl.can_be_made_mutable() { - err.span_label(local_decl.source_info.span, - format!("consider changing this to `mut {}`", name)); + err.span_label( + local_decl.source_info.span, + format!("consider changing this to `mut {}`", name), + ); } } } @@ -654,12 +668,26 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } +pub(super) struct IncludingDowncast(bool); + impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // End-user visible description of `place` if one can be found. If the // place is a temporary for instance, None will be returned. pub(super) fn describe_place(&self, place: &Place<'tcx>) -> Option { + self.describe_place_with_options(place, IncludingDowncast(false)) + } + + // End-user visible description of `place` if one can be found. If the + // place is a temporary for instance, None will be returned. + // `IncludingDowncast` parameter makes the function return `Err` if `ProjectionElem` is + // `Downcast` and `IncludingDowncast` is true + pub(super) fn describe_place_with_options( + &self, + place: &Place<'tcx>, + including_downcast: IncludingDowncast, + ) -> Option { let mut buf = String::new(); - match self.append_place_to_string(place, &mut buf, false) { + match self.append_place_to_string(place, &mut buf, false, &including_downcast) { Ok(()) => Some(buf), Err(()) => None, } @@ -671,6 +699,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { place: &Place<'tcx>, buf: &mut String, mut autoderef: bool, + including_downcast: &IncludingDowncast, ) -> Result<(), ()> { match *place { Place::Local(local) => { @@ -692,15 +721,33 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } else { if autoderef { - self.append_place_to_string(&proj.base, buf, autoderef)?; + self.append_place_to_string( + &proj.base, + buf, + autoderef, + &including_downcast, + )?; } else { buf.push_str(&"*"); - self.append_place_to_string(&proj.base, buf, autoderef)?; + self.append_place_to_string( + &proj.base, + buf, + autoderef, + &including_downcast, + )?; } } } ProjectionElem::Downcast(..) => { - self.append_place_to_string(&proj.base, buf, autoderef)?; + self.append_place_to_string( + &proj.base, + buf, + autoderef, + &including_downcast, + )?; + if including_downcast.0 { + return Err(()); + } } ProjectionElem::Field(field, _ty) => { autoderef = true; @@ -711,14 +758,24 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { buf.push_str(&name); } else { let field_name = self.describe_field(&proj.base, field); - self.append_place_to_string(&proj.base, buf, autoderef)?; + self.append_place_to_string( + &proj.base, + buf, + autoderef, + &including_downcast, + )?; buf.push_str(&format!(".{}", field_name)); } } ProjectionElem::Index(index) => { autoderef = true; - self.append_place_to_string(&proj.base, buf, autoderef)?; + self.append_place_to_string( + &proj.base, + buf, + autoderef, + &including_downcast, + )?; buf.push_str("["); if let Err(_) = self.append_local_to_string(index, buf) { buf.push_str(".."); @@ -730,7 +787,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Since it isn't possible to borrow an element on a particular index and // then use another while the borrow is held, don't output indices details // to avoid confusing the end-user - self.append_place_to_string(&proj.base, buf, autoderef)?; + self.append_place_to_string( + &proj.base, + buf, + autoderef, + &including_downcast, + )?; buf.push_str(&"[..]"); } }; diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 115f36c149b..6d77364aae0 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -15,13 +15,13 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::hir::map::definitions::DefPathData; use rustc::infer::InferCtxt; -use rustc::ty::{self, ParamEnv, TyCtxt}; -use rustc::ty::query::Providers; use rustc::lint::builtin::UNUSED_MUT; use rustc::mir::{self, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; -use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand}; -use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind}; +use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place}; +use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; +use rustc::ty::query::Providers; +use rustc::ty::{self, ParamEnv, TyCtxt}; use rustc_data_structures::control_flow_graph::dominators::Dominators; use rustc_data_structures::fx::FxHashSet; @@ -33,20 +33,20 @@ use std::rc::Rc; use syntax_pos::Span; -use dataflow::{do_dataflow, DebugFormatted}; +use dataflow::indexes::BorrowIndex; +use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; +use dataflow::move_paths::{IllegalMoveOriginKind, MoveError}; +use dataflow::Borrows; +use dataflow::DataflowResultsConsumer; use dataflow::FlowAtLocation; use dataflow::MoveDataParamEnv; -use dataflow::{DataflowResultsConsumer}; -use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; +use dataflow::{do_dataflow, DebugFormatted}; use dataflow::{EverInitializedPlaces, MovingOutStatements}; -use dataflow::Borrows; -use dataflow::indexes::BorrowIndex; -use dataflow::move_paths::{IllegalMoveOriginKind, MoveError}; -use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; +use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use util::borrowck_errors::{BorrowckErrors, Origin}; use util::collect_writes::FindAssignments; -use self::borrow_set::{BorrowSet, BorrowData}; +use self::borrow_set::{BorrowData, BorrowSet}; use self::flows::Flows; use self::location::LocationTable; use self::prefixes::PrefixSet; @@ -58,9 +58,9 @@ crate mod borrow_set; mod error_reporting; mod flows; mod location; +mod path_utils; crate mod place_ext; mod prefixes; -mod path_utils; mod used_muts; pub(crate) mod nll; @@ -72,10 +72,7 @@ pub fn provide(providers: &mut Providers) { }; } -fn mir_borrowck<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId, -) -> BorrowCheckResult<'tcx> { +fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowCheckResult<'tcx> { let input_mir = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); @@ -103,7 +100,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let tcx = infcx.tcx; let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); - let id = tcx.hir + let id = tcx + .hir .as_local_node_id(def_id) .expect("do_mir_borrowck: non-local DefId"); @@ -138,9 +136,10 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // borrow to provide feedback about why this // was a move rather than a copy. match ty.sty { - ty::TyArray(..) | ty::TySlice(..) => - tcx.cannot_move_out_of_interior_noncopy(span, ty, None, origin), - _ => tcx.cannot_move_out_of(span, "borrowed content", origin) + ty::TyArray(..) | ty::TySlice(..) => { + tcx.cannot_move_out_of_interior_noncopy(span, ty, None, origin) + } + _ => tcx.cannot_move_out_of(span, "borrowed content", origin), } } IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => { @@ -277,16 +276,21 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // Note that this set is expected to be small - only upvars from closures // would have a chance of erroneously adding non-user-defined mutable vars // to the set. - let temporary_used_locals: FxHashSet = - mbcx.used_mut.iter() - .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some()) - .cloned() - .collect(); + let temporary_used_locals: FxHashSet = mbcx + .used_mut + .iter() + .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some()) + .cloned() + .collect(); mbcx.gather_used_muts(temporary_used_locals); debug!("mbcx.used_mut: {:?}", mbcx.used_mut); - for local in mbcx.mir.mut_vars_and_args_iter().filter(|local| !mbcx.used_mut.contains(local)) { + for local in mbcx + .mir + .mut_vars_and_args_iter() + .filter(|local| !mbcx.used_mut.contains(local)) + { if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.source_scope_local_data { let local_decl = &mbcx.mir.local_decls[local]; @@ -297,7 +301,9 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // Skip over locals that begin with an underscore or have no name match local_decl.name { - Some(name) => if name.as_str().starts_with("_") { continue; }, + Some(name) => if name.as_str().starts_with("_") { + continue; + }, None => continue, } @@ -308,10 +314,9 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( UNUSED_MUT, vsi[local_decl.source_info.scope].lint_root, span, - "variable does not need to be mutable" - ) - .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()) - .emit(); + "variable does not need to be mutable", + ).span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()) + .emit(); } } @@ -419,12 +424,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx ); } StatementKind::ReadForMatch(ref place) => { - self.access_place(ContextKind::ReadForMatch.new(location), - (place, span), - (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), - LocalMutationIsAllowed::No, - flow_state, - ); + self.access_place( + ContextKind::ReadForMatch.new(location), + (place, span), + (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), + LocalMutationIsAllowed::No, + flow_state, + ); } StatementKind::SetDiscriminant { ref place, @@ -479,10 +485,10 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx // ignored when consuming results (update to // flow_state already handled). } - StatementKind::Nop | - StatementKind::UserAssertTy(..) | - StatementKind::Validate(..) | - StatementKind::StorageLive(..) => { + StatementKind::Nop + | StatementKind::UserAssertTy(..) + | StatementKind::Validate(..) + | StatementKind::StorageLive(..) => { // `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant // to borrow check. } @@ -596,11 +602,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx use rustc::mir::interpret::EvalErrorKind::BoundsCheck; if let BoundsCheck { ref len, ref index } = *msg { self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state); - self.consume_operand( - ContextKind::Assert.new(loc), - (index, span), - flow_state, - ); + self.consume_operand(ContextKind::Assert.new(loc), (index, span), flow_state); } } @@ -660,8 +662,8 @@ enum MutateMode { WriteAndRead, } -use self::ShallowOrDeep::{Deep, Shallow}; use self::ReadOrWrite::{Activation, Read, Reservation, Write}; +use self::ShallowOrDeep::{Deep, Shallow}; #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum ArtificialField { @@ -795,10 +797,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span: Span, ) { let gcx = self.tcx.global_tcx(); - let drop_field = | - mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, - (index, field): (usize, ty::Ty<'gcx>), - | { + let drop_field = |mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, + (index, field): (usize, ty::Ty<'gcx>)| { let field_ty = gcx.normalize_erasing_regions(mir.param_env, field); let place = drop_place.clone().field(Field::new(index), field_ty); @@ -820,23 +820,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } // Same as above, but for tuples. ty::TyTuple(tys) => { - tys.iter().cloned().enumerate() + tys.iter() + .cloned() + .enumerate() .for_each(|field| drop_field(self, field)); } // Closures also have disjoint fields, but they are only // directly accessed in the body of the closure. ty::TyClosure(def, substs) - if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() - => { - substs.upvar_tys(def, self.tcx).enumerate() + if *drop_place == Place::Local(Local::new(1)) + && !self.mir.upvar_decls.is_empty() => + { + substs + .upvar_tys(def, self.tcx) + .enumerate() .for_each(|field| drop_field(self, field)); } // Generators also have disjoint fields, but they are only // directly accessed in the body of the generator. ty::TyGenerator(def, substs, _) - if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() - => { - substs.upvar_tys(def, self.tcx).enumerate() + if *drop_place == Place::Local(Local::new(1)) + && !self.mir.upvar_decls.is_empty() => + { + substs + .upvar_tys(def, self.tcx) + .enumerate() .for_each(|field| drop_field(self, field)); } _ => { @@ -888,7 +896,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - if self.access_place_error_reported + if self + .access_place_error_reported .contains(&(place_span.0.clone(), place_span.1)) { debug!( @@ -931,10 +940,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ) -> bool { debug!( "check_access_for_conflict(context={:?}, place_span={:?}, sd={:?}, rw={:?})", - context, - place_span, - sd, - rw, + context, place_span, sd, rw, ); let mut error_reported = false; @@ -951,8 +957,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (sd, place_span.0), &borrow_set, flow_state.borrows_in_scope(location), - |this, borrow_index, borrow| - match (rw, borrow.kind) { + |this, borrow_index, borrow| match (rw, borrow.kind) { // Obviously an activation is compatible with its own // reservation (or even prior activating uses of same // borrow); so don't check if they interfere. @@ -989,12 +994,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } ReadKind::Borrow(bk) => { error_reported = true; - this.report_conflicting_borrow( - context, - place_span, - bk, - &borrow, - ) + this.report_conflicting_borrow(context, place_span, bk, &borrow) } } Control::Break @@ -1026,12 +1026,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match kind { WriteKind::MutableBorrow(bk) => { error_reported = true; - this.report_conflicting_borrow( - context, - place_span, - bk, - &borrow, - ) + this.report_conflicting_borrow(context, place_span, bk, &borrow) } WriteKind::StorageDeadOrDrop => { error_reported = true; @@ -1185,7 +1180,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // moved into the closure and subsequently used by the closure, // in order to populate our used_mut set. if let AggregateKind::Closure(def_id, _) = &**aggregate_kind { - let BorrowCheckResult { used_mut_upvars, .. } = self.tcx.mir_borrowck(*def_id); + let BorrowCheckResult { + used_mut_upvars, .. + } = self.tcx.mir_borrowck(*def_id); debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars); for field in used_mut_upvars { match operands[field.index()] { @@ -1197,9 +1194,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.used_mut_upvars.push(field); } } - Operand::Move(Place::Static(..)) | - Operand::Copy(..) | - Operand::Constant(..) => {} + Operand::Move(Place::Static(..)) + | Operand::Copy(..) + | Operand::Constant(..) => {} } } } @@ -1280,7 +1277,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Place::Static(statik) => { // Thread-locals might be dropped after the function exits, but // "true" statics will never be. - let is_thread_local = self.tcx + let is_thread_local = self + .tcx .get_attrs(statik.def_id) .iter() .any(|attr| attr.check_name("thread_local")); @@ -1676,8 +1674,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique)) | Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) | Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique)) - | Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) => - { + | Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) => { let is_local_mutation_allowed = match borrow_kind { BorrowKind::Unique => LocalMutationIsAllowed::Yes, BorrowKind::Mut { .. } => is_local_mutation_allowed, @@ -1747,28 +1744,33 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // `act` and `acted_on` are strings that let us abstract over // the verbs used in some diagnostic messages. - let act; let acted_on; + let act; + let acted_on; match error_access { AccessKind::Mutate => { let item_msg = match the_place_err { Place::Projection(box Projection { base: _, - elem: ProjectionElem::Deref } - ) => match self.describe_place(place) { - Some(description) => - format!("`{}` which is behind a `&` reference", description), + elem: ProjectionElem::Deref, + }) => match self.describe_place(place) { + Some(description) => { + format!("`{}` which is behind a `&` reference", description) + } None => format!("data in a `&` reference"), }, _ => item_msg, }; err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir); - act = "assign"; acted_on = "written"; + act = "assign"; + acted_on = "written"; } AccessKind::MutableBorrow => { - err = self.tcx + err = self + .tcx .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir); - act = "borrow as mutable"; acted_on = "borrowed as mutable"; + act = "borrow as mutable"; + acted_on = "borrowed as mutable"; } } @@ -1783,23 +1785,27 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let local_decl = &self.mir.local_decls[*local]; assert_eq!(local_decl.mutability, Mutability::Not); - err.span_label(span, format!("cannot {ACT}", ACT=act)); - err.span_suggestion(local_decl.source_info.span, - "consider changing this to be mutable", - format!("mut {}", local_decl.name.unwrap())); + err.span_label(span, format!("cannot {ACT}", ACT = act)); + err.span_suggestion( + local_decl.source_info.span, + "consider changing this to be mutable", + format!("mut {}", local_decl.name.unwrap()), + ); } // complete hack to approximate old AST-borrowck // diagnostic: if the span starts with a mutable borrow of // a local variable, then just suggest the user remove it. - Place::Local(_) if { - if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { - snippet.starts_with("&mut ") - } else { - false - } - } => { - err.span_label(span, format!("cannot {ACT}", ACT=act)); + Place::Local(_) + if { + if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { + snippet.starts_with("&mut ") + } else { + false + } + } => + { + err.span_label(span, format!("cannot {ACT}", ACT = act)); err.span_label(span, "try removing `&mut` here"); } @@ -1808,29 +1814,40 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // // FIXME: can this case be generalized to work for an // arbitrary base for the projection? - Place::Projection(box Projection { base: Place::Local(local), - elem: ProjectionElem::Deref }) - if self.mir.local_decls[*local].is_nonref_binding() => + Place::Projection(box Projection { + base: Place::Local(local), + elem: ProjectionElem::Deref, + }) if self.mir.local_decls[*local].is_nonref_binding() => { let (err_help_span, suggested_code) = find_place_to_suggest_ampmut(self.tcx, self.mir, *local); - err.span_suggestion(err_help_span, - "consider changing this to be a mutable reference", - suggested_code); + err.span_suggestion( + err_help_span, + "consider changing this to be a mutable reference", + suggested_code, + ); let local_decl = &self.mir.local_decls[*local]; if let Some(name) = local_decl.name { err.span_label( - span, format!("`{NAME}` is a `&` reference, \ - so the data it refers to cannot be {ACTED_ON}", - NAME=name, ACTED_ON=acted_on)); + span, + format!( + "`{NAME}` is a `&` reference, \ + so the data it refers to cannot be {ACTED_ON}", + NAME = name, + ACTED_ON = acted_on + ), + ); } else { - err.span_label(span, format!("cannot {ACT} through `&`-reference", ACT=act)); + err.span_label( + span, + format!("cannot {ACT} through `&`-reference", ACT = act), + ); } } _ => { - err.span_label(span, format!("cannot {ACT}", ACT=act)); + err.span_label(span, format!("cannot {ACT}", ACT = act)); } } @@ -1852,10 +1869,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // for example, if the RHS is present and the Type is not, then the type is going to // be inferred *from* the RHS, which means we should highlight that (and suggest // that they borrow the RHS mutably). - fn find_place_to_suggest_ampmut<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, - mir: &Mir<'tcx>, - local: Local) -> (Span, String) - { + fn find_place_to_suggest_ampmut<'cx, 'gcx, 'tcx>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + mir: &Mir<'tcx>, + local: Local, + ) -> (Span, String) { // This implementation attempts to emulate AST-borrowck prioritization // by trying (3.), then (2.) and finally falling back on (1.). let locations = mir.find_assignments(local); @@ -1877,7 +1895,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // if this is a variable binding with an explicit type, // try to highlight that for the suggestion. Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm { - opt_ty_info: Some(ty_span), .. }))) => ty_span, + opt_ty_info: Some(ty_span), + .. + }))) => ty_span, Some(ClearCrossCrate::Clear) => bug!("saw cleared local state"), @@ -1896,7 +1916,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn add_used_mut<'d>( &mut self, root_place: RootPlace<'d, 'tcx>, - flow_state: &Flows<'cx, 'gcx, 'tcx> + flow_state: &Flows<'cx, 'gcx, 'tcx>, ) { match root_place { RootPlace { @@ -1944,29 +1964,32 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let local = &self.mir.local_decls[local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { - LocalMutationIsAllowed::Yes => { - Ok(RootPlace { - place, - is_local_mutation_allowed: LocalMutationIsAllowed::Yes - }) - } - LocalMutationIsAllowed::ExceptUpvars => { - Ok(RootPlace { - place, - is_local_mutation_allowed: LocalMutationIsAllowed::ExceptUpvars - }) - } + LocalMutationIsAllowed::Yes => Ok(RootPlace { + place, + is_local_mutation_allowed: LocalMutationIsAllowed::Yes, + }), + LocalMutationIsAllowed::ExceptUpvars => Ok(RootPlace { + place, + is_local_mutation_allowed: LocalMutationIsAllowed::ExceptUpvars, + }), LocalMutationIsAllowed::No => Err(place), }, - Mutability::Mut => Ok(RootPlace { place, is_local_mutation_allowed }), + Mutability::Mut => Ok(RootPlace { + place, + is_local_mutation_allowed, + }), } } - Place::Static(ref static_) => + Place::Static(ref static_) => { if self.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) { Err(place) } else { - Ok(RootPlace { place, is_local_mutation_allowed }) - }, + Ok(RootPlace { + place, + is_local_mutation_allowed, + }) + } + } Place::Projection(ref proj) => { match proj.elem { ProjectionElem::Deref => { @@ -2004,7 +2027,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // `*mut` raw pointers are always mutable, regardless of // context. The users have to check by themselves. hir::MutMutable => { - return Ok(RootPlace { place, is_local_mutation_allowed }); + return Ok(RootPlace { + place, + is_local_mutation_allowed, + }); } } } @@ -2063,7 +2089,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // } // ``` let _ = self.is_mutable(&proj.base, is_local_mutation_allowed)?; - Ok(RootPlace { place, is_local_mutation_allowed }) + Ok(RootPlace { + place, + is_local_mutation_allowed, + }) } } } else { @@ -2083,7 +2112,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match *place { Place::Projection(ref proj) => match proj.elem { ProjectionElem::Field(field, _ty) => { - let is_projection_from_ty_closure = proj.base + let is_projection_from_ty_closure = proj + .base .ty(self.mir, self.tcx) .to_ty(self.tcx) .is_closure(); @@ -2185,4 +2215,3 @@ impl ContextKind { } } } - diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index d01b90ad262..be87365bdbb 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -8,15 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::ty::{self, TyCtxt}; use rustc::session::config::BorrowckMode; +use rustc::ty::{self, TyCtxt}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use syntax_pos::{MultiSpan, Span}; use std::fmt; #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Origin { Ast, Mir } +pub enum Origin { + Ast, + Mir, +} impl fmt::Display for Origin { fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { @@ -53,94 +56,130 @@ impl Origin { } pub trait BorrowckErrors<'cx>: Sized + Copy { - fn struct_span_err_with_code>(self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'cx>; + fn struct_span_err_with_code>( + self, + sp: S, + msg: &str, + code: DiagnosticId, + ) -> DiagnosticBuilder<'cx>; - fn struct_span_err>(self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'cx>; + fn struct_span_err>(self, sp: S, msg: &str) -> DiagnosticBuilder<'cx>; /// Cancels the given error if we shouldn't emit errors for a given /// origin in the current mode. /// /// Always make sure that the error gets passed through this function /// before you return it. - fn cancel_if_wrong_origin(self, - diag: DiagnosticBuilder<'cx>, - o: Origin) - -> DiagnosticBuilder<'cx>; + fn cancel_if_wrong_origin( + self, + diag: DiagnosticBuilder<'cx>, + o: Origin, + ) -> DiagnosticBuilder<'cx>; - fn cannot_move_when_borrowed(self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, span, E0505, - "cannot move out of `{}` because it is borrowed{OGN}", - desc, OGN=o); + fn cannot_move_when_borrowed( + self, + span: Span, + desc: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!( + self, + span, + E0505, + "cannot move out of `{}` because it is borrowed{OGN}", + desc, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn cannot_use_when_mutably_borrowed(self, - span: Span, - desc: &str, - borrow_span: Span, - borrow_desc: &str, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, span, E0503, - "cannot use `{}` because it was mutably borrowed{OGN}", - desc, OGN=o); + fn cannot_use_when_mutably_borrowed( + self, + span: Span, + desc: &str, + borrow_span: Span, + borrow_desc: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + span, + E0503, + "cannot use `{}` because it was mutably borrowed{OGN}", + desc, + OGN = o + ); - err.span_label(borrow_span, format!("borrow of `{}` occurs here", borrow_desc)); + err.span_label( + borrow_span, + format!("borrow of `{}` occurs here", borrow_desc), + ); err.span_label(span, format!("use of borrowed `{}`", borrow_desc)); self.cancel_if_wrong_origin(err, o) } - fn cannot_act_on_uninitialized_variable(self, - span: Span, - verb: &str, - desc: &str, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, span, E0381, - "{} of possibly uninitialized variable: `{}`{OGN}", - verb, desc, OGN=o); + fn cannot_act_on_uninitialized_variable( + self, + span: Span, + verb: &str, + desc: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!( + self, + span, + E0381, + "{} of possibly uninitialized variable: `{}`{OGN}", + verb, + desc, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn cannot_mutably_borrow_multiply(self, - new_loan_span: Span, - desc: &str, - opt_via: &str, - old_loan_span: Span, - old_opt_via: &str, - old_load_end_span: Option, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, new_loan_span, E0499, - "cannot borrow `{}`{} as mutable more than once at a time{OGN}", - desc, opt_via, OGN=o); + fn cannot_mutably_borrow_multiply( + self, + new_loan_span: Span, + desc: &str, + opt_via: &str, + old_loan_span: Span, + old_opt_via: &str, + old_load_end_span: Option, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + new_loan_span, + E0499, + "cannot borrow `{}`{} as mutable more than once at a time{OGN}", + desc, + opt_via, + OGN = o + ); if old_loan_span == new_loan_span { // Both borrows are happening in the same place // Meaning the borrow is occurring in a loop - err.span_label(new_loan_span, - format!("mutable borrow starts here in previous \ - iteration of loop{}", opt_via)); + err.span_label( + new_loan_span, + format!( + "mutable borrow starts here in previous \ + iteration of loop{}", + opt_via + ), + ); if let Some(old_load_end_span) = old_load_end_span { err.span_label(old_load_end_span, "mutable borrow ends here"); } } else { - err.span_label(old_loan_span, - format!("first mutable borrow occurs here{}", old_opt_via)); - err.span_label(new_loan_span, - format!("second mutable borrow occurs here{}", opt_via)); + err.span_label( + old_loan_span, + format!("first mutable borrow occurs here{}", old_opt_via), + ); + err.span_label( + new_loan_span, + format!("second mutable borrow occurs here{}", opt_via), + ); if let Some(old_load_end_span) = old_load_end_span { err.span_label(old_load_end_span, "first borrow ends here"); } @@ -148,166 +187,222 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { self.cancel_if_wrong_origin(err, o) } - fn cannot_uniquely_borrow_by_two_closures(self, - new_loan_span: Span, - desc: &str, - old_loan_span: Span, - old_load_end_span: Option, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, new_loan_span, E0524, - "two closures require unique access to `{}` at the same time{OGN}", - desc, OGN=o); - err.span_label( - old_loan_span, - "first closure is constructed here"); - err.span_label( + fn cannot_uniquely_borrow_by_two_closures( + self, + new_loan_span: Span, + desc: &str, + old_loan_span: Span, + old_load_end_span: Option, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, new_loan_span, - "second closure is constructed here"); + E0524, + "two closures require unique access to `{}` at the same time{OGN}", + desc, + OGN = o + ); + err.span_label(old_loan_span, "first closure is constructed here"); + err.span_label(new_loan_span, "second closure is constructed here"); if let Some(old_load_end_span) = old_load_end_span { - err.span_label( - old_load_end_span, - "borrow from first closure ends here"); + err.span_label(old_load_end_span, "borrow from first closure ends here"); } self.cancel_if_wrong_origin(err, o) } - fn cannot_uniquely_borrow_by_one_closure(self, - new_loan_span: Span, - desc_new: &str, - opt_via: &str, - old_loan_span: Span, - noun_old: &str, - old_opt_via: &str, - previous_end_span: Option, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, new_loan_span, E0500, - "closure requires unique access to `{}` but {} is already borrowed{}{OGN}", - desc_new, noun_old, old_opt_via, OGN=o); - err.span_label(new_loan_span, - format!("closure construction occurs here{}", opt_via)); - err.span_label(old_loan_span, - format!("borrow occurs here{}", old_opt_via)); + fn cannot_uniquely_borrow_by_one_closure( + self, + new_loan_span: Span, + desc_new: &str, + opt_via: &str, + old_loan_span: Span, + noun_old: &str, + old_opt_via: &str, + previous_end_span: Option, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + new_loan_span, + E0500, + "closure requires unique access to `{}` but {} is already borrowed{}{OGN}", + desc_new, + noun_old, + old_opt_via, + OGN = o + ); + err.span_label( + new_loan_span, + format!("closure construction occurs here{}", opt_via), + ); + err.span_label(old_loan_span, format!("borrow occurs here{}", old_opt_via)); if let Some(previous_end_span) = previous_end_span { err.span_label(previous_end_span, "borrow ends here"); } self.cancel_if_wrong_origin(err, o) } - fn cannot_reborrow_already_uniquely_borrowed(self, - new_loan_span: Span, - desc_new: &str, - opt_via: &str, - kind_new: &str, - old_loan_span: Span, - old_opt_via: &str, - previous_end_span: Option, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, new_loan_span, E0501, - "cannot borrow `{}`{} as {} because previous closure \ - requires unique access{OGN}", - desc_new, opt_via, kind_new, OGN=o); - err.span_label(new_loan_span, - format!("borrow occurs here{}", opt_via)); - err.span_label(old_loan_span, - format!("closure construction occurs here{}", old_opt_via)); + fn cannot_reborrow_already_uniquely_borrowed( + self, + new_loan_span: Span, + desc_new: &str, + opt_via: &str, + kind_new: &str, + old_loan_span: Span, + old_opt_via: &str, + previous_end_span: Option, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + new_loan_span, + E0501, + "cannot borrow `{}`{} as {} because previous closure \ + requires unique access{OGN}", + desc_new, + opt_via, + kind_new, + OGN = o + ); + err.span_label(new_loan_span, format!("borrow occurs here{}", opt_via)); + err.span_label( + old_loan_span, + format!("closure construction occurs here{}", old_opt_via), + ); if let Some(previous_end_span) = previous_end_span { err.span_label(previous_end_span, "borrow from closure ends here"); } self.cancel_if_wrong_origin(err, o) } - fn cannot_reborrow_already_borrowed(self, - span: Span, - desc_new: &str, - msg_new: &str, - kind_new: &str, - old_span: Span, - noun_old: &str, - kind_old: &str, - msg_old: &str, - old_load_end_span: Option, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, span, E0502, - "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}", - desc_new, msg_new, kind_new, noun_old, kind_old, msg_old, OGN=o); + fn cannot_reborrow_already_borrowed( + self, + span: Span, + desc_new: &str, + msg_new: &str, + kind_new: &str, + old_span: Span, + noun_old: &str, + kind_old: &str, + msg_old: &str, + old_load_end_span: Option, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + span, + E0502, + "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}", + desc_new, + msg_new, + kind_new, + noun_old, + kind_old, + msg_old, + OGN = o + ); err.span_label(span, format!("{} borrow occurs here{}", kind_new, msg_new)); - err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, msg_old)); + err.span_label( + old_span, + format!("{} borrow occurs here{}", kind_old, msg_old), + ); if let Some(old_load_end_span) = old_load_end_span { err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old)); } self.cancel_if_wrong_origin(err, o) } - fn cannot_assign_to_borrowed(self, span: Span, borrow_span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, span, E0506, - "cannot assign to `{}` because it is borrowed{OGN}", - desc, OGN=o); + fn cannot_assign_to_borrowed( + self, + span: Span, + borrow_span: Span, + desc: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + span, + E0506, + "cannot assign to `{}` because it is borrowed{OGN}", + desc, + OGN = o + ); err.span_label(borrow_span, format!("borrow of `{}` occurs here", desc)); - err.span_label(span, format!("assignment to borrowed `{}` occurs here", desc)); + err.span_label( + span, + format!("assignment to borrowed `{}` occurs here", desc), + ); self.cancel_if_wrong_origin(err, o) } - fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, span, E0504, - "cannot move `{}` into closure because it is borrowed{OGN}", - desc, OGN=o); + fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!( + self, + span, + E0504, + "cannot move `{}` into closure because it is borrowed{OGN}", + desc, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn cannot_reassign_immutable(self, span: Span, desc: &str, is_arg: bool, o: Origin) - -> DiagnosticBuilder<'cx> - { + fn cannot_reassign_immutable( + self, + span: Span, + desc: &str, + is_arg: bool, + o: Origin, + ) -> DiagnosticBuilder<'cx> { let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" }; - let err = struct_span_err!(self, span, E0384, - "cannot assign {} `{}`{OGN}", - msg, desc, OGN=o); + let err = struct_span_err!( + self, + span, + E0384, + "cannot assign {} `{}`{OGN}", + msg, + desc, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn cannot_assign(self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, span, E0594, - "cannot assign to {}{OGN}", - desc, OGN=o); + fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!(self, span, E0594, "cannot assign to {}{OGN}", desc, OGN = o); self.cancel_if_wrong_origin(err, o) } - fn cannot_assign_static(self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder<'cx> - { + fn cannot_assign_static(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> { self.cannot_assign(span, &format!("immutable static item `{}`", desc), o) } - fn cannot_move_out_of(self, move_from_span: Span, move_from_desc: &str, o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, move_from_span, E0507, - "cannot move out of {}{OGN}", - move_from_desc, OGN=o); + fn cannot_move_out_of( + self, + move_from_span: Span, + move_from_desc: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + move_from_span, + E0507, + "cannot move out of {}{OGN}", + move_from_desc, + OGN = o + ); err.span_label( move_from_span, - format!("cannot move out of {}", move_from_desc)); + format!("cannot move out of {}", move_from_desc), + ); self.cancel_if_wrong_origin(err, o) } @@ -315,210 +410,274 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { /// Signal an error due to an attempt to move out of the interior /// of an array or slice. `is_index` is None when error origin /// didn't capture whether there was an indexing operation or not. - fn cannot_move_out_of_interior_noncopy(self, - move_from_span: Span, - ty: ty::Ty, - is_index: Option, - o: Origin) - -> DiagnosticBuilder<'cx> - { + fn cannot_move_out_of_interior_noncopy( + self, + move_from_span: Span, + ty: ty::Ty, + is_index: Option, + o: Origin, + ) -> DiagnosticBuilder<'cx> { let type_name = match (&ty.sty, is_index) { - (&ty::TyArray(_, _), Some(true)) | - (&ty::TyArray(_, _), None) => "array", - (&ty::TySlice(_), _) => "slice", + (&ty::TyArray(_, _), Some(true)) | (&ty::TyArray(_, _), None) => "array", + (&ty::TySlice(_), _) => "slice", _ => span_bug!(move_from_span, "this path should not cause illegal move"), }; - let mut err = struct_span_err!(self, move_from_span, E0508, - "cannot move out of type `{}`, \ - a non-copy {}{OGN}", - ty, type_name, OGN=o); + let mut err = struct_span_err!( + self, + move_from_span, + E0508, + "cannot move out of type `{}`, \ + a non-copy {}{OGN}", + ty, + type_name, + OGN = o + ); err.span_label(move_from_span, "cannot move out of here"); self.cancel_if_wrong_origin(err, o) } - fn cannot_move_out_of_interior_of_drop(self, - move_from_span: Span, - container_ty: ty::Ty, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, move_from_span, E0509, - "cannot move out of type `{}`, \ - which implements the `Drop` trait{OGN}", - container_ty, OGN=o); + fn cannot_move_out_of_interior_of_drop( + self, + move_from_span: Span, + container_ty: ty::Ty, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + move_from_span, + E0509, + "cannot move out of type `{}`, \ + which implements the `Drop` trait{OGN}", + container_ty, + OGN = o + ); err.span_label(move_from_span, "cannot move out of here"); self.cancel_if_wrong_origin(err, o) } - fn cannot_act_on_moved_value(self, - use_span: Span, - verb: &str, - optional_adverb_for_moved: &str, - moved_path: &str, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, use_span, E0382, - "{} of {}moved value: `{}`{OGN}", - verb, optional_adverb_for_moved, moved_path, OGN=o); + fn cannot_act_on_moved_value( + self, + use_span: Span, + verb: &str, + optional_adverb_for_moved: &str, + moved_path: Option, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let moved_path = moved_path + .map(|mp| format!(": `{}`", mp)) + .unwrap_or("".to_owned()); + + let err = struct_span_err!( + self, + use_span, + E0382, + "{} of {}moved value{}{OGN}", + verb, + optional_adverb_for_moved, + moved_path, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn cannot_partially_reinit_an_uninit_struct(self, - span: Span, - uninit_path: &str, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, - span, - E0383, - "partial reinitialization of uninitialized structure `{}`{OGN}", - uninit_path, OGN=o); + fn cannot_partially_reinit_an_uninit_struct( + self, + span: Span, + uninit_path: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!( + self, + span, + E0383, + "partial reinitialization of uninitialized structure `{}`{OGN}", + uninit_path, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn closure_cannot_assign_to_borrowed(self, - span: Span, - descr: &str, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}", - descr, OGN=o); + fn closure_cannot_assign_to_borrowed( + self, + span: Span, + descr: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!( + self, + span, + E0595, + "closure cannot assign to {}{OGN}", + descr, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn cannot_borrow_path_as_mutable(self, - span: Span, - path: &str, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}", - path, OGN=o); + fn cannot_borrow_path_as_mutable( + self, + span: Span, + path: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!( + self, + span, + E0596, + "cannot borrow {} as mutable{OGN}", + path, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn cannot_borrow_across_generator_yield(self, - span: Span, - yield_span: Span, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, - span, - E0626, - "borrow may still be in use when generator yields{OGN}", - OGN=o); + fn cannot_borrow_across_generator_yield( + self, + span: Span, + yield_span: Span, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + span, + E0626, + "borrow may still be in use when generator yields{OGN}", + OGN = o + ); err.span_label(yield_span, "possible yield occurs here"); self.cancel_if_wrong_origin(err, o) } - fn path_does_not_live_long_enough(self, - span: Span, - path: &str, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}", - path, OGN=o); + fn path_does_not_live_long_enough( + self, + span: Span, + path: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!( + self, + span, + E0597, + "{} does not live long enough{OGN}", + path, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn lifetime_too_short_for_reborrow(self, - span: Span, - path: &str, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let err = struct_span_err!(self, span, E0598, - "lifetime of {} is too short to guarantee \ - its contents can be safely reborrowed{OGN}", - path, OGN=o); + fn lifetime_too_short_for_reborrow( + self, + span: Span, + path: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let err = struct_span_err!( + self, + span, + E0598, + "lifetime of {} is too short to guarantee \ + its contents can be safely reborrowed{OGN}", + path, + OGN = o + ); self.cancel_if_wrong_origin(err, o) } - fn cannot_act_on_capture_in_sharable_fn(self, - span: Span, - bad_thing: &str, - help: (Span, &str), - o: Origin) - -> DiagnosticBuilder<'cx> - { + fn cannot_act_on_capture_in_sharable_fn( + self, + span: Span, + bad_thing: &str, + help: (Span, &str), + o: Origin, + ) -> DiagnosticBuilder<'cx> { let (help_span, help_msg) = help; - let mut err = struct_span_err!(self, span, E0387, - "{} in a captured outer variable in an `Fn` closure{OGN}", - bad_thing, OGN=o); + let mut err = struct_span_err!( + self, + span, + E0387, + "{} in a captured outer variable in an `Fn` closure{OGN}", + bad_thing, + OGN = o + ); err.span_help(help_span, help_msg); self.cancel_if_wrong_origin(err, o) } - fn cannot_assign_into_immutable_reference(self, - span: Span, - bad_thing: &str, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}", - bad_thing, OGN=o); + fn cannot_assign_into_immutable_reference( + self, + span: Span, + bad_thing: &str, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + span, + E0389, + "{} in a `&` reference{OGN}", + bad_thing, + OGN = o + ); err.span_label(span, "assignment into an immutable reference"); self.cancel_if_wrong_origin(err, o) } - fn cannot_capture_in_long_lived_closure(self, - closure_span: Span, - borrowed_path: &str, - capture_span: Span, - o: Origin) - -> DiagnosticBuilder<'cx> - { - let mut err = struct_span_err!(self, closure_span, E0373, - "closure may outlive the current function, \ - but it borrows {}, \ - which is owned by the current function{OGN}", - borrowed_path, OGN=o); + fn cannot_capture_in_long_lived_closure( + self, + closure_span: Span, + borrowed_path: &str, + capture_span: Span, + o: Origin, + ) -> DiagnosticBuilder<'cx> { + let mut err = struct_span_err!( + self, + closure_span, + E0373, + "closure may outlive the current function, \ + but it borrows {}, \ + which is owned by the current function{OGN}", + borrowed_path, + OGN = o + ); err.span_label(capture_span, format!("{} is borrowed here", borrowed_path)) - .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path)); + .span_label( + closure_span, + format!("may outlive borrowed value {}", borrowed_path), + ); self.cancel_if_wrong_origin(err, o) } } impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> { - fn struct_span_err_with_code>(self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'cx> - { + fn struct_span_err_with_code>( + self, + sp: S, + msg: &str, + code: DiagnosticId, + ) -> DiagnosticBuilder<'cx> { self.sess.struct_span_err_with_code(sp, msg, code) } - fn struct_span_err>(self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'cx> - { + fn struct_span_err>(self, sp: S, msg: &str) -> DiagnosticBuilder<'cx> { self.sess.struct_span_err(sp, msg) } - fn cancel_if_wrong_origin(self, - mut diag: DiagnosticBuilder<'cx>, - o: Origin) - -> DiagnosticBuilder<'cx> - { + fn cancel_if_wrong_origin( + self, + mut diag: DiagnosticBuilder<'cx>, + o: Origin, + ) -> DiagnosticBuilder<'cx> { if !o.should_emit_errors(self.borrowck_mode()) { self.sess.diagnostic().cancel(&mut diag); } diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr index 1b370567ed1..601f05b499c 100644 --- a/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr +++ b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr @@ -7,7 +7,7 @@ LL | //~^ value moved here LL | let _y = a.y; //~ ERROR use of moved | ^^^ value used here after move | - = note: move occurs because `a.y` has type `std::boxed::Box`, which does not implement the `Copy` trait + = note: move occurs because `a.x` has type `std::boxed::Box`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a.y` --> $DIR/borrowck-box-insensitivity.rs:108:14 @@ -18,7 +18,7 @@ LL | //~^ value moved here LL | let _y = a.y; //~ ERROR use of collaterally moved | ^^^ value used here after move | - = note: move occurs because `a.y` has type `std::boxed::Box`, which does not implement the `Copy` trait + = note: move occurs because `a.x.x` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/issue-41962.rs b/src/test/ui/borrowck/issue-41962.rs index 29481dbe522..2a94e05016d 100644 --- a/src/test/ui/borrowck/issue-41962.rs +++ b/src/test/ui/borrowck/issue-41962.rs @@ -20,7 +20,7 @@ pub fn main(){ //~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382] //~| ERROR use of moved value: `maybe` (Mir) [E0382] //~| ERROR use of moved value: `maybe` (Mir) [E0382] - //~| ERROR use of moved value: `maybe.0` (Mir) [E0382] + //~| ERROR use of moved value (Mir) [E0382] //~| ERROR borrow of moved value: `maybe` (Mir) [E0382] } } diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index e6eb3739d8c..bd5d2a46fd8 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -26,7 +26,7 @@ LL | if let Some(thing) = maybe { LL | | } | |_________^ value used here after move | - = note: move occurs because `maybe` has type `std::option::Option>`, which does not implement the `Copy` trait + = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `maybe` (Mir) --> $DIR/issue-41962.rs:17:9 @@ -38,7 +38,7 @@ LL | if let Some(thing) = maybe { LL | | } | |_________^ value borrowed here after move | - = note: move occurs because `maybe` has type `std::option::Option>`, which does not implement the `Copy` trait + = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait error[E0382]: use of moved value: `maybe` (Mir) --> $DIR/issue-41962.rs:17:16 @@ -49,15 +49,15 @@ LL | if let Some(thing) = maybe { | | value moved here | value used here after move | - = note: move occurs because `maybe` has type `std::option::Option>`, which does not implement the `Copy` trait + = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `maybe.0` (Mir) +error[E0382]: use of moved value (Mir) --> $DIR/issue-41962.rs:17:21 | LL | if let Some(thing) = maybe { | ^^^^^ value moved here in previous iteration of loop | - = note: move occurs because `maybe.0` has type `std::vec::Vec`, which does not implement the `Copy` trait + = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait error: aborting due to 6 previous errors diff --git a/src/test/ui/moves-based-on-type-match-bindings.nll.stderr b/src/test/ui/moves-based-on-type-match-bindings.nll.stderr index 6ebbf670acd..d5b18a6c962 100644 --- a/src/test/ui/moves-based-on-type-match-bindings.nll.stderr +++ b/src/test/ui/moves-based-on-type-match-bindings.nll.stderr @@ -7,7 +7,7 @@ LL | Foo {f} => {} LL | touch(&x); //~ ERROR use of partially moved value: `x` | ^^ value borrowed here after move | - = note: move occurs because `x` has type `Foo`, which does not implement the `Copy` trait + = note: move occurs because `x.f` has type `std::string::String`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/nll/issue-51512.rs b/src/test/ui/nll/issue-51512.rs new file mode 100644 index 00000000000..4543d2ba638 --- /dev/null +++ b/src/test/ui/nll/issue-51512.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(warnings)] +#![feature(nll)] + +fn main() { + let range = 0..1; + let r = range; + let x = range.start; + //~^ ERROR use of moved value: `range.start` [E0382] +} diff --git a/src/test/ui/nll/issue-51512.stderr b/src/test/ui/nll/issue-51512.stderr new file mode 100644 index 00000000000..102de43e5d7 --- /dev/null +++ b/src/test/ui/nll/issue-51512.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `range.start` + --> $DIR/issue-51512.rs:17:13 + | +LL | let r = range; + | ----- value moved here +LL | let x = range.start; + | ^^^^^^^^^^^ value used here after move + | + = note: move occurs because `range` has type `std::ops::Range`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`.