Auto merge of #99725 - lcnr:dedup-region_bound_pairs, r=compiler-errors

use `FxIndexSet` for `region_bound_pairs`

should help with #99217 and might generally be a perf improvement.

r? types
This commit is contained in:
bors 2022-07-27 22:02:14 +00:00
commit ada80a13b9
5 changed files with 37 additions and 35 deletions

View File

@ -22,6 +22,16 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>, infcx: &'a InferCtxt<'a, 'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>, universal_regions: &'a UniversalRegions<'tcx>,
/// Each RBP `GK: 'a` is assumed to be true. These encode
/// relationships like `T: 'a` that are added via implicit bounds
/// or the `param_env`.
///
/// Each region here is guaranteed to be a key in the `indices`
/// map. We use the "original" regions (i.e., the keys from the
/// map, and not the values) because the code in
/// `process_registered_region_obligations` has some special-cased
/// logic expecting to see (e.g.) `ReStatic`, and if we supplied
/// our special inference variable there, we would mess that up.
region_bound_pairs: &'a RegionBoundPairs<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>, implicit_region_bound: ty::Region<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,

View File

@ -2,6 +2,7 @@ use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::transitive_relation::TransitiveRelation; use rustc_data_structures::transitive_relation::TransitiveRelation;
use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::outlives; use rustc_infer::infer::outlives;
use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::region_constraints::GenericKind;
use rustc_infer::infer::InferCtxt; use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
@ -34,18 +35,6 @@ pub(crate) struct UniversalRegionRelations<'tcx> {
inverse_outlives: TransitiveRelation<RegionVid>, inverse_outlives: TransitiveRelation<RegionVid>,
} }
/// Each RBP `('a, GK)` indicates that `GK: 'a` can be assumed to
/// be true. These encode relationships like `T: 'a` that are
/// added via implicit bounds.
///
/// Each region here is guaranteed to be a key in the `indices`
/// map. We use the "original" regions (i.e., the keys from the
/// map, and not the values) because the code in
/// `process_registered_region_obligations` has some special-cased
/// logic expecting to see (e.g.) `ReStatic`, and if we supplied
/// our special inference variable there, we would mess that up.
type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>;
/// As part of computing the free region relations, we also have to /// As part of computing the free region relations, we also have to
/// normalize the input-output types, which we then need later. So we /// normalize the input-output types, which we then need later. So we
/// return those. This vector consists of first the input types and /// return those. This vector consists of first the input types and
@ -71,7 +60,7 @@ pub(crate) fn create<'tcx>(
implicit_region_bound, implicit_region_bound,
constraints, constraints,
universal_regions: universal_regions.clone(), universal_regions: universal_regions.clone(),
region_bound_pairs: Vec::new(), region_bound_pairs: Default::default(),
relations: UniversalRegionRelations { relations: UniversalRegionRelations {
universal_regions: universal_regions.clone(), universal_regions: universal_regions.clone(),
outlives: Default::default(), outlives: Default::default(),
@ -371,11 +360,13 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
} }
OutlivesBound::RegionSubParam(r_a, param_b) => { 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) => { 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));
} }
} }
} }

View File

@ -1,6 +1,7 @@
use crate::infer::free_regions::FreeRegionMap; use crate::infer::free_regions::FreeRegionMap;
use crate::infer::{GenericKind, InferCtxt}; use crate::infer::{GenericKind, InferCtxt};
use crate::traits::query::OutlivesBound; use crate::traits::query::OutlivesBound;
use rustc_data_structures::fx::FxIndexSet;
use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region}; use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};
use super::explicit_outlives_bounds; use super::explicit_outlives_bounds;
@ -53,7 +54,8 @@ pub struct OutlivesEnvironment<'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> = Vec<(Region<'tcx>, GenericKind<'tcx>)>; pub type RegionBoundPairs<'tcx> =
FxIndexSet<ty::OutlivesPredicate<GenericKind<'tcx>, Region<'tcx>>>;
impl<'a, 'tcx> OutlivesEnvironment<'tcx> { impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self { pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
@ -97,10 +99,12 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound); debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound);
match outlives_bound { match outlives_bound {
OutlivesBound::RegionSubParam(r_a, param_b) => { 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) => { 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) => { OutlivesBound::RegionSubRegion(r_a, r_b) => {
if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) { if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {

View File

@ -6,7 +6,7 @@ use rustc_data_structures::captures::Captures;
use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::sso::SsoHashSet;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, Subst}; use rustc_middle::ty::subst::{GenericArg, Subst};
use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt}; use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, Ty, TyCtxt};
use smallvec::smallvec; use smallvec::smallvec;
@ -259,16 +259,17 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// The problem is that the type of `x` is `&'a A`. To be // The problem is that the type of `x` is `&'a A`. To be
// well-formed, then, A must outlive `'a`, but we don't know that // well-formed, then, A must outlive `'a`, but we don't know that
// this holds from first principles. // this holds from first principles.
let from_region_bound_pairs = self.region_bound_pairs.iter().filter_map(|&(r, p)| { let from_region_bound_pairs =
debug!( self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| {
"declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}", debug!(
(r, p) "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
); (r, p)
let p_ty = p.to_ty(tcx); );
let erased_p_ty = self.tcx.erase_regions(p_ty); let p_ty = p.to_ty(tcx);
(erased_p_ty == erased_ty) let erased_p_ty = self.tcx.erase_regions(p_ty);
.then_some(ty::Binder::dummy(ty::OutlivesPredicate(p.to_ty(tcx), r))) (erased_p_ty == erased_ty)
}); .then_some(ty::Binder::dummy(ty::OutlivesPredicate(p.to_ty(tcx), r)))
});
param_bounds param_bounds
.chain(from_region_bound_pairs) .chain(from_region_bound_pairs)

View File

@ -7,9 +7,8 @@ use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind; use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
use rustc_infer::infer::outlives::obligations::TypeOutlives; use rustc_infer::infer::outlives::obligations::TypeOutlives;
use rustc_infer::infer::region_constraints::GenericKind;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::Normalized; use rustc_infer::traits::Normalized;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
@ -689,10 +688,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
id: hir::HirId, id: hir::HirId,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxHashSet<Ty<'tcx>>, wf_tys: &FxHashSet<Ty<'tcx>>,
add_constraints: impl for<'a> FnOnce( add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'a, 'tcx>, &'a RegionBoundPairs<'tcx>),
&'a InferCtxt<'a, 'tcx>,
&'a Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
),
) -> bool { ) -> bool {
// Unfortunately, we have to use a new `InferCtxt` each call, because // Unfortunately, we have to use a new `InferCtxt` each call, because
// region constraints get added and solved there and we need to test each // region constraints get added and solved there and we need to test each