@@ -761,47 +761,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
761
761
let move_data = self . move_data ;
762
762
763
763
// 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 ;
794
766
}
795
767
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
+ }
803
781
}
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
+ } ,
805
792
}
806
793
}
807
794
@@ -1108,20 +1095,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1108
1095
ProjectionElem :: Deref => {
1109
1096
let base_ty = proj. base . ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
1110
1097
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
1117
1099
match base_ty. sty {
1118
1100
ty:: TyRef ( _, tnm) => {
1119
1101
match tnm. mutbl {
1120
1102
// Shared borrowed data is never mutable
1121
1103
hir:: MutImmutable => Err ( lvalue) ,
1122
1104
// Mutably borrowed data is mutable, but only if we have a
1123
1105
// 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
+ } ,
1125
1113
}
1126
1114
} ,
1127
1115
ty:: TyRawPtr ( tnm) => {
@@ -1133,8 +1121,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1133
1121
hir:: MutMutable => Ok ( ( ) ) ,
1134
1122
}
1135
1123
} ,
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 ) ,
1136
1127
// 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) ,
1138
1129
}
1139
1130
} ,
1140
1131
// All other projections are owned by their base path, so mutable if
@@ -1143,8 +1134,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1143
1134
ProjectionElem :: Index ( ..) |
1144
1135
ProjectionElem :: ConstantIndex { ..} |
1145
1136
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
+
1147
1149
self . is_mutable ( & proj. base , LocalMutationIsAllowed :: No )
1150
+ }
1148
1151
}
1149
1152
}
1150
1153
}
0 commit comments