X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_infer%2Fsrc%2Finfer%2Foutlives%2Fenv.rs;h=7afb44517a37b464bb3602fe07bdef043dcadaad;hb=d037f1843e9472d547dc22edbfb18788174c0754;hp=b897de7315a02dd2b0c6f14592379d1f6059d4a4;hpb=ef81fca760067e887e1dc69413f004327d23bb7e;p=rust.git diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index b897de7315a..7afb44517a3 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -1,6 +1,8 @@ use crate::infer::free_regions::FreeRegionMap; 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; @@ -50,22 +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_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> = Vec<(Region<'tcx>, GenericKind<'tcx>)>; +pub type RegionBoundPairs<'tcx> = + FxIndexSet, 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>, + ) -> 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`. @@ -77,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. /// @@ -84,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( - &mut self, - infcx: Option<&InferCtxt<'a, 'tcx>>, - outlives_bounds: I, - ) where + fn add_outlives_bounds(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I) + where I: IntoIterator>, { // Record relationships such as `T:'x` that don't go into the @@ -97,10 +133,12 @@ pub fn add_outlives_bounds( debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound); match outlives_bound { OutlivesBound::RegionSubParam(r_a, param_b) => { - self.region_bound_pairs.push((r_a, GenericKind::Param(param_b))); + self.region_bound_pairs + .insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a)); } OutlivesBound::RegionSubProjection(r_a, projection_b) => { - self.region_bound_pairs.push((r_a, GenericKind::Projection(projection_b))); + self.region_bound_pairs + .insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a)); } OutlivesBound::RegionSubRegion(r_a, r_b) => { if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) { @@ -118,7 +156,9 @@ pub fn add_outlives_bounds( // 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) + } } } }