about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorKeith Yeung <kungfukeith11@gmail.com>2018-03-16 02:52:07 -0700
committerKeith Yeung <kungfukeith11@gmail.com>2018-04-28 01:55:25 -0700
commit71d221f29425bf7c87fbc781fcbc5740b00d1c8f (patch)
treeee5ca5b1c9acf87b8c9732fed8c85f08b99b85ed /src
parente3b372f67d9fbfda2818febe3af914d4f4069c6d (diff)
downloadrust-71d221f29425bf7c87fbc781fcbc5740b00d1c8f.tar.gz
rust-71d221f29425bf7c87fbc781fcbc5740b00d1c8f.zip
Determine unused mutable variables based on the 'root' place
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/borrow_check/mod.rs197
1 files changed, 111 insertions, 86 deletions
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 60691d1179a..2498162d10f 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -241,7 +241,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         access_place_error_reported: FxHashSet(),
         reservation_error_reported: FxHashSet(),
         moved_error_reported: FxHashSet(),
-        nonlexical_regioncx: opt_regioncx,
+        nonlexical_regioncx: regioncx,
         used_mut: FxHashSet(),
         used_mut_upvars: SmallVec::new(),
         nonlexical_cause_info: None,
@@ -276,7 +276,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
 
             tcx.struct_span_lint_node(
                 UNUSED_MUT,
-                vsi[source_info.scope].lint_root,
+                vsi[local_decl.syntactic_scope].lint_root,
                 source_info.span,
                 "variable does not need to be mutable"
             )
@@ -1366,7 +1366,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     ) {
         debug!("check_if_reassignment_to_immutable_state({:?})", place);
         // determine if this path has a non-mut owner (and thus needs checking).
-        if let Ok(()) = self.is_mutable(place, LocalMutationIsAllowed::No) {
+        if let Ok(_) = self.is_mutable(place, LocalMutationIsAllowed::No) {
             return;
         }
         debug!(
@@ -1679,27 +1679,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 }
             }
             Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. }))
-            | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => if let Err(place_err) =
-                self.is_mutable(place, is_local_mutation_allowed)
-            {
-                error_reported = true;
-                let item_msg = self.get_default_err_msg(place);
-                let mut err = self.tcx
-                    .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
-                err.span_label(span, "cannot borrow as mutable");
-
-                if place != place_err {
-                    if let Some(name) = self.describe_place(place_err) {
-                        err.note(&format!("the value which is causing this path not to be mutable \
-                                           is...: `{}`", name));
-                    }
-                }
-
-                err.emit();
-            },
-            Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
-                match place {
-                    Place::Local(local) => {
+            | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => {
+                match self.is_mutable(place, is_local_mutation_allowed) {
+                    Ok(Place::Local(local))
+                        if is_local_mutation_allowed != LocalMutationIsAllowed::Yes =>
+                    {
                         // If the local may be initialized, and it is now currently being
                         // mutated, then it is justified to be annotated with the `mut` keyword,
                         // since the mutation may be a possible reassignment.
@@ -1708,77 +1692,118 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             self.used_mut.insert(*local);
                         }
                     }
-                    Place::Projection(ref proj) => {
+                    Ok(Place::Projection(ref proj)) => {
                         if let Some(field) = self.is_upvar_field_projection(&proj.base) {
                             self.used_mut_upvars.push(field);
                         }
                     }
-                    Place::Static(..) => {}
-                }
-                if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) {
-                    error_reported = true;
-                    let mut err_info = None;
-                    match *place_err {
-
-                        Place::Projection(box Projection {
-                        ref base, elem:ProjectionElem::Deref}) => {
-                            match *base {
-                                Place::Local(local) => {
-                                    let locations = self.mir.find_assignments(local);
-                                        if locations.len() > 0 {
-                                            let item_msg = if error_reported {
-                                                self.get_secondary_err_msg(base)
-                                            } else {
-                                                self.get_default_err_msg(place)
-                                            };
-                                            let sp = self.mir.source_info(locations[0]).span;
-                                            let mut to_suggest_span = String::new();
-                                            if let Ok(src) =
-                                                self.tcx.sess.codemap().span_to_snippet(sp) {
-                                                    to_suggest_span = src[1..].to_string();
-                                            };
-                                            err_info = Some((
-                                                    sp,
-                                                    "consider changing this to be a \
-                                                    mutable reference",
-                                                    to_suggest_span,
-                                                    item_msg,
-                                                    self.get_primary_err_msg(base)));
-                                        }
-                                },
-                            _ => {},
-                            }
-                        },
-                        _ => {},
-                    }
+                    Ok(Place::Local(_)) |
+                    Ok(Place::Static(..)) => {}
+                    Err(place_err) => {
+                        error_reported = true;
+                        let item_msg = self.get_default_err_msg(place);
+                        let mut err = self.tcx
+                            .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
+                        err.span_label(span, "cannot borrow as mutable");
 
-                    if let Some((err_help_span,
-                                 err_help_stmt,
-                                 to_suggest_span,
-                                 item_msg,
-                                 sec_span)) = err_info {
-                        let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
-                        err.span_suggestion(err_help_span,
-                                            err_help_stmt,
-                                            format!("&mut {}", to_suggest_span));
-                        if place != place_err {
-                            err.span_label(span, sec_span);
-                        }
-                        err.emit()
-                    } else {
-                        let item_msg_ = self.get_default_err_msg(place);
-                        let mut err = self.tcx.cannot_assign(span, &item_msg_, Origin::Mir);
-                        err.span_label(span, "cannot mutate");
                         if place != place_err {
                             if let Some(name) = self.describe_place(place_err) {
                                 err.note(&format!("the value which is causing this path not to be \
-                                                   mutable is...: `{}`", name));
+                                    mutable is...: `{}`", name));
                             }
                         }
+
                         err.emit();
                     }
                 }
             }
+            Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
+                match self.is_mutable(place, is_local_mutation_allowed) {
+                    Ok(Place::Local(local))
+                        if is_local_mutation_allowed != LocalMutationIsAllowed::Yes =>
+                    {
+                        // If the local may be initialized, and it is now currently being
+                        // mutated, then it is justified to be annotated with the `mut` keyword,
+                        // since the mutation may be a possible reassignment.
+                        let mpi = self.move_data.rev_lookup.find_local(*local);
+                        if flow_state.inits.contains(&mpi) {
+                            self.used_mut.insert(*local);
+                        }
+                    }
+                    Ok(Place::Projection(ref proj)) => {
+                        if let Some(field) = self.is_upvar_field_projection(&proj.base) {
+                            self.used_mut_upvars.push(field);
+                        }
+                    }
+                    Ok(Place::Local(_)) |
+                    Ok(Place::Static(..)) => {}
+                    Err(place_err) => {
+                        error_reported = true;
+
+                        let err_info = if let Place::Projection(
+                            box Projection {
+                                ref base,
+                                elem: ProjectionElem::Deref
+                            }
+                        ) = *place_err {
+                            if let Place::Local(local) = *base {
+                                let locations = self.mir.find_assignments(local);
+                                if locations.len() > 0 {
+                                    let item_msg = if error_reported {
+                                        self.get_secondary_err_msg(base)
+                                    } else {
+                                        self.get_default_err_msg(place)
+                                    };
+                                    let sp = self.mir.source_info(locations[0]).span;
+                                    let mut to_suggest_span = String::new();
+                                    if let Ok(src) =
+                                        self.tcx.sess.codemap().span_to_snippet(sp) {
+                                            to_suggest_span = src[1..].to_string();
+                                    };
+                                    Some((sp,
+                                          "consider changing this to be a \
+                                          mutable reference",
+                                          to_suggest_span,
+                                          item_msg,
+                                          self.get_primary_err_msg(base)))
+                                } else {
+                                    None
+                                }
+                            } else {
+                                None
+                            }
+                        } else {
+                            None
+                        };
+
+                        if let Some((err_help_span,
+                                     err_help_stmt,
+                                     to_suggest_span,
+                                     item_msg,
+                                     sec_span)) = err_info {
+                            let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
+                            err.span_suggestion(err_help_span,
+                                                err_help_stmt,
+                                                format!("&mut {}", to_suggest_span));
+                            if place != place_err {
+                                err.span_label(span, sec_span);
+                            }
+                            err.emit()
+                        } else {
+                            let item_msg = self.get_default_err_msg(place);
+                            let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
+                            err.span_label(span, "cannot mutate");
+                            if place != place_err {
+                                if let Some(name) = self.describe_place(place_err) {
+                                    err.note(&format!("the value which is causing this path not \
+                                                       to be mutable is...: `{}`", name));
+                                }
+                            }
+                            err.emit();
+                        }
+                    }
+                }
+            }
             Reservation(WriteKind::Move)
             | Reservation(WriteKind::StorageDeadOrDrop)
             | Reservation(WriteKind::MutableBorrow(BorrowKind::Shared))
@@ -1810,25 +1835,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         &self,
         place: &'d Place<'tcx>,
         is_local_mutation_allowed: LocalMutationIsAllowed,
-    ) -> Result<(), &'d Place<'tcx>> {
+    ) -> Result<&'d Place<'tcx>, &'d Place<'tcx>> {
         match *place {
             Place::Local(local) => {
                 let local = &self.mir.local_decls[local];
                 match local.mutability {
                     Mutability::Not => match is_local_mutation_allowed {
                         LocalMutationIsAllowed::Yes | LocalMutationIsAllowed::ExceptUpvars => {
-                            Ok(())
+                            Ok(place)
                         }
                         LocalMutationIsAllowed::No => Err(place),
                     },
-                    Mutability::Mut => Ok(()),
+                    Mutability::Mut => Ok(place),
                 }
             }
             Place::Static(ref static_) =>
                 if self.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
                     Err(place)
                 } else {
-                    Ok(())
+                    Ok(place)
                 },
             Place::Projection(ref proj) => {
                 match proj.elem {
@@ -1866,7 +1891,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                     hir::MutImmutable => return Err(place),
                                     // `*mut` raw pointers are always mutable, regardless of context
                                     // The users have to check by themselve.
-                                    hir::MutMutable => return Ok(()),
+                                    hir::MutMutable => return Ok(place),
                                 }
                             }
                             // `Box<T>` owns its content, so mutable if its location is mutable