]> git.lizzy.rs Git - rust.git/commitdiff
add `Locations::All` as a concept
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 1 May 2018 14:50:05 +0000 (10:50 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Sat, 5 May 2018 09:03:56 +0000 (05:03 -0400)
In particular, type annotations given by the user must hold at all
points in the program. This doesn't affect current analysis but
will affect fact generation later.

src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs
src/librustc_mir/borrow_check/nll/type_check/input_output.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs

index a42ce3a2d3ba53171b148174907e1e4a7c8b0947..411bf5b55ed6b3de70cbad768fcb99116ff132ee 100644 (file)
@@ -38,7 +38,6 @@
 use self::region_infer::RegionInferenceContext;
 use self::universal_regions::UniversalRegions;
 
-
 /// Rewrites the regions in the MIR to use NLL variables, also
 /// scraping out the set of universal regions (e.g., region parameters)
 /// declared on the function. That set will need to be given to
index 32728145b29f682b8e733cde1d566acb373e394a..05b61f25a398c1debff978feaaed0be72e943f28 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::mir::Mir;
+use rustc::mir::{Location, Mir};
 use rustc::infer::region_constraints::Constraint;
 use rustc::infer::region_constraints::RegionConstraintData;
 use rustc::infer::region_constraints::{Verify, VerifyBound};
@@ -65,7 +65,11 @@ fn generate(&mut self, constraints: &MirTypeckRegionConstraints<'tcx>) {
                 givens,
             } = data;
 
-            let span = self.mir.source_info(locations.from_location).span;
+            let span = self.mir
+                .source_info(locations.from_location().unwrap_or(Location::START))
+                .span;
+
+            let at_location = locations.at_location().unwrap_or(Location::START);
 
             for constraint in constraints.keys() {
                 debug!("generate: constraint: {:?}", constraint);
@@ -83,8 +87,7 @@ fn generate(&mut self, constraints: &MirTypeckRegionConstraints<'tcx>) {
                 // reverse direction, because `regioncx` talks about
                 // "outlives" (`>=`) whereas the region constraints
                 // talk about `<=`.
-                self.regioncx
-                    .add_outlives(span, b_vid, a_vid, locations.at_location);
+                self.regioncx.add_outlives(span, b_vid, a_vid, at_location);
             }
 
             for verify in verifys {
@@ -109,7 +112,7 @@ fn verify_to_type_test(
 
         let lower_bound = self.to_region_vid(verify.region);
 
-        let point = locations.at_location;
+        let point = locations.at_location().unwrap_or(Location::START);
 
         let test = self.verify_bound_to_region_test(&verify.bound);
 
@@ -149,14 +152,6 @@ fn verify_bound_to_region_test(&self, verify_bound: &VerifyBound<'tcx>) -> Regio
     }
 
     fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
-        // Every region that we see in the constraints came from the
-        // MIR or from the parameter environment. If the former, it
-        // will be a region variable.  If the latter, it will be in
-        // the set of universal regions *somewhere*.
-        if let ty::ReVar(vid) = r {
-            *vid
-        } else {
-            self.regioncx.to_region_vid(r)
-        }
+        self.regioncx.to_region_vid(r)
     }
 }
index beb1a26ae70754dbc9e002d9590331f3bc226b83..2b1878c33e90b78f877672427d6c7f6703fae1de 100644 (file)
@@ -29,7 +29,7 @@
 
 use rustc_data_structures::indexed_vec::Idx;
 
-use super::{AtLocation, TypeChecker};
+use super::{Locations, TypeChecker};
 
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     pub(super) fn equate_inputs_and_outputs(
@@ -47,26 +47,21 @@ pub(super) fn equate_inputs_and_outputs(
         } = universal_regions;
         let infcx = self.infcx;
 
-        let start_position = Location {
-            block: START_BLOCK,
-            statement_index: 0,
-        };
-
         // Equate expected input tys with those in the MIR.
         let argument_locals = (1..).map(Local::new);
         for (&unnormalized_input_ty, local) in unnormalized_input_tys.iter().zip(argument_locals) {
-            let input_ty = self.normalize(&unnormalized_input_ty, start_position);
+            let input_ty = self.normalize(&unnormalized_input_ty, Locations::All);
             let mir_input_ty = mir.local_decls[local].ty;
-            self.equate_normalized_input_or_output(start_position, input_ty, mir_input_ty);
+            self.equate_normalized_input_or_output(input_ty, mir_input_ty);
         }
 
         assert!(
             mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() ||
             mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
-            );
+        );
         if let Some(mir_yield_ty) = mir.yield_ty {
             let ur_yield_ty = universal_regions.yield_ty.unwrap();
-            self.equate_normalized_input_or_output(start_position, ur_yield_ty, mir_yield_ty);
+            self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty);
         }
 
         // Return types are a bit more complex. They may contain existential `impl Trait`
@@ -75,13 +70,13 @@ pub(super) fn equate_inputs_and_outputs(
             "equate_inputs_and_outputs: unnormalized_output_ty={:?}",
             unnormalized_output_ty
         );
-        let output_ty = self.normalize(&unnormalized_output_ty, start_position);
+        let output_ty = self.normalize(&unnormalized_output_ty, Locations::All);
         debug!(
             "equate_inputs_and_outputs: normalized output_ty={:?}",
             output_ty
         );
         let mir_output_ty = mir.local_decls[RETURN_PLACE].ty;
-        let anon_type_map = self.fully_perform_op(start_position.at_self(), |cx| {
+        let anon_type_map = self.fully_perform_op(Locations::All, |cx| {
             let mut obligations = ObligationAccumulator::default();
 
             let (output_ty, anon_type_map) = obligations.add(infcx.instantiate_anon_types(
@@ -148,7 +143,7 @@ pub(super) fn equate_inputs_and_outputs(
         // prove that `T: Iterator` where `T` is the type we
         // instantiated it with).
         if let Some(anon_type_map) = anon_type_map {
-            self.fully_perform_op(start_position.at_self(), |_cx| {
+            self.fully_perform_op(Locations::All, |_cx| {
                 infcx.constrain_anon_types(&anon_type_map, universal_regions);
                 Ok(InferOk {
                     value: (),
@@ -158,13 +153,13 @@ pub(super) fn equate_inputs_and_outputs(
         }
     }
 
-    fn equate_normalized_input_or_output(&mut self, location: Location, a: Ty<'tcx>, b: Ty<'tcx>) {
+    fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
         debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
 
-        if let Err(terr) = self.eq_types(a, b, location.at_self()) {
+        if let Err(terr) = self.eq_types(a, b, Locations::All) {
             span_mirbug!(
                 self,
-                location,
+                Location::START,
                 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
                 a,
                 b,
index a21b9196badb5856b5fba5c3e8575114662bdf09..ec98a0a02c066144e0d1be58adb99ce8706de629 100644 (file)
@@ -619,16 +619,35 @@ pub struct OutlivesSet<'tcx> {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub struct Locations {
-    /// The location in the MIR that generated these constraints.
-    /// This is intended for error reporting and diagnosis; the
-    /// constraints may *take effect* at a distinct spot.
-    pub from_location: Location,
-
-    /// The constraints must be met at this location. In terms of the
-    /// NLL RFC, when you have a constraint `R1: R2 @ P`, this field
-    /// is the `P` value.
-    pub at_location: Location,
+pub enum Locations {
+    All,
+    Pair {
+        /// The location in the MIR that generated these constraints.
+        /// This is intended for error reporting and diagnosis; the
+        /// constraints may *take effect* at a distinct spot.
+        from_location: Location,
+
+        /// The constraints must be met at this location. In terms of the
+        /// NLL RFC, when you have a constraint `R1: R2 @ P`, this field
+        /// is the `P` value.
+        at_location: Location,
+    }
+}
+
+impl Locations {
+    pub fn from_location(&self) -> Option<Location> {
+        match self {
+            Locations::All => None,
+            Locations::Pair { from_location, .. } => Some(*from_location),
+        }
+    }
+
+    pub fn at_location(&self) -> Option<Location> {
+        match self {
+            Locations::All => None,
+            Locations::Pair { at_location, .. } => Some(*at_location),
+        }
+    }
 }
 
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
@@ -770,7 +789,7 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                     "check_stmt: user_assert_ty ty={:?} local_ty={:?}",
                     ty, local_ty
                 );
-                if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) {
+                if let Err(terr) = self.eq_types(ty, local_ty, Locations::All) {
                     span_mirbug!(
                         self,
                         stmt,
@@ -820,7 +839,7 @@ fn check_terminator(
                 let place_ty = location.ty(mir, tcx).to_ty(tcx);
                 let rv_ty = value.ty(mir, tcx);
 
-                let locations = Locations {
+                let locations = Locations::Pair {
                     from_location: term_location,
                     at_location: target.start_location(),
                 };
@@ -839,7 +858,7 @@ fn check_terminator(
                 // *both* blocks, so we need to ensure that it holds
                 // at both locations.
                 if let Some(unwind) = unwind {
-                    let locations = Locations {
+                    let locations = Locations::Pair {
                         from_location: term_location,
                         at_location: unwind.start_location(),
                     };
@@ -971,7 +990,7 @@ fn check_call_dest(
         match *destination {
             Some((ref dest, target_block)) => {
                 let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
-                let locations = Locations {
+                let locations = Locations::Pair {
                     from_location: term_location,
                     at_location: target_block.start_location(),
                 };
@@ -1375,7 +1394,7 @@ fn check_aggregate_rvalue(
             };
             let operand_ty = operand.ty(mir, tcx);
             if let Err(terr) =
-                self.sub_types(operand_ty, field_ty, location.at_successor_within_block())
+                self.sub_types(operand_ty, field_ty, location.at_self())
             {
                 span_mirbug!(
                     self,
@@ -1514,12 +1533,12 @@ fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
         }
     }
 
-    fn normalize<T>(&mut self, value: &T, location: Location) -> T
+    fn normalize<T>(&mut self, value: &T, location: impl ToLocations) -> T
     where
         T: fmt::Debug + TypeFoldable<'tcx>,
     {
         debug!("normalize(value={:?}, location={:?})", value, location);
-        self.fully_perform_op(location.at_self(), |this| {
+        self.fully_perform_op(location.to_locations(), |this| {
             let Normalized { value, obligations } = this.infcx
                 .at(&this.misc(this.last_span), this.param_env)
                 .normalize(value)
@@ -1585,16 +1604,32 @@ trait AtLocation {
 
 impl AtLocation for Location {
     fn at_self(self) -> Locations {
-        Locations {
+        Locations::Pair {
             from_location: self,
             at_location: self,
         }
     }
 
     fn at_successor_within_block(self) -> Locations {
-        Locations {
+        Locations::Pair {
             from_location: self,
             at_location: self.successor_within_block(),
         }
     }
 }
+
+trait ToLocations: fmt::Debug + Copy {
+    fn to_locations(self) -> Locations;
+}
+
+impl ToLocations for Locations {
+    fn to_locations(self) -> Locations {
+        self
+    }
+}
+
+impl ToLocations for Location {
+    fn to_locations(self) -> Locations {
+        self.at_self()
+    }
+}