]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_infer/src/infer/outlives/env.rs
add `with_bounds` to `OutlivesEnvironment` and `implied_bounds_tys` to `outlives_boun...
[rust.git] / compiler / rustc_infer / src / infer / outlives / env.rs
index b2decd64f0fd9690d1bab2db52559ccb48f05d89..7afb44517a37b464bb3602fe07bdef043dcadaad 100644 (file)
@@ -2,6 +2,7 @@
 use crate::infer::{GenericKind, InferCtxt};
 use crate::traits::query::OutlivesBound;
 use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::transitive_relation::TransitiveRelationBuilder;
 use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};
 
 use super::explicit_outlives_bounds;
@@ -51,23 +52,48 @@ pub struct OutlivesEnvironment<'tcx> {
     region_bound_pairs: RegionBoundPairs<'tcx>,
 }
 
+/// Builder of OutlivesEnvironment.
+struct OutlivesEnvironmentBuilder<'tcx> {
+    param_env: ty::ParamEnv<'tcx>,
+    region_relation: TransitiveRelationBuilder<Region<'tcx>>,
+    region_bound_pairs: RegionBoundPairs<'tcx>,
+}
+
 /// "Region-bound pairs" tracks outlives relations that are known to
 /// be true, either because of explicit where-clauses like `T: 'a` or
 /// because of implied bounds.
 pub type RegionBoundPairs<'tcx> =
     FxIndexSet<ty::OutlivesPredicate<GenericKind<'tcx>, Region<'tcx>>>;
 
-impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
-    pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
-        let mut env = OutlivesEnvironment {
+impl<'tcx> OutlivesEnvironment<'tcx> {
+    /// Create a builder using `ParamEnv` and add explicit outlives bounds into it.
+    fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> {
+        let mut builder = OutlivesEnvironmentBuilder {
             param_env,
-            free_region_map: Default::default(),
+            region_relation: Default::default(),
             region_bound_pairs: Default::default(),
         };
 
-        env.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
+        builder.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
 
-        env
+        builder
+    }
+
+    #[inline]
+    /// Create a new `OutlivesEnvironment` without extra outlives bounds.
+    pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
+        Self::builder(param_env).build()
+    }
+
+    /// Create a new `OutlivesEnvironment` with extra outlives bounds.
+    pub fn with_bounds<'a>(
+        param_env: ty::ParamEnv<'tcx>,
+        infcx: Option<&InferCtxt<'a, 'tcx>>,
+        extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
+    ) -> Self {
+        let mut builder = Self::builder(param_env);
+        builder.add_outlives_bounds(infcx, extra_bounds);
+        builder.build()
     }
 
     /// Borrows current value of the `free_region_map`.
@@ -79,6 +105,17 @@ pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> {
     pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
         &self.region_bound_pairs
     }
+}
+
+impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
+    #[inline]
+    pub fn build(self) -> OutlivesEnvironment<'tcx> {
+        OutlivesEnvironment {
+            param_env: self.param_env,
+            free_region_map: FreeRegionMap { relation: self.region_relation.freeze() },
+            region_bound_pairs: self.region_bound_pairs,
+        }
+    }
 
     /// Processes outlives bounds that are known to hold, whether from implied or other sources.
     ///
@@ -86,11 +123,8 @@ pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
     /// contain inference variables, it must be supplied, in which
     /// case we will register "givens" on the inference context. (See
     /// `RegionConstraintData`.)
-    pub fn add_outlives_bounds<I>(
-        &mut self,
-        infcx: Option<&InferCtxt<'a, 'tcx>>,
-        outlives_bounds: I,
-    ) where
+    fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I)
+    where
         I: IntoIterator<Item = OutlivesBound<'tcx>>,
     {
         // Record relationships such as `T:'x` that don't go into the
@@ -122,7 +156,9 @@ pub fn add_outlives_bounds<I>(
                         // system to be more general and to make use
                         // of *every* relationship that arises here,
                         // but presently we do not.)
-                        self.free_region_map.relate_regions(r_a, r_b);
+                        if r_a.is_free_or_static() && r_b.is_free() {
+                            self.region_relation.add(r_a, r_b)
+                        }
                     }
                 }
             }