FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
};
-use rustc::traits::error_reporting::suggest_constraining_type_param;
use rustc::ty::{self, Ty};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir::def_id::DefId;
use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
use rustc_index::vec::Idx;
+use rustc_infer::traits::error_reporting::suggest_constraining_type_param;
use rustc_span::source_map::DesugaringKind;
use rustc_span::Span;
&mut self,
location: Location,
desired_action: InitializationRequiringAction,
- (moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'cx, 'tcx>, Span),
+ (moved_place, used_place, span): (PlaceRef<'tcx>, PlaceRef<'tcx>, Span),
mpi: MovePathIndex,
) {
debug!(
tcx.hir().get_generics(tcx.closure_base_def_id(self.mir_def_id))
{
suggest_constraining_type_param(
+ tcx,
generics,
&mut err,
¶m.name.as_str(),
"Copy",
tcx.sess.source_map(),
span,
+ None,
);
}
}
(BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => {
first_borrow_desc = "first ";
- self.cannot_mutably_borrow_multiply(
+ let mut err = self.cannot_mutably_borrow_multiply(
span,
&desc_place,
&msg_place,
issued_span,
&msg_borrow,
None,
- )
+ );
+ self.suggest_split_at_mut_if_applicable(
+ &mut err,
+ &place,
+ &issued_borrow.borrowed_place,
+ );
+ err
}
(BorrowKind::Unique, BorrowKind::Unique) => {
err
}
+ fn suggest_split_at_mut_if_applicable(
+ &self,
+ err: &mut DiagnosticBuilder<'_>,
+ place: &Place<'tcx>,
+ borrowed_place: &Place<'tcx>,
+ ) {
+ match (&place.projection[..], &borrowed_place.projection[..]) {
+ ([ProjectionElem::Index(_)], [ProjectionElem::Index(_)]) => {
+ err.help(
+ "consider using `.split_at_mut(position)` or similar method to obtain \
+ two mutable non-overlapping sub-slices",
+ );
+ }
+ _ => {}
+ }
+ }
+
/// Returns the description of the root place for a conflicting borrow and the full
/// descriptions of the places that caused the conflict.
///
cursor = proj_base;
match elem {
- ProjectionElem::Field(field, _) if union_ty(local, proj_base).is_some() => {
- return Some((PlaceRef { local, projection: proj_base }, field));
+ ProjectionElem::Field(field, _)
+ if union_ty(*local, proj_base).is_some() =>
+ {
+ return Some((
+ PlaceRef { local: *local, projection: proj_base },
+ field,
+ ));
}
_ => {}
}
// borrowed place and look for a access to a different field of the same union.
let Place { local, projection } = second_borrowed_place;
- let mut cursor = projection.as_ref();
+ let mut cursor = &projection[..];
while let [proj_base @ .., elem] = cursor {
cursor = proj_base;
if let ProjectionElem::Field(field, _) = elem {
- if let Some(union_ty) = union_ty(local, proj_base) {
+ if let Some(union_ty) = union_ty(*local, proj_base) {
if field != target_field
- && local == target_base.local
+ && *local == target_base.local
&& proj_base == target_base.projection
{
// FIXME when we avoid clone reuse describe_place closure
let describe_base_place = self
- .describe_place(PlaceRef { local, projection: proj_base })
+ .describe_place(PlaceRef {
+ local: *local,
+ projection: proj_base,
+ })
.unwrap_or_else(|| "_".to_owned());
return Some((
let borrow_span = borrow_spans.var_or_use();
assert!(root_place.projection.is_empty());
- let proper_span = self.body.local_decls[*root_place.local].source_info.span;
+ let proper_span = self.body.local_decls[root_place.local].source_info.span;
let root_place_projection = self.infcx.tcx.intern_place_elems(root_place.projection);
if self.access_place_error_reported.contains(&(
- Place { local: *root_place.local, projection: root_place_projection },
+ Place { local: root_place.local, projection: root_place_projection },
borrow_span,
)) {
debug!(
}
self.access_place_error_reported.insert((
- Place { local: *root_place.local, projection: root_place_projection },
+ Place { local: root_place.local, projection: root_place_projection },
borrow_span,
));
let root_place =
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
let local = root_place.local;
- match self.body.local_kind(*local) {
+ match self.body.local_kind(local) {
LocalKind::ReturnPointer | LocalKind::Temp => {
("temporary value".to_string(), "temporary value created here".to_string())
}
GeneratorKind::Async(async_kind) => match async_kind {
AsyncGeneratorKind::Block => "async block",
AsyncGeneratorKind::Closure => "async closure",
- _ => bug!("async block/closure expected, but async funtion found."),
+ _ => bug!("async block/closure expected, but async function found."),
},
GeneratorKind::Gen => "generator",
},
}
_ => bug!(
"report_escaping_closure_capture called with unexpected constraint \
- category: `{:?}`",
+ category: `{:?}`",
category
),
};
) -> DiagnosticBuilder<'cx> {
let tcx = self.infcx.tcx;
- let escapes_from = if tcx.is_closure(self.mir_def_id) {
- let tables = tcx.typeck_tables_of(self.mir_def_id);
- let mir_hir_id = tcx.hir().def_index_to_hir_id(self.mir_def_id.index);
- match tables.node_type(mir_hir_id).kind {
- ty::Closure(..) => "closure",
- ty::Generator(..) => "generator",
- _ => bug!("Closure body doesn't have a closure or generator type"),
- }
- } else {
- "function"
- };
+ let (_, escapes_from) = tcx.article_and_description(self.mir_def_id);
let mut err =
borrowck_errors::borrowed_data_escapes_closure(tcx, escape_span, escapes_from);
err.span_label(
upvar_span,
- format!("`{}` is declared here, outside of the {} body", upvar_name, escapes_from),
+ format!("`{}` declared here, outside of the {} body", upvar_name, escapes_from),
);
err.span_label(borrow_span, format!("borrow is only valid in the {} body", escapes_from));
// there.
let mut mpis = vec![mpi];
let move_paths = &self.move_data.move_paths;
- mpis.extend(move_paths[mpi].parents(move_paths));
+ mpis.extend(move_paths[mpi].parents(move_paths).map(|(mpi, _)| mpi));
for moi in &self.move_data.loc_map[location] {
debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
err.buffer(&mut self.errors_buffer);
}
- fn classify_drop_access_kind(&self, place: PlaceRef<'cx, 'tcx>) -> StorageDeadOrDrop<'tcx> {
+ fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> {
let tcx = self.infcx.tcx;
match place.projection {
[] => StorageDeadOrDrop::LocalStorageDead,
StorageDeadOrDrop::LocalStorageDead
| StorageDeadOrDrop::BoxedStorageDead => {
assert!(
- Place::ty_from(&place.local, proj_base, *self.body, tcx)
- .ty
- .is_box(),
+ Place::ty_from(place.local, proj_base, *self.body, tcx).ty.is_box(),
"Drop of value behind a reference or raw pointer"
);
StorageDeadOrDrop::BoxedStorageDead
StorageDeadOrDrop::Destructor(_) => base_access,
},
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
- let base_ty = Place::ty_from(&place.local, proj_base, *self.body, tcx).ty;
+ let base_ty = Place::ty_from(place.local, proj_base, *self.body, tcx).ty;
match base_ty.kind {
ty::Adt(def, _) if def.has_dtor(tcx) => {
// Report the outermost adt with a destructor
// as the HIR doesn't have full types for closure arguments.
let return_ty = *sig.output().skip_binder();
let mut return_span = fn_decl.output.span();
- if let hir::FunctionRetTy::Return(ty) = &fn_decl.output {
+ if let hir::FnRetTy::Return(ty) = &fn_decl.output {
if let hir::TyKind::Rptr(lifetime, _) = ty.kind {
return_span = lifetime.span;
}