]> git.lizzy.rs Git - rust.git/commitdiff
treat local variables specially
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 10 Aug 2018 21:34:56 +0000 (17:34 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Sun, 19 Aug 2018 14:34:43 +0000 (07:34 -0700)
src/librustc_mir/borrow_check/mod.rs

index f96b9b8082fa799d2aee174bd92565d7b2cf0c1b..75e9b5f2df022689d80a7b090e86ebc1c1590a8e 100644 (file)
@@ -798,12 +798,6 @@ enum LocalMutationIsAllowed {
     No,
 }
 
-struct AccessErrorsReported {
-    mutability_error: bool,
-    #[allow(dead_code)]
-    conflict_error: bool,
-}
-
 #[derive(Copy, Clone)]
 enum InitializationRequiringAction {
     Update,
@@ -1072,7 +1066,7 @@ fn access_place(
         kind: (ShallowOrDeep, ReadOrWrite),
         is_local_mutation_allowed: LocalMutationIsAllowed,
         flow_state: &Flows<'cx, 'gcx, 'tcx>,
-    ) -> AccessErrorsReported {
+    ) {
         let (sd, rw) = kind;
 
         if let Activation(_, borrow_index) = rw {
@@ -1082,10 +1076,7 @@ fn access_place(
                      place: {:?} borrow_index: {:?}",
                     place_span.0, borrow_index
                 );
-                return AccessErrorsReported {
-                    mutability_error: false,
-                    conflict_error: true,
-                };
+                return;
             }
         }
 
@@ -1097,10 +1088,7 @@ fn access_place(
                 "access_place: suppressing error place_span=`{:?}` kind=`{:?}`",
                 place_span, kind
             );
-            return AccessErrorsReported {
-                mutability_error: false,
-                conflict_error: true,
-            };
+            return;
         }
 
         let mutability_error =
@@ -1122,11 +1110,6 @@ fn access_place(
             self.access_place_error_reported
                 .insert((place_span.0.clone(), place_span.1));
         }
-
-        AccessErrorsReported {
-            mutability_error,
-            conflict_error,
-        }
     }
 
     fn check_access_for_conflict(
@@ -1275,23 +1258,25 @@ fn mutate_place(
             }
         }
 
-        let errors_reported = self.access_place(
+        // Special case: you can assign a immutable local variable
+        // (e.g., `x = ...`) so long as it has never been initialized
+        // before (at this point in the flow).
+        if let &Place::Local(local) = place_span.0 {
+            if let Mutability::Not = self.mir.local_decls[local].mutability {
+                // check for reassignments to immutable local variables
+                self.check_if_reassignment_to_immutable_state(context, place_span, flow_state);
+                return;
+            }
+        }
+
+        // Otherwise, use the normal access permission rules.
+        self.access_place(
             context,
             place_span,
             (kind, Write(WriteKind::Mutate)),
-            // We want immutable upvars to cause an "assignment to immutable var"
-            // error, not an "reassignment of immutable var" error, because the
-            // latter can't find a good previous assignment span.
-            //
-            // There's probably a better way to do this.
-            LocalMutationIsAllowed::ExceptUpvars,
+            LocalMutationIsAllowed::No,
             flow_state,
         );
-
-        if !errors_reported.mutability_error {
-            // check for reassignments to immutable local variables
-            self.check_if_reassignment_to_immutable_state(context, place_span, flow_state);
-        }
     }
 
     fn consume_rvalue(