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, _) => {
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(),
};
.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))
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,
};
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;
+
+ 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
- ));
+ err.note(&format!(
+ "move occurs because {} has type `{}`, \
+ which does not implement the `Copy` trait",
+ note_msg, ty
+ ));
+ }
}
}
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),
+ );
}
}
}
}
}
+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<String> {
+ 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<String> {
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,
}
place: &Place<'tcx>,
buf: &mut String,
mut autoderef: bool,
+ including_downcast: &IncludingDowncast,
) -> Result<(), ()> {
match *place {
Place::Local(local) => {
}
} 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;
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("..");
// 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(&"[..]");
}
};
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;
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;
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;
};
}
-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));
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");
// 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 } => {
// 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<Local> =
- mbcx.used_mut.iter()
- .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())
- .cloned()
- .collect();
+ let temporary_used_locals: FxHashSet<Local> = 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];
// 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,
}
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();
}
}
);
}
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,
// 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.
}
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);
}
}
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 {
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);
}
// 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));
}
_ => {
}
}
- if self.access_place_error_reported
+ if self
+ .access_place_error_reported
.contains(&(place_span.0.clone(), place_span.1))
{
debug!(
) -> 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;
(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.
}
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
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;
// 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()] {
self.used_mut_upvars.push(field);
}
}
- Operand::Move(Place::Static(..)) |
- Operand::Copy(..) |
- Operand::Constant(..) => {}
+ Operand::Move(Place::Static(..))
+ | Operand::Copy(..)
+ | Operand::Constant(..) => {}
}
}
}
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"));
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,
// `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";
}
}
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");
}
//
// 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));
}
}
// 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);
// 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"),
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 {
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 => {
// `*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,
+ });
}
}
}
// }
// ```
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 {
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();
}
}
}
-
// 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 {
}
pub trait BorrowckErrors<'cx>: Sized + Copy {
- fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'cx>;
+ fn struct_span_err_with_code<S: Into<MultiSpan>>(
+ self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId,
+ ) -> DiagnosticBuilder<'cx>;
- fn struct_span_err<S: Into<MultiSpan>>(self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'cx>;
+ fn struct_span_err<S: Into<MultiSpan>>(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 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 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
+ );
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);
-
- err.span_label(borrow_span, format!("borrow of `{}` occurs here", borrow_desc));
+ 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(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<Span>,
- 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<Span>,
+ 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");
}
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<Span>,
- 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<Span>,
+ 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<Span>,
- 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<Span>,
+ 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<Span>,
- 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<Span>,
+ 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<Span>,
- 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<Span>,
+ 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)
}
/// 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<bool>,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
+ fn cannot_move_out_of_interior_noncopy(
+ self,
+ move_from_span: Span,
+ ty: ty::Ty,
+ is_index: Option<bool>,
+ 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<String>,
+ 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<S: Into<MultiSpan>>(self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'cx>
- {
+ fn struct_span_err_with_code<S: Into<MultiSpan>>(
+ self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId,
+ ) -> DiagnosticBuilder<'cx> {
self.sess.struct_span_err_with_code(sp, msg, code)
}
- fn struct_span_err<S: Into<MultiSpan>>(self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'cx>
- {
+ fn struct_span_err<S: Into<MultiSpan>>(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);
}
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<isize>`, which does not implement the `Copy` trait
+ = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `a.y`
--> $DIR/borrowck-box-insensitivity.rs:108:14
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<isize>`, which does not implement the `Copy` trait
+ = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors
//~| 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]
}
}
LL | | }
| |_________^ value used here after move
|
- = note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
+ = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:9
LL | | }
| |_________^ value borrowed here after move
|
- = note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
+ = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:16
| | value moved here
| value used here after move
|
- = note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
+ = note: move occurs because value has type `std::vec::Vec<bool>`, 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<bool>`, which does not implement the `Copy` trait
+ = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error: aborting due to 6 previous errors
LL | touch(&x); //~ ERROR use of partially moved value: `x`
| ^^ value borrowed here after move
|
- = note: move occurs because `x` has type `Foo<std::string::String>`, 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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
+}
--- /dev/null
+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<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.