mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
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:
commit
ada80a13b9
@ -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>,
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()) {
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user