diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-04-06 12:35:50 -0400 |
|---|---|---|
| committer | Keith Yeung <kungfukeith11@gmail.com> | 2018-04-28 22:25:57 -0700 |
| commit | ded06976790299c87ca3501aca23d3c74b5b0039 (patch) | |
| tree | 51888e9f86f80c975a8c0331139a81f0acafce53 /src | |
| parent | 8c607eaf949a0ba9c365dd00e18d948418cfe957 (diff) | |
| download | rust-ded06976790299c87ca3501aca23d3c74b5b0039.tar.gz rust-ded06976790299c87ca3501aca23d3c74b5b0039.zip | |
Return RootPlace in is_mutable
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/borrow_check/mod.rs | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index a70c601bd1a..f2b0ec58e78 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1150,13 +1150,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // in order to populate our used_mut set. if let AggregateKind::Closure(def_id, _) = &**aggregate_kind { let BorrowCheckResult { used_mut_upvars, .. } = self.tcx.mir_borrowck(*def_id); + debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars); for field in used_mut_upvars { match operands[field.index()] { Operand::Move(Place::Local(local)) => { self.used_mut.insert(local); } - Operand::Move(Place::Projection(ref proj)) => { - if let Some(field) = self.is_upvar_field_projection(&proj.base) { + Operand::Move(ref place @ Place::Projection(_)) => { + if let Some(field) = self.is_upvar_field_projection(place) { self.used_mut_upvars.push(field); } } @@ -1697,8 +1698,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } } - Ok((Place::Projection(ref proj), _mut_allowed)) => { - if let Some(field) = self.is_upvar_field_projection(&proj.base) { + Ok((Place::Projection(_), _mut_allowed)) => { + if let Some(field) = self.is_upvar_field_projection(&place) { self.used_mut_upvars.push(field); } } @@ -1734,8 +1735,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } } - Ok((Place::Projection(ref proj), _mut_allowed)) => { - if let Some(field) = self.is_upvar_field_projection(&proj.base) { + Ok((Place::Projection(_), _mut_allowed)) => { + if let Some(field) = self.is_upvar_field_projection(&place) { self.used_mut_upvars.push(field); } } @@ -1930,7 +1931,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } (Mutability::Not, LocalMutationIsAllowed::Yes) | (Mutability::Mut, _) => { - self.is_mutable(&proj.base, is_local_mutation_allowed) + // Subtle: this is an upvar + // reference, so it looks like + // `self.foo` -- we want to double + // check that the context `*self` + // is mutable (i.e., this is not a + // `Fn` closure). But if that + // check succeeds, we want to + // *blame* the mutability on + // `place` (that is, + // `self.foo`). This is used to + // propagate the info about + // whether mutability declarations + // are used outwards, so that we register + // the outer variable as mutable. Otherwise a + // test like this fails to record the `mut` + // as needed: + // + // ``` + // fn foo<F: FnOnce()>(_f: F) { } + // fn main() { + // let var = Vec::new(); + // foo(move || { + // var.push(1); + // }); + // } + // ``` + let _ = self.is_mutable(&proj.base, is_local_mutation_allowed)?; + Ok((place, is_local_mutation_allowed)) } } } else { |
