Remove OutlivesEnvironmentBuilder.

`OutlivesEnvironment::new` can call `OutlivesEnvironment::with_bounds`
with an empty `extra_bounds`. And once that's done,
`OutlivesEnvironmentBuilder` has a single use and can be inlined and
removed into `OutlivesEnvironment::with_bounds`.
This commit is contained in:
Nicholas Nethercote 2024-10-02 17:38:42 +10:00
parent b8495e5dd2
commit abf212c16c

View File

@ -1,8 +1,7 @@
use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::transitive_relation::TransitiveRelationBuilder; use rustc_data_structures::transitive_relation::TransitiveRelationBuilder;
use rustc_middle::bug; use rustc_middle::{bug, ty};
use rustc_middle::ty::{self, Region}; use tracing::debug;
use tracing::{debug, instrument};
use super::explicit_outlives_bounds; use super::explicit_outlives_bounds;
use crate::infer::GenericKind; use crate::infer::GenericKind;
@ -54,37 +53,16 @@ pub struct OutlivesEnvironment<'tcx> {
region_bound_pairs: RegionBoundPairs<'tcx>, region_bound_pairs: RegionBoundPairs<'tcx>,
} }
/// Builder of OutlivesEnvironment.
#[derive(Debug)]
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 /// "Region-bound pairs" tracks outlives relations that are known to
/// be true, either because of explicit where-clauses like `T: 'a` or /// be true, either because of explicit where-clauses like `T: 'a` or
/// because of implied bounds. /// because of implied bounds.
pub type RegionBoundPairs<'tcx> = FxIndexSet<ty::OutlivesPredicate<'tcx, GenericKind<'tcx>>>; pub type RegionBoundPairs<'tcx> = FxIndexSet<ty::OutlivesPredicate<'tcx, GenericKind<'tcx>>>;
impl<'tcx> OutlivesEnvironment<'tcx> { 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,
region_relation: Default::default(),
region_bound_pairs: Default::default(),
};
builder.add_outlives_bounds(explicit_outlives_bounds(param_env));
builder
}
#[inline]
/// Create a new `OutlivesEnvironment` without extra outlives bounds. /// Create a new `OutlivesEnvironment` without extra outlives bounds.
#[inline]
pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self { pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
Self::builder(param_env).build() Self::with_bounds(param_env, vec![])
} }
/// Create a new `OutlivesEnvironment` with extra outlives bounds. /// Create a new `OutlivesEnvironment` with extra outlives bounds.
@ -92,9 +70,41 @@ pub fn with_bounds(
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>, extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
) -> Self { ) -> Self {
let mut builder = Self::builder(param_env); let mut region_relation = TransitiveRelationBuilder::default();
builder.add_outlives_bounds(extra_bounds); let mut region_bound_pairs = RegionBoundPairs::default();
builder.build()
// Record relationships such as `T:'x` that don't go into the
// free-region-map but which we use here.
for outlives_bound in explicit_outlives_bounds(param_env).chain(extra_bounds) {
debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound);
match outlives_bound {
OutlivesBound::RegionSubParam(r_a, param_b) => {
region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
}
OutlivesBound::RegionSubAlias(r_a, alias_b) => {
region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
}
OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) {
(
ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
) => region_relation.add(r_a, r_b),
(ty::ReError(_), _) | (_, ty::ReError(_)) => {}
// FIXME(#109628): We shouldn't have existential variables in implied bounds.
// Panic here once the linked issue is resolved!
(ty::ReVar(_), _) | (_, ty::ReVar(_)) => {}
_ => bug!("add_outlives_bounds: unexpected regions: ({r_a:?}, {r_b:?})"),
},
}
}
OutlivesEnvironment {
param_env,
free_region_map: FreeRegionMap { relation: region_relation.freeze() },
region_bound_pairs,
}
} }
/// Borrows current value of the `free_region_map`. /// Borrows current value of the `free_region_map`.
@ -107,48 +117,3 @@ pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
&self.region_bound_pairs &self.region_bound_pairs
} }
} }
impl<'tcx> OutlivesEnvironmentBuilder<'tcx> {
#[inline]
#[instrument(level = "debug")]
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.
fn add_outlives_bounds<I>(&mut self, outlives_bounds: I)
where
I: IntoIterator<Item = OutlivesBound<'tcx>>,
{
// Record relationships such as `T:'x` that don't go into the
// free-region-map but which we use here.
for outlives_bound in outlives_bounds {
debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound);
match outlives_bound {
OutlivesBound::RegionSubParam(r_a, param_b) => {
self.region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a));
}
OutlivesBound::RegionSubAlias(r_a, alias_b) => {
self.region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a));
}
OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) {
(
ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
) => self.region_relation.add(r_a, r_b),
(ty::ReError(_), _) | (_, ty::ReError(_)) => {}
// FIXME(#109628): We shouldn't have existential variables in implied bounds.
// Panic here once the linked issue is resolved!
(ty::ReVar(_), _) | (_, ty::ReVar(_)) => {}
_ => bug!("add_outlives_bounds: unexpected regions: ({r_a:?}, {r_b:?})"),
},
}
}
}
}