Skip to content

Commit e3b372f

Browse files
committed
Only check possibly initialized values and also loop over fn args
1 parent 5a2b590 commit e3b372f

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed

src/librustc/mir/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,15 @@ impl<'tcx> Mir<'tcx> {
248248
})
249249
}
250250

251-
/// Returns an iterator over all user-declared mutable locals.
251+
/// Returns an iterator over all user-declared mutable arguments and locals.
252252
#[inline]
253-
pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
254-
(self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
253+
pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
254+
(1..self.local_decls.len()).filter_map(move |index| {
255255
let local = Local::new(index);
256256
let decl = &self.local_decls[local];
257-
if decl.is_user_variable && decl.mutability == Mutability::Mut {
257+
if (decl.is_user_variable || index < self.arg_count + 1)
258+
&& decl.mutability == Mutability::Mut
259+
{
258260
Some(local)
259261
} else {
260262
None

src/librustc_mir/borrow_check/mod.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,17 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
261261

262262
debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
263263

264-
for local in mbcx.mir.mut_vars_iter().filter(|local| !mbcx.used_mut.contains(local)) {
264+
for local in mbcx.mir.mut_vars_and_args_iter().filter(|local| !mbcx.used_mut.contains(local)) {
265265
if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.visibility_scope_info {
266-
let source_info = mbcx.mir.local_decls[local].source_info;
266+
let local_decl = &mbcx.mir.local_decls[local];
267+
268+
// Skip over locals that begin with an underscore
269+
match local_decl.name {
270+
Some(name) if name.as_str().starts_with("_") => continue,
271+
_ => {},
272+
}
273+
274+
let source_info = local_decl.source_info;
267275
let mut_span = tcx.sess.codemap().span_until_non_whitespace(source_info.span);
268276

269277
tcx.struct_span_lint_node(
@@ -864,7 +872,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
864872
}
865873

866874
let mutability_error =
867-
self.check_access_permissions(place_span, rw, is_local_mutation_allowed);
875+
self.check_access_permissions(place_span, rw, is_local_mutation_allowed, flow_state);
868876
let conflict_error =
869877
self.check_access_for_conflict(context, place_span, sd, rw, flow_state);
870878

@@ -1656,6 +1664,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16561664
(place, span): (&Place<'tcx>, Span),
16571665
kind: ReadOrWrite,
16581666
is_local_mutation_allowed: LocalMutationIsAllowed,
1667+
flow_state: &Flows<'cx, 'gcx, 'tcx>,
16591668
) -> bool {
16601669
debug!(
16611670
"check_access_permissions({:?}, {:?}, {:?})",
@@ -1691,7 +1700,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16911700
Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
16921701
match place {
16931702
Place::Local(local) => {
1694-
self.used_mut.insert(*local);
1703+
// If the local may be initialized, and it is now currently being
1704+
// mutated, then it is justified to be annotated with the `mut` keyword,
1705+
// since the mutation may be a possible reassignment.
1706+
let mpi = self.move_data.rev_lookup.find_local(*local);
1707+
if flow_state.inits.contains(&mpi) {
1708+
self.used_mut.insert(*local);
1709+
}
16951710
}
16961711
Place::Projection(ref proj) => {
16971712
if let Some(field) = self.is_upvar_field_projection(&proj.base) {

0 commit comments

Comments
 (0)