@@ -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