diff options
| -rw-r--r-- | src/librustc/mir/mod.rs | 10 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/mod.rs | 23 |
2 files changed, 25 insertions, 8 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 7b6389072b7..c26b3014e53 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -248,13 +248,15 @@ impl<'tcx> Mir<'tcx> { }) } - /// Returns an iterator over all user-declared mutable locals. + /// Returns an iterator over all user-declared mutable arguments and locals. #[inline] - pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a { - (self.arg_count+1..self.local_decls.len()).filter_map(move |index| { + pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a { + (1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); let decl = &self.local_decls[local]; - if decl.is_user_variable && decl.mutability == Mutability::Mut { + if (decl.is_user_variable || index < self.arg_count + 1) + && decl.mutability == Mutability::Mut + { Some(local) } else { None diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index ea628cefd3e..60691d1179a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -261,9 +261,17 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( debug!("mbcx.used_mut: {:?}", mbcx.used_mut); - for local in mbcx.mir.mut_vars_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.visibility_scope_info { - let source_info = mbcx.mir.local_decls[local].source_info; + let local_decl = &mbcx.mir.local_decls[local]; + + // Skip over locals that begin with an underscore + match local_decl.name { + Some(name) if name.as_str().starts_with("_") => continue, + _ => {}, + } + + let source_info = local_decl.source_info; let mut_span = tcx.sess.codemap().span_until_non_whitespace(source_info.span); tcx.struct_span_lint_node( @@ -864,7 +872,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } let mutability_error = - self.check_access_permissions(place_span, rw, is_local_mutation_allowed); + self.check_access_permissions(place_span, rw, is_local_mutation_allowed, flow_state); let conflict_error = self.check_access_for_conflict(context, place_span, sd, rw, flow_state); @@ -1656,6 +1664,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (place, span): (&Place<'tcx>, Span), kind: ReadOrWrite, is_local_mutation_allowed: LocalMutationIsAllowed, + flow_state: &Flows<'cx, 'gcx, 'tcx>, ) -> bool { debug!( "check_access_permissions({:?}, {:?}, {:?})", @@ -1691,7 +1700,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { match place { Place::Local(local) => { - self.used_mut.insert(*local); + // 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); + } } Place::Projection(ref proj) => { if let Some(field) = self.is_upvar_field_projection(&proj.base) { |
