mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-09 00:17:44 +00:00
Store interned predicates in ParameterEnvironment
See #41444. As a first step towards untangling `ParameterEnvironment`, change its `caller_bounds` field from a `Vec` into an interned slice of `ty::Predicate`s. This change is intentionally well-contained and doesn't pull on any of the loose ends. In particular, you'll note that `normalize_param_env_or_error` now interns twice.
This commit is contained in:
parent
ed1f26ddda
commit
a6658d5ff1
@ -462,7 +462,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
unnormalized_env);
|
||||
|
||||
let predicates: Vec<_> =
|
||||
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.clone())
|
||||
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec())
|
||||
.filter(|p| !p.is_global()) // (*)
|
||||
.collect();
|
||||
|
||||
@ -477,11 +477,19 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
|
||||
predicates);
|
||||
|
||||
let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
|
||||
let elaborated_env = unnormalized_env.with_caller_bounds(tcx.intern_predicates(&predicates));
|
||||
|
||||
tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
|
||||
let predicates = match fully_normalize(&infcx, cause,
|
||||
&infcx.parameter_environment.caller_bounds) {
|
||||
let predicates = match fully_normalize(
|
||||
&infcx, cause,
|
||||
// You would really want to pass infcx.parameter_environment.caller_bounds here,
|
||||
// but that is an interned slice, and fully_normalize takes &T and returns T, so
|
||||
// without further refactoring, a slice can't be used. Luckily, we still have the
|
||||
// predicate vector from which we created the ParameterEnvironment in infcx, so we
|
||||
// can pass that instead. It's roundabout and a bit brittle, but this code path
|
||||
// ought to be refactored anyway, and until then it saves us from having to copy.
|
||||
&predicates,
|
||||
) {
|
||||
Ok(predicates) => predicates,
|
||||
Err(errors) => {
|
||||
infcx.report_fulfillment_errors(&errors);
|
||||
@ -520,7 +528,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
debug!("normalize_param_env_or_error: resolved predicates={:?}",
|
||||
predicates);
|
||||
|
||||
infcx.parameter_environment.with_caller_bounds(predicates)
|
||||
infcx.parameter_environment.with_caller_bounds(tcx.intern_predicates(&predicates))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ use ty::{self, TraitRef, Ty, TypeAndMut};
|
||||
use ty::{TyS, TypeVariants, Slice};
|
||||
use ty::{AdtKind, AdtDef, ClosureSubsts, Region};
|
||||
use hir::FreevarMap;
|
||||
use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
|
||||
use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
|
||||
use ty::RegionKind;
|
||||
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
|
||||
use ty::TypeVariants::*;
|
||||
@ -96,6 +96,7 @@ pub struct CtxtInterners<'tcx> {
|
||||
substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
|
||||
region: RefCell<FxHashSet<Interned<'tcx, RegionKind<'tcx>>>>,
|
||||
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
|
||||
predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
|
||||
}
|
||||
|
||||
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
@ -107,6 +108,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
substs: RefCell::new(FxHashSet()),
|
||||
region: RefCell::new(FxHashSet()),
|
||||
existential_predicates: RefCell::new(FxHashSet()),
|
||||
predicates: RefCell::new(FxHashSet()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1130,6 +1132,13 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx: 'lcx, 'lcx> Borrow<[Predicate<'lcx>]>
|
||||
for Interned<'tcx, Slice<Predicate<'tcx>>> {
|
||||
fn borrow<'a>(&'a self) -> &'a [Predicate<'lcx>] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! intern_method {
|
||||
($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
|
||||
$alloc_method:ident,
|
||||
@ -1224,6 +1233,7 @@ macro_rules! slice_interners {
|
||||
|
||||
slice_interners!(
|
||||
existential_predicates: _intern_existential_predicates(ExistentialPredicate),
|
||||
predicates: _intern_predicates(Predicate),
|
||||
type_list: _intern_type_list(Ty),
|
||||
substs: _intern_substs(Kind)
|
||||
);
|
||||
@ -1443,6 +1453,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self._intern_existential_predicates(eps)
|
||||
}
|
||||
|
||||
pub fn intern_predicates(self, preds: &[Predicate<'tcx>])
|
||||
-> &'tcx Slice<Predicate<'tcx>> {
|
||||
// FIXME consider asking the input slice to be sorted to avoid
|
||||
// re-interning permutations, in which case that would be asserted
|
||||
// here.
|
||||
if preds.len() == 0 {
|
||||
// The macro-generated method below asserts we don't intern an empty slice.
|
||||
Slice::empty()
|
||||
} else {
|
||||
self._intern_predicates(preds)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice<Ty<'tcx>> {
|
||||
if ts.len() == 0 {
|
||||
Slice::empty()
|
||||
@ -1481,6 +1504,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
iter.intern_with(|xs| self.intern_existential_predicates(xs))
|
||||
}
|
||||
|
||||
pub fn mk_predicates<I: InternAs<[Predicate<'tcx>],
|
||||
&'tcx Slice<Predicate<'tcx>>>>(self, iter: I)
|
||||
-> I::Output {
|
||||
iter.intern_with(|xs| self.intern_predicates(xs))
|
||||
}
|
||||
|
||||
pub fn mk_type_list<I: InternAs<[Ty<'tcx>],
|
||||
&'tcx Slice<Ty<'tcx>>>>(self, iter: I) -> I::Output {
|
||||
iter.intern_with(|xs| self.intern_type_list(xs))
|
||||
|
@ -747,7 +747,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub enum Predicate<'tcx> {
|
||||
/// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be
|
||||
/// the `Self` type of the trait reference and `A`, `B`, and `C`
|
||||
@ -876,7 +876,7 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct TraitPredicate<'tcx> {
|
||||
pub trait_ref: TraitRef<'tcx>
|
||||
}
|
||||
@ -928,18 +928,18 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct EquatePredicate<'tcx>(pub Ty<'tcx>, pub Ty<'tcx>); // `0 == 1`
|
||||
pub type PolyEquatePredicate<'tcx> = ty::Binder<EquatePredicate<'tcx>>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
|
||||
pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
|
||||
pub type PolyRegionOutlivesPredicate<'tcx> = PolyOutlivesPredicate<ty::Region<'tcx>,
|
||||
ty::Region<'tcx>>;
|
||||
pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct SubtypePredicate<'tcx> {
|
||||
pub a_is_expected: bool,
|
||||
pub a: Ty<'tcx>,
|
||||
@ -1173,7 +1173,7 @@ pub struct ParameterEnvironment<'tcx> {
|
||||
/// Obligations that the caller must satisfy. This is basically
|
||||
/// the set of bounds on the in-scope type parameters, translated
|
||||
/// into Obligations, and elaborated and normalized.
|
||||
pub caller_bounds: Vec<ty::Predicate<'tcx>>,
|
||||
pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
|
||||
|
||||
/// Scope that is attached to free regions for this scope. This is
|
||||
/// usually the id of the fn body, but for more abstract scopes
|
||||
@ -1196,7 +1196,7 @@ pub struct ParameterEnvironment<'tcx> {
|
||||
|
||||
impl<'a, 'tcx> ParameterEnvironment<'tcx> {
|
||||
pub fn with_caller_bounds(&self,
|
||||
caller_bounds: Vec<ty::Predicate<'tcx>>)
|
||||
caller_bounds: &'tcx [ty::Predicate<'tcx>])
|
||||
-> ParameterEnvironment<'tcx>
|
||||
{
|
||||
ParameterEnvironment {
|
||||
@ -2441,7 +2441,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
|
||||
ty::ParameterEnvironment {
|
||||
free_substs: self.intern_substs(&[]),
|
||||
caller_bounds: Vec::new(),
|
||||
caller_bounds: Slice::empty(),
|
||||
implicit_region_bound: None,
|
||||
free_id_outlive: None,
|
||||
is_copy_cache: RefCell::new(FxHashMap()),
|
||||
@ -2516,7 +2516,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
let unnormalized_env = ty::ParameterEnvironment {
|
||||
free_substs: free_substs,
|
||||
implicit_region_bound: free_id_outlive.map(|f| tcx.mk_region(ty::ReScope(f))),
|
||||
caller_bounds: predicates,
|
||||
caller_bounds: tcx.intern_predicates(&predicates),
|
||||
free_id_outlive: free_id_outlive,
|
||||
is_copy_cache: RefCell::new(FxHashMap()),
|
||||
is_sized_cache: RefCell::new(FxHashMap()),
|
||||
|
@ -313,6 +313,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
///
|
||||
/// Requires that trait definitions have been processed so that we can
|
||||
/// elaborate predicates and walk supertraits.
|
||||
///
|
||||
/// FIXME callers may only have a &[Predicate], not a Vec, so that's
|
||||
/// what this code should accept.
|
||||
pub fn required_region_bounds(self,
|
||||
erased_self_ty: Ty<'tcx>,
|
||||
predicates: Vec<ty::Predicate<'tcx>>)
|
||||
|
@ -218,7 +218,8 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// The key step here is to update the caller_bounds's predicates to be
|
||||
// the new hybrid bounds we computed.
|
||||
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
|
||||
let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates);
|
||||
let trait_param_env = impl_param_env.with_caller_bounds(
|
||||
tcx.intern_predicates(&hybrid_preds.predicates));
|
||||
let trait_param_env = traits::normalize_param_env_or_error(tcx,
|
||||
impl_m.def_id,
|
||||
trait_param_env,
|
||||
|
@ -893,7 +893,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
|
||||
trait_def_id);
|
||||
|
||||
let caller_predicates = self.parameter_environment.caller_bounds.clone();
|
||||
let caller_predicates = self.parameter_environment.caller_bounds.to_vec();
|
||||
for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates)
|
||||
.filter_map(|p| p.to_opt_poly_trait_ref())
|
||||
.filter(|b| b.def_id() == trait_def_id) {
|
||||
|
@ -1687,7 +1687,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
// To start, collect bounds from user:
|
||||
let mut param_bounds = self.tcx.required_region_bounds(generic.to_ty(self.tcx),
|
||||
param_env.caller_bounds.clone());
|
||||
param_env.caller_bounds.to_vec());
|
||||
|
||||
// Next, collect regions we scraped from the well-formedness
|
||||
// constraints in the fn signature. To do that, we walk the list
|
||||
|
Loading…
Reference in New Issue
Block a user