use FxIndexSet
for region_bound_pairs
This commit is contained in:
parent
2fdbf075cf
commit
2e796acf33
@ -22,6 +22,16 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
tcx: TyCtxt<'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>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
@ -2,6 +2,7 @@
|
||||
use rustc_data_structures::transitive_relation::TransitiveRelation;
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives;
|
||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc_infer::infer::region_constraints::GenericKind;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
@ -34,18 +35,6 @@ pub(crate) struct UniversalRegionRelations<'tcx> {
|
||||
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
|
||||
/// normalize the input-output types, which we then need later. So we
|
||||
/// return those. This vector consists of first the input types and
|
||||
@ -71,7 +60,7 @@ pub(crate) fn create<'tcx>(
|
||||
implicit_region_bound,
|
||||
constraints,
|
||||
universal_regions: universal_regions.clone(),
|
||||
region_bound_pairs: Vec::new(),
|
||||
region_bound_pairs: Default::default(),
|
||||
relations: UniversalRegionRelations {
|
||||
universal_regions: universal_regions.clone(),
|
||||
outlives: Default::default(),
|
||||
@ -371,11 +360,13 @@ fn add_outlives_bounds<I>(&mut self, outlives_bounds: I)
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::infer::free_regions::FreeRegionMap;
|
||||
use crate::infer::{GenericKind, InferCtxt};
|
||||
use crate::traits::query::OutlivesBound;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};
|
||||
|
||||
use super::explicit_outlives_bounds;
|
||||
@ -53,7 +54,8 @@ pub struct OutlivesEnvironment<'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<ty::OutlivesPredicate<GenericKind<'tcx>, Region<'tcx>>>;
|
||||
|
||||
impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
|
||||
pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
|
||||
@ -97,10 +99,12 @@ pub fn add_outlives_bounds<I>(
|
||||
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()) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
use rustc_hir::def_id::DefId;
|
||||
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;
|
||||
|
||||
@ -259,16 +259,17 @@ fn declared_generic_bounds_from_env_for_erased_ty(
|
||||
// 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
|
||||
// this holds from first principles.
|
||||
let from_region_bound_pairs = self.region_bound_pairs.iter().filter_map(|&(r, p)| {
|
||||
debug!(
|
||||
"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);
|
||||
(erased_p_ty == erased_ty)
|
||||
.then_some(ty::Binder::dummy(ty::OutlivesPredicate(p.to_ty(tcx), r)))
|
||||
});
|
||||
let from_region_bound_pairs =
|
||||
self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| {
|
||||
debug!(
|
||||
"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);
|
||||
(erased_p_ty == erased_ty)
|
||||
.then_some(ty::Binder::dummy(ty::OutlivesPredicate(p.to_ty(tcx), r)))
|
||||
});
|
||||
|
||||
param_bounds
|
||||
.chain(from_region_bound_pairs)
|
||||
|
@ -7,9 +7,8 @@
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
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::region_constraints::GenericKind;
|
||||
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::Normalized;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
@ -689,10 +688,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
|
||||
id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
wf_tys: &FxHashSet<Ty<'tcx>>,
|
||||
add_constraints: impl for<'a> FnOnce(
|
||||
&'a InferCtxt<'a, 'tcx>,
|
||||
&'a Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
|
||||
),
|
||||
add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'a, 'tcx>, &'a RegionBoundPairs<'tcx>),
|
||||
) -> bool {
|
||||
// Unfortunately, we have to use a new `InferCtxt` each call, because
|
||||
// region constraints get added and solved there and we need to test each
|
||||
|
Loading…
Reference in New Issue
Block a user