Skip to content

Commit ded0697

Browse files
nikomatsakisKiChjang
authored andcommitted
Return RootPlace in is_mutable
1 parent 8c607ea commit ded0697

File tree

1 file changed

+35
-7
lines changed
  • src/librustc_mir/borrow_check

1 file changed

+35
-7
lines changed

src/librustc_mir/borrow_check/mod.rs

+35-7
Original file line numberDiff line numberDiff line change
@@ -1150,13 +1150,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11501150
// in order to populate our used_mut set.
11511151
if let AggregateKind::Closure(def_id, _) = &**aggregate_kind {
11521152
let BorrowCheckResult { used_mut_upvars, .. } = self.tcx.mir_borrowck(*def_id);
1153+
debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
11531154
for field in used_mut_upvars {
11541155
match operands[field.index()] {
11551156
Operand::Move(Place::Local(local)) => {
11561157
self.used_mut.insert(local);
11571158
}
1158-
Operand::Move(Place::Projection(ref proj)) => {
1159-
if let Some(field) = self.is_upvar_field_projection(&proj.base) {
1159+
Operand::Move(ref place @ Place::Projection(_)) => {
1160+
if let Some(field) = self.is_upvar_field_projection(place) {
11601161
self.used_mut_upvars.push(field);
11611162
}
11621163
}
@@ -1697,8 +1698,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
16971698
}
16981699
}
16991700
}
1700-
Ok((Place::Projection(ref proj), _mut_allowed)) => {
1701-
if let Some(field) = self.is_upvar_field_projection(&proj.base) {
1701+
Ok((Place::Projection(_), _mut_allowed)) => {
1702+
if let Some(field) = self.is_upvar_field_projection(&place) {
17021703
self.used_mut_upvars.push(field);
17031704
}
17041705
}
@@ -1734,8 +1735,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
17341735
}
17351736
}
17361737
}
1737-
Ok((Place::Projection(ref proj), _mut_allowed)) => {
1738-
if let Some(field) = self.is_upvar_field_projection(&proj.base) {
1738+
Ok((Place::Projection(_), _mut_allowed)) => {
1739+
if let Some(field) = self.is_upvar_field_projection(&place) {
17391740
self.used_mut_upvars.push(field);
17401741
}
17411742
}
@@ -1930,7 +1931,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
19301931
}
19311932
(Mutability::Not, LocalMutationIsAllowed::Yes)
19321933
| (Mutability::Mut, _) => {
1933-
self.is_mutable(&proj.base, is_local_mutation_allowed)
1934+
// Subtle: this is an upvar
1935+
// reference, so it looks like
1936+
// `self.foo` -- we want to double
1937+
// check that the context `*self`
1938+
// is mutable (i.e., this is not a
1939+
// `Fn` closure). But if that
1940+
// check succeeds, we want to
1941+
// *blame* the mutability on
1942+
// `place` (that is,
1943+
// `self.foo`). This is used to
1944+
// propagate the info about
1945+
// whether mutability declarations
1946+
// are used outwards, so that we register
1947+
// the outer variable as mutable. Otherwise a
1948+
// test like this fails to record the `mut`
1949+
// as needed:
1950+
//
1951+
// ```
1952+
// fn foo<F: FnOnce()>(_f: F) { }
1953+
// fn main() {
1954+
// let var = Vec::new();
1955+
// foo(move || {
1956+
// var.push(1);
1957+
// });
1958+
// }
1959+
// ```
1960+
let _ = self.is_mutable(&proj.base, is_local_mutation_allowed)?;
1961+
Ok((place, is_local_mutation_allowed))
19341962
}
19351963
}
19361964
} else {

0 commit comments

Comments
 (0)