@@ -1150,13 +1150,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1150
1150
// in order to populate our used_mut set.
1151
1151
if let AggregateKind :: Closure ( def_id, _) = & * * aggregate_kind {
1152
1152
let BorrowCheckResult { used_mut_upvars, .. } = self . tcx . mir_borrowck ( * def_id) ;
1153
+ debug ! ( "{:?} used_mut_upvars={:?}" , def_id, used_mut_upvars) ;
1153
1154
for field in used_mut_upvars {
1154
1155
match operands[ field. index ( ) ] {
1155
1156
Operand :: Move ( Place :: Local ( local) ) => {
1156
1157
self . used_mut . insert ( local) ;
1157
1158
}
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 ) {
1160
1161
self . used_mut_upvars . push ( field) ;
1161
1162
}
1162
1163
}
@@ -1697,8 +1698,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1697
1698
}
1698
1699
}
1699
1700
}
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 ) {
1702
1703
self . used_mut_upvars . push ( field) ;
1703
1704
}
1704
1705
}
@@ -1734,8 +1735,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1734
1735
}
1735
1736
}
1736
1737
}
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 ) {
1739
1740
self . used_mut_upvars . push ( field) ;
1740
1741
}
1741
1742
}
@@ -1930,7 +1931,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1930
1931
}
1931
1932
( Mutability :: Not , LocalMutationIsAllowed :: Yes )
1932
1933
| ( 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) )
1934
1962
}
1935
1963
}
1936
1964
} else {
0 commit comments