]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
suggest to add move keyword for generator
[rust.git] / src / librustc_mir / borrow_check / nll / explain_borrow / mod.rs
index ed88b16253584634bb1db1426144ad06cc4f47a8..5354b45f92d0a236dfd90f1cfa5f0d69db94ed34 100644 (file)
@@ -7,7 +7,7 @@
 use crate::borrow_check::{MirBorrowckCtxt, WriteKind};
 use rustc::mir::{
     CastKind, ConstraintCategory, FakeReadCause, Local, Location, Body, Operand, Place, PlaceBase,
-    Projection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
+    Rvalue, Statement, StatementKind, TerminatorKind,
 };
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::adjustment::{PointerCast};
@@ -17,6 +17,7 @@
 
 mod find_use;
 
+#[derive(Debug)]
 pub(in crate::borrow_check) enum BorrowExplanation {
     UsedLater(LaterUseKind, Span),
     UsedLaterInLoop(LaterUseKind, Span),
@@ -35,7 +36,7 @@ pub(in crate::borrow_check) enum BorrowExplanation {
     Unexplained,
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub(in crate::borrow_check) enum LaterUseKind {
     TraitCapture,
     ClosureCapture,
@@ -95,7 +96,7 @@ pub(in crate::borrow_check) fn add_explanation_to_diagnostic<'tcx>(
                 should_note_order,
             } => {
                 let local_decl = &body.local_decls[dropped_local];
-                let (dtor_desc, type_desc) = match local_decl.ty.sty {
+                let (dtor_desc, type_desc) = match local_decl.ty.kind {
                     // If type is an ADT that implements Drop, then
                     // simplify output by reporting just the ADT name.
                     ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => (
@@ -252,7 +253,7 @@ pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
             Some(Cause::LiveVar(local, location)) => {
                 let span = body.source_info(location).span;
                 let spans = self
-                    .move_spans(&Place::from(local), location)
+                    .move_spans(Place::from(local).as_ref(), location)
                     .or_else(|| self.borrow_spans(span, location));
 
                 let borrow_location = location;
@@ -272,7 +273,10 @@ pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
                 let mut should_note_order = false;
                 if body.local_decls[local].name.is_some() {
                     if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
-                        if let Place::Base(PlaceBase::Local(borrowed_local)) = place {
+                        if let Place {
+                            base: PlaceBase::Local(borrowed_local),
+                            projection: box [],
+                        } = place {
                              if body.local_decls[*borrowed_local].name.is_some()
                                 && local != *borrowed_local
                             {
@@ -301,7 +305,8 @@ pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
                             region,
                         );
                     if let Some(region_name) = region_name {
-                        let opt_place_desc = self.describe_place(&borrow.borrowed_place);
+                        let opt_place_desc =
+                            self.describe_place(borrow.borrowed_place.as_ref());
                         BorrowExplanation::MustBeValidFor {
                             category,
                             from_closure,
@@ -489,8 +494,14 @@ fn later_use_kind(
                         // Just point to the function, to reduce the chance of overlapping spans.
                         let function_span = match func {
                             Operand::Constant(c) => c.span,
-                            Operand::Copy(Place::Base(PlaceBase::Local(l))) |
-                            Operand::Move(Place::Base(PlaceBase::Local(l))) => {
+                            Operand::Copy(Place {
+                                base: PlaceBase::Local(l),
+                                projection: box [],
+                            }) |
+                            Operand::Move(Place {
+                                base: PlaceBase::Local(l),
+                                projection: box [],
+                            }) => {
                                 let local_decl = &self.body.local_decls[*l];
                                 if local_decl.name.is_none() {
                                     local_decl.source_info.span
@@ -531,7 +542,10 @@ fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
         // it which simplifies the termination logic.
         let mut queue = vec![location];
         let mut target = if let Some(&Statement {
-            kind: StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _),
+            kind: StatementKind::Assign(box(Place {
+                base: PlaceBase::Local(local),
+                projection: box [],
+            }, _)),
             ..
         }) = stmt
         {
@@ -554,14 +568,10 @@ fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
                 debug!("was_captured_by_trait_object: stmt={:?}", stmt);
 
                 // The only kind of statement that we care about is assignments...
-                if let StatementKind::Assign(place, box rvalue) = &stmt.kind {
-                    let into = match place {
-                        Place::Base(PlaceBase::Local(into)) => into,
-                        Place::Projection(box Projection {
-                            base: Place::Base(PlaceBase::Local(into)),
-                            elem: ProjectionElem::Deref,
-                        }) => into,
-                        _ => {
+                if let StatementKind::Assign(box(place, rvalue)) = &stmt.kind {
+                    let into = match place.local_or_deref_local() {
+                        Some(into) => into,
+                        None => {
                             // Continue at the next location.
                             queue.push(current_location.successor_within_block());
                             continue;
@@ -572,11 +582,17 @@ fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
                         // If we see a use, we should check whether it is our data, and if so
                         // update the place that we're looking for to that new place.
                         Rvalue::Use(operand) => match operand {
-                            Operand::Copy(Place::Base(PlaceBase::Local(from)))
-                            | Operand::Move(Place::Base(PlaceBase::Local(from)))
+                            Operand::Copy(Place {
+                                base: PlaceBase::Local(from),
+                                projection: box [],
+                            })
+                            | Operand::Move(Place {
+                                base: PlaceBase::Local(from),
+                                projection: box [],
+                            })
                                 if *from == target =>
                             {
-                                target = *into;
+                                target = into;
                             }
                             _ => {}
                         },
@@ -585,13 +601,19 @@ fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
                         Rvalue::Cast(
                             CastKind::Pointer(PointerCast::Unsize), operand, ty
                         ) => match operand {
-                            Operand::Copy(Place::Base(PlaceBase::Local(from)))
-                            | Operand::Move(Place::Base(PlaceBase::Local(from)))
+                            Operand::Copy(Place {
+                                base: PlaceBase::Local(from),
+                                projection: box [],
+                            })
+                            | Operand::Move(Place {
+                                base: PlaceBase::Local(from),
+                                projection: box [],
+                            })
                                 if *from == target =>
                             {
                                 debug!("was_captured_by_trait_object: ty={:?}", ty);
                                 // Check the type for a trait object.
-                                return match ty.sty {
+                                return match ty.kind {
                                     // `&dyn Trait`
                                     ty::Ref(_, ty, _) if ty.is_trait() => true,
                                     // `Box<dyn Trait>`
@@ -616,7 +638,10 @@ fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
                 debug!("was_captured_by_trait_object: terminator={:?}", terminator);
 
                 if let TerminatorKind::Call {
-                    destination: Some((Place::Base(PlaceBase::Local(dest)), block)),
+                    destination: Some((Place {
+                        base: PlaceBase::Local(dest),
+                        projection: box [],
+                    }, block)),
                     args,
                     ..
                 } = &terminator.kind
@@ -627,7 +652,10 @@ fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
                     );
                     // Check if one of the arguments to this function is the target place.
                     let found_target = args.iter().any(|arg| {
-                        if let Operand::Move(Place::Base(PlaceBase::Local(potential))) = arg {
+                        if let Operand::Move(Place {
+                            base: PlaceBase::Local(potential),
+                            projection: box [],
+                        }) = arg {
                             *potential == target
                         } else {
                             false