@@ -183,7 +183,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
183
183
None => { }
184
184
}
185
185
186
- self . check_assignment ( assignment_id, assignment_span, assignee_cmt, mode ) ;
186
+ self . check_assignment ( assignment_id, assignment_span, assignee_cmt) ;
187
187
}
188
188
189
189
fn decl_without_init ( & mut self , _id : ast:: NodeId , _span : Span ) { }
@@ -567,13 +567,6 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
567
567
true
568
568
}
569
569
570
- fn is_local_variable_or_arg ( & self , cmt : mc:: cmt < ' tcx > ) -> bool {
571
- match cmt. cat {
572
- mc:: cat_local( _) => true ,
573
- _ => false
574
- }
575
- }
576
-
577
570
fn consume_common ( & self ,
578
571
id : ast:: NodeId ,
579
572
span : Span ,
@@ -791,202 +784,35 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
791
784
fn check_assignment ( & self ,
792
785
assignment_id : ast:: NodeId ,
793
786
assignment_span : Span ,
794
- assignee_cmt : mc:: cmt < ' tcx > ,
795
- mode : euv:: MutateMode ) {
787
+ assignee_cmt : mc:: cmt < ' tcx > ) {
796
788
debug ! ( "check_assignment(assignee_cmt={:?})" , assignee_cmt) ;
797
789
798
- // Mutable values can be assigned, as long as they obey loans
799
- // and aliasing restrictions:
800
- if assignee_cmt. mutbl . is_mutable ( ) {
801
- if check_for_aliasable_mutable_writes ( self , assignment_span, assignee_cmt. clone ( ) ) {
802
- if mode != euv:: Init {
803
- check_for_assignment_to_borrowed_path (
804
- self , assignment_id, assignment_span, assignee_cmt. clone ( ) ) ;
805
- mark_variable_as_used_mut ( self , assignee_cmt) ;
806
- }
807
- }
808
-
809
- return ;
810
- }
811
-
812
- // Initializations are OK if and only if they aren't partial
813
- // reinitialization of a partially-uninitialized structure.
814
- if mode == euv:: Init {
815
- return
816
- }
817
-
818
- // For immutable local variables, assignments are legal
819
- // if they cannot already have been assigned
820
- if self . is_local_variable_or_arg ( assignee_cmt. clone ( ) ) {
821
- assert ! ( assignee_cmt. mutbl. is_immutable( ) ) ; // no "const" locals
822
- let lp = opt_loan_path ( & assignee_cmt) . unwrap ( ) ;
823
- self . move_data . each_assignment_of ( assignment_id, & lp, |assign| {
824
- self . bccx . report_reassigned_immutable_variable (
825
- assignment_span,
826
- & * lp,
827
- assign) ;
790
+ // Check that we don't invalidate any outstanding loans
791
+ if let Some ( loan_path) = opt_loan_path ( & assignee_cmt) {
792
+ let scope = region:: CodeExtent :: from_node_id ( assignment_id) ;
793
+ self . each_in_scope_loan_affecting_path ( scope, & * loan_path, |loan| {
794
+ self . report_illegal_mutation ( assignment_span, & * loan_path, loan) ;
828
795
false
829
796
} ) ;
830
- return ;
831
797
}
832
798
833
- // Otherwise, just a plain error.
834
- match assignee_cmt. note {
835
- mc:: NoteClosureEnv ( upvar_id) => {
836
- // If this is an `Fn` closure, it simply can't mutate upvars.
837
- // If it's an `FnMut` closure, the original variable was declared immutable.
838
- // We need to determine which is the case here.
839
- let kind = match assignee_cmt. upvar ( ) . unwrap ( ) . cat {
840
- mc:: cat_upvar( mc:: Upvar { kind, .. } ) => kind,
841
- _ => unreachable ! ( )
842
- } ;
843
- if kind == ty:: FnClosureKind {
844
- self . bccx . span_err (
845
- assignment_span,
846
- & format ! ( "cannot assign to {}" ,
847
- self . bccx. cmt_to_string( & * assignee_cmt) ) ) ;
848
- self . bccx . span_help (
849
- self . tcx ( ) . map . span ( upvar_id. closure_expr_id ) ,
850
- "consider changing this closure to take self by mutable reference" ) ;
799
+ // Check for reassignments to (immutable) local variables. This
800
+ // needs to be done here instead of in check_loans because we
801
+ // depend on move data.
802
+ if let mc:: cat_local( local_id) = assignee_cmt. cat {
803
+ let lp = opt_loan_path ( & assignee_cmt) . unwrap ( ) ;
804
+ self . move_data . each_assignment_of ( assignment_id, & lp, |assign| {
805
+ if assignee_cmt. mutbl . is_mutable ( ) {
806
+ self . tcx ( ) . used_mut_nodes . borrow_mut ( ) . insert ( local_id) ;
851
807
} else {
852
- self . bccx . span_err (
808
+ self . bccx . report_reassigned_immutable_variable (
853
809
assignment_span,
854
- & format ! ( "cannot assign to {} {}" ,
855
- assignee_cmt. mutbl. to_user_str( ) ,
856
- self . bccx. cmt_to_string( & * assignee_cmt) ) ) ;
857
- }
858
- }
859
- _ => match opt_loan_path ( & assignee_cmt) {
860
- Some ( lp) => {
861
- self . bccx . span_err (
862
- assignment_span,
863
- & format ! ( "cannot assign to {} {} `{}`" ,
864
- assignee_cmt. mutbl. to_user_str( ) ,
865
- self . bccx. cmt_to_string( & * assignee_cmt) ,
866
- self . bccx. loan_path_to_string( & * lp) ) ) ;
867
- }
868
- None => {
869
- self . bccx . span_err (
870
- assignment_span,
871
- & format ! ( "cannot assign to {} {}" ,
872
- assignee_cmt. mutbl. to_user_str( ) ,
873
- self . bccx. cmt_to_string( & * assignee_cmt) ) ) ;
874
- }
875
- }
876
- }
877
- return ;
878
-
879
- fn mark_variable_as_used_mut < ' a , ' tcx > ( this : & CheckLoanCtxt < ' a , ' tcx > ,
880
- mut cmt : mc:: cmt < ' tcx > ) {
881
- //! If the mutability of the `cmt` being written is inherited
882
- //! from a local variable, liveness will
883
- //! not have been able to detect that this variable's mutability
884
- //! is important, so we must add the variable to the
885
- //! `used_mut_nodes` table here.
886
-
887
- loop {
888
- debug ! ( "mark_variable_as_used_mut(cmt={:?})" , cmt) ;
889
- match cmt. cat . clone ( ) {
890
- mc:: cat_upvar( mc:: Upvar { id : ty:: UpvarId { var_id : id, .. } , .. } ) |
891
- mc:: cat_local( id) => {
892
- this. tcx ( ) . used_mut_nodes . borrow_mut ( ) . insert ( id) ;
893
- return ;
894
- }
895
-
896
- mc:: cat_rvalue( ..) |
897
- mc:: cat_static_item |
898
- mc:: cat_deref( _, _, mc:: UnsafePtr ( ..) ) |
899
- mc:: cat_deref( _, _, mc:: Implicit ( ..) ) => {
900
- assert_eq ! ( cmt. mutbl, mc:: McDeclared ) ;
901
- return ;
902
- }
903
-
904
- mc:: cat_deref( _, _, mc:: BorrowedPtr ( ..) ) => {
905
- assert_eq ! ( cmt. mutbl, mc:: McDeclared ) ;
906
- // We need to drill down to upvar if applicable
907
- match cmt. upvar ( ) {
908
- Some ( b) => cmt = b,
909
- None => return
910
- }
911
- }
912
-
913
- mc:: cat_deref( b, _, mc:: Unique ) => {
914
- assert_eq ! ( cmt. mutbl, mc:: McInherited ) ;
915
- cmt = b;
916
- }
917
-
918
- mc:: cat_downcast( b, _) |
919
- mc:: cat_interior( b, _) => {
920
- assert_eq ! ( cmt. mutbl, mc:: McInherited ) ;
921
- cmt = b;
922
- }
923
- }
924
- }
925
- }
926
-
927
- fn check_for_aliasable_mutable_writes < ' a , ' tcx > ( this : & CheckLoanCtxt < ' a , ' tcx > ,
928
- span : Span ,
929
- cmt : mc:: cmt < ' tcx > ) -> bool {
930
- //! Safety checks related to writes to aliasable, mutable locations
931
-
932
- let guarantor = cmt. guarantor ( ) ;
933
- debug ! ( "check_for_aliasable_mutable_writes(cmt={:?}, guarantor={:?})" ,
934
- cmt, guarantor) ;
935
- if let mc:: cat_deref( ref b, _, mc:: BorrowedPtr ( ty:: MutBorrow , _) ) = guarantor. cat {
936
- // Statically prohibit writes to `&mut` when aliasable
937
- check_for_aliasability_violation ( this, span, b. clone ( ) ) ;
938
- }
939
-
940
- return true ; // no errors reported
941
- }
942
-
943
- fn check_for_aliasability_violation < ' a , ' tcx > ( this : & CheckLoanCtxt < ' a , ' tcx > ,
944
- span : Span ,
945
- cmt : mc:: cmt < ' tcx > )
946
- -> bool {
947
- match cmt. freely_aliasable ( this. tcx ( ) ) {
948
- mc:: Aliasability :: NonAliasable => {
949
- return true ;
950
- }
951
- mc:: Aliasability :: FreelyAliasable ( mc:: AliasableStaticMut ( ..) ) => {
952
- return true ;
953
- }
954
- mc:: Aliasability :: ImmutableUnique ( _) => {
955
- this. bccx . report_aliasability_violation (
956
- span,
957
- MutabilityViolation ,
958
- mc:: AliasableReason :: UnaliasableImmutable ) ;
959
- return false ;
960
- }
961
- mc:: Aliasability :: FreelyAliasable ( cause) => {
962
- this. bccx . report_aliasability_violation (
963
- span,
964
- MutabilityViolation ,
965
- cause) ;
966
- return false ;
810
+ & * lp,
811
+ assign) ;
967
812
}
968
- }
969
- }
970
-
971
- fn check_for_assignment_to_borrowed_path < ' a , ' tcx > (
972
- this : & CheckLoanCtxt < ' a , ' tcx > ,
973
- assignment_id : ast:: NodeId ,
974
- assignment_span : Span ,
975
- assignee_cmt : mc:: cmt < ' tcx > )
976
- {
977
- //! Check for assignments that violate the terms of an
978
- //! outstanding loan.
979
-
980
- let loan_path = match opt_loan_path ( & assignee_cmt) {
981
- Some ( lp) => lp,
982
- None => { return ; /* no loan path, can't be any loans */ }
983
- } ;
984
-
985
- let scope = region:: CodeExtent :: from_node_id ( assignment_id) ;
986
- this. each_in_scope_loan_affecting_path ( scope, & * loan_path, |loan| {
987
- this. report_illegal_mutation ( assignment_span, & * loan_path, loan) ;
988
813
false
989
814
} ) ;
815
+ return
990
816
}
991
817
}
992
818
0 commit comments