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