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