@@ -761,47 +761,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
761761        let  move_data = self . move_data ; 
762762
763763        // determine if this path has a non-mut owner (and thus needs checking). 
764-         let  mut  l = lvalue; 
765-         loop  { 
766-             match  * l { 
767-                 Lvalue :: Projection ( ref  proj)  => { 
768-                     l = & proj. base ; 
769-                     continue ; 
770-                 } 
771-                 Lvalue :: Local ( local)  => { 
772-                     match  self . mir . local_decls [ local] . mutability  { 
773-                         Mutability :: Not  => break ,  // needs check 
774-                         Mutability :: Mut  => return , 
775-                     } 
776-                 } 
777-                 Lvalue :: Static ( ref  static_)  => { 
778-                     // mutation of non-mut static is always illegal, 
779-                     // independent of dataflow. However it will be catched by 
780-                     // `check_access_permissions()`, we call delay_span_bug here 
781-                     // to be sure that no case has been missed 
782-                     if  !self . tcx . is_static_mut ( static_. def_id )  { 
783-                         let  item_msg = match  self . describe_lvalue ( lvalue)  { 
784-                             Some ( name)  => format ! ( "immutable static item `{}`" ,  name) , 
785-                             None  => "immutable static item" . to_owned ( ) 
786-                         } ; 
787-                         self . tcx . sess . delay_span_bug ( span, 
788-                             & format ! ( "cannot assign to {}, should have been caught by \  
789-                              `check_access_permissions()`",  item_msg) ) ; 
790-                     } 
791-                     return ; 
792-                 } 
793-             } 
764+         if  let  Ok ( ( ) )  = self . is_mutable ( lvalue,  LocalMutationIsAllowed :: No )  { 
765+             return ; 
794766        } 
795767
796-         if  let  Some ( mpi)  = self . move_path_for_lvalue ( lvalue)  { 
797-             for  ii in  & move_data. init_path_map [ mpi]  { 
798-                 if  flow_state. ever_inits . curr_state . contains ( ii)  { 
799-                     let  first_assign_span = self . move_data . inits [ * ii] . span ; 
800-                     self . report_illegal_reassignment ( 
801-                         context,  ( lvalue,  span) ,  first_assign_span) ; 
802-                     break ; 
768+         if  let  Err ( _)  = self . is_mutable ( lvalue,  LocalMutationIsAllowed :: Yes )  { 
769+             return ; 
770+         } 
771+ 
772+         match  self . move_path_closest_to ( lvalue)  { 
773+             Ok ( mpi)  => { 
774+                 for  ii in  & move_data. init_path_map [ mpi]  { 
775+                     if  flow_state. ever_inits . curr_state . contains ( ii)  { 
776+                         let  first_assign_span = self . move_data . inits [ * ii] . span ; 
777+                         self . report_illegal_reassignment ( 
778+                             context,  ( lvalue,  span) ,  first_assign_span) ; 
779+                         break ; 
780+                     } 
803781                } 
804-             } 
782+             } , 
783+             Err ( NoMovePathFound :: ReachedStatic )  => { 
784+                 let  item_msg = match  self . describe_lvalue ( lvalue)  { 
785+                     Some ( name)  => format ! ( "immutable static item `{}`" ,  name) , 
786+                     None  => "immutable static item" . to_owned ( ) 
787+                 } ; 
788+                 self . tcx . sess . delay_span_bug ( span, 
789+                     & format ! ( "cannot assign to {}, should have been caught by \  
790+                      `check_access_permissions()`",  item_msg) ) ; 
791+             } , 
805792        } 
806793    } 
807794
@@ -1108,20 +1095,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11081095                    ProjectionElem :: Deref  => { 
11091096                        let  base_ty = proj. base . ty ( self . mir ,  self . tcx ) . to_ty ( self . tcx ) ; 
11101097
1111-                         // `Box<T>` owns its content, so mutable if its location is mutable 
1112-                         if  base_ty. is_box ( )  { 
1113-                             return  self . is_mutable ( & proj. base ,  LocalMutationIsAllowed :: No ) ; 
1114-                         } 
1115- 
1116-                         // Otherwise we check the kind of deref to decide 
1098+                         // Check the kind of deref to decide 
11171099                        match  base_ty. sty  { 
11181100                            ty:: TyRef ( _,  tnm)  => { 
11191101                                match  tnm. mutbl  { 
11201102                                    // Shared borrowed data is never mutable 
11211103                                    hir:: MutImmutable  => Err ( lvalue) , 
11221104                                    // Mutably borrowed data is mutable, but only if we have a 
11231105                                    // unique path to the `&mut` 
1124-                                     hir:: MutMutable  => self . is_unique ( & proj. base ) , 
1106+                                     hir:: MutMutable  => { 
1107+                                         if  self . is_upvar_field_projection ( & proj. base ) . is_some ( )  { 
1108+                                             self . is_mutable ( & proj. base ,  is_local_mutation_allowed) 
1109+                                         }  else  { 
1110+                                             self . is_unique ( & proj. base ) 
1111+                                         } 
1112+                                     } , 
11251113                                } 
11261114                            } , 
11271115                            ty:: TyRawPtr ( tnm)  => { 
@@ -1133,8 +1121,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11331121                                    hir:: MutMutable  => Ok ( ( ) ) , 
11341122                                } 
11351123                            } , 
1124+                             // `Box<T>` owns its content, so mutable if its location is mutable 
1125+                             _ if  base_ty. is_box ( )  =>
1126+                                 self . is_mutable ( & proj. base ,  LocalMutationIsAllowed :: No ) , 
11361127                            // Deref should only be for reference, pointers or boxes 
1137-                             _ => bug ! ( "Deref of unexpected type: {:?}" ,  base_ty) 
1128+                             _ => bug ! ( "Deref of unexpected type: {:?}" ,  base_ty) , 
11381129                        } 
11391130                    } , 
11401131                    // All other projections are owned by their base path, so mutable if 
@@ -1143,8 +1134,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11431134                    ProjectionElem :: Index ( ..)  |
11441135                    ProjectionElem :: ConstantIndex { ..}  |
11451136                    ProjectionElem :: Subslice { ..}  |
1146-                     ProjectionElem :: Downcast ( ..)  =>
1137+                     ProjectionElem :: Downcast ( ..)  => { 
1138+                         let  field_projection = self . is_upvar_field_projection ( lvalue) ; 
1139+ 
1140+                         if  let  Some ( field)  = field_projection { 
1141+                             let  decl = & self . mir . upvar_decls [ field. index ( ) ] ; 
1142+ 
1143+                             return  match  decl. mutability  { 
1144+                                 Mutability :: Mut  => self . is_unique ( & proj. base ) , 
1145+                                 Mutability :: Not  => Err ( lvalue) , 
1146+                             } ; 
1147+                         } 
1148+ 
11471149                        self . is_mutable ( & proj. base ,  LocalMutationIsAllowed :: No ) 
1150+                     } 
11481151                } 
11491152            } 
11501153        } 
0 commit comments