Skip to content

Commit 4d81b14

Browse files
committed
Auto merge of #41605 - tschottdorf:param-env, r=nikomatsakis
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.
2 parents 6a5fc9e + a6658d5 commit 4d81b14

File tree

7 files changed

+59
-18
lines changed

7 files changed

+59
-18
lines changed

src/librustc/traits/mod.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
462462
unnormalized_env);
463463

464464
let predicates: Vec<_> =
465-
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.clone())
465+
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec())
466466
.filter(|p| !p.is_global()) // (*)
467467
.collect();
468468

@@ -477,11 +477,19 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
477477
debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
478478
predicates);
479479

480-
let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
480+
let elaborated_env = unnormalized_env.with_caller_bounds(tcx.intern_predicates(&predicates));
481481

482482
tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
483-
let predicates = match fully_normalize(&infcx, cause,
484-
&infcx.parameter_environment.caller_bounds) {
483+
let predicates = match fully_normalize(
484+
&infcx, cause,
485+
// You would really want to pass infcx.parameter_environment.caller_bounds here,
486+
// but that is an interned slice, and fully_normalize takes &T and returns T, so
487+
// without further refactoring, a slice can't be used. Luckily, we still have the
488+
// predicate vector from which we created the ParameterEnvironment in infcx, so we
489+
// can pass that instead. It's roundabout and a bit brittle, but this code path
490+
// ought to be refactored anyway, and until then it saves us from having to copy.
491+
&predicates,
492+
) {
485493
Ok(predicates) => predicates,
486494
Err(errors) => {
487495
infcx.report_fulfillment_errors(&errors);
@@ -520,7 +528,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
520528
debug!("normalize_param_env_or_error: resolved predicates={:?}",
521529
predicates);
522530

523-
infcx.parameter_environment.with_caller_bounds(predicates)
531+
infcx.parameter_environment.with_caller_bounds(tcx.intern_predicates(&predicates))
524532
})
525533
}
526534

src/librustc/ty/context.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use ty::{self, TraitRef, Ty, TypeAndMut};
3232
use ty::{TyS, TypeVariants, Slice};
3333
use ty::{AdtKind, AdtDef, ClosureSubsts, Region};
3434
use hir::FreevarMap;
35-
use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
35+
use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
3636
use ty::RegionKind;
3737
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
3838
use ty::TypeVariants::*;
@@ -96,6 +96,7 @@ pub struct CtxtInterners<'tcx> {
9696
substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
9797
region: RefCell<FxHashSet<Interned<'tcx, RegionKind<'tcx>>>>,
9898
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
99+
predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
99100
}
100101

101102
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
@@ -107,6 +108,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
107108
substs: RefCell::new(FxHashSet()),
108109
region: RefCell::new(FxHashSet()),
109110
existential_predicates: RefCell::new(FxHashSet()),
111+
predicates: RefCell::new(FxHashSet()),
110112
}
111113
}
112114

@@ -1130,6 +1132,13 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
11301132
}
11311133
}
11321134

1135+
impl<'tcx: 'lcx, 'lcx> Borrow<[Predicate<'lcx>]>
1136+
for Interned<'tcx, Slice<Predicate<'tcx>>> {
1137+
fn borrow<'a>(&'a self) -> &'a [Predicate<'lcx>] {
1138+
&self.0[..]
1139+
}
1140+
}
1141+
11331142
macro_rules! intern_method {
11341143
($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
11351144
$alloc_method:ident,
@@ -1224,6 +1233,7 @@ macro_rules! slice_interners {
12241233

12251234
slice_interners!(
12261235
existential_predicates: _intern_existential_predicates(ExistentialPredicate),
1236+
predicates: _intern_predicates(Predicate),
12271237
type_list: _intern_type_list(Ty),
12281238
substs: _intern_substs(Kind)
12291239
);
@@ -1443,6 +1453,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
14431453
self._intern_existential_predicates(eps)
14441454
}
14451455

1456+
pub fn intern_predicates(self, preds: &[Predicate<'tcx>])
1457+
-> &'tcx Slice<Predicate<'tcx>> {
1458+
// FIXME consider asking the input slice to be sorted to avoid
1459+
// re-interning permutations, in which case that would be asserted
1460+
// here.
1461+
if preds.len() == 0 {
1462+
// The macro-generated method below asserts we don't intern an empty slice.
1463+
Slice::empty()
1464+
} else {
1465+
self._intern_predicates(preds)
1466+
}
1467+
}
1468+
14461469
pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice<Ty<'tcx>> {
14471470
if ts.len() == 0 {
14481471
Slice::empty()
@@ -1481,6 +1504,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
14811504
iter.intern_with(|xs| self.intern_existential_predicates(xs))
14821505
}
14831506

1507+
pub fn mk_predicates<I: InternAs<[Predicate<'tcx>],
1508+
&'tcx Slice<Predicate<'tcx>>>>(self, iter: I)
1509+
-> I::Output {
1510+
iter.intern_with(|xs| self.intern_predicates(xs))
1511+
}
1512+
14841513
pub fn mk_type_list<I: InternAs<[Ty<'tcx>],
14851514
&'tcx Slice<Ty<'tcx>>>>(self, iter: I) -> I::Output {
14861515
iter.intern_with(|xs| self.intern_type_list(xs))

src/librustc/ty/mod.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
747747
}
748748
}
749749

750-
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
750+
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
751751
pub enum Predicate<'tcx> {
752752
/// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be
753753
/// the `Self` type of the trait reference and `A`, `B`, and `C`
@@ -876,7 +876,7 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
876876
}
877877
}
878878

879-
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
879+
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
880880
pub struct TraitPredicate<'tcx> {
881881
pub trait_ref: TraitRef<'tcx>
882882
}
@@ -928,18 +928,18 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
928928
}
929929
}
930930

931-
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
931+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
932932
pub struct EquatePredicate<'tcx>(pub Ty<'tcx>, pub Ty<'tcx>); // `0 == 1`
933933
pub type PolyEquatePredicate<'tcx> = ty::Binder<EquatePredicate<'tcx>>;
934934

935-
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
935+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
936936
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
937937
pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
938938
pub type PolyRegionOutlivesPredicate<'tcx> = PolyOutlivesPredicate<ty::Region<'tcx>,
939939
ty::Region<'tcx>>;
940940
pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
941941

942-
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
942+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
943943
pub struct SubtypePredicate<'tcx> {
944944
pub a_is_expected: bool,
945945
pub a: Ty<'tcx>,
@@ -1173,7 +1173,7 @@ pub struct ParameterEnvironment<'tcx> {
11731173
/// Obligations that the caller must satisfy. This is basically
11741174
/// the set of bounds on the in-scope type parameters, translated
11751175
/// into Obligations, and elaborated and normalized.
1176-
pub caller_bounds: Vec<ty::Predicate<'tcx>>,
1176+
pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
11771177

11781178
/// Scope that is attached to free regions for this scope. This is
11791179
/// usually the id of the fn body, but for more abstract scopes
@@ -1196,7 +1196,7 @@ pub struct ParameterEnvironment<'tcx> {
11961196

11971197
impl<'a, 'tcx> ParameterEnvironment<'tcx> {
11981198
pub fn with_caller_bounds(&self,
1199-
caller_bounds: Vec<ty::Predicate<'tcx>>)
1199+
caller_bounds: &'tcx [ty::Predicate<'tcx>])
12001200
-> ParameterEnvironment<'tcx>
12011201
{
12021202
ParameterEnvironment {
@@ -2441,7 +2441,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
24412441
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
24422442
ty::ParameterEnvironment {
24432443
free_substs: self.intern_substs(&[]),
2444-
caller_bounds: Vec::new(),
2444+
caller_bounds: Slice::empty(),
24452445
implicit_region_bound: None,
24462446
free_id_outlive: None,
24472447
is_copy_cache: RefCell::new(FxHashMap()),
@@ -2516,7 +2516,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
25162516
let unnormalized_env = ty::ParameterEnvironment {
25172517
free_substs: free_substs,
25182518
implicit_region_bound: free_id_outlive.map(|f| tcx.mk_region(ty::ReScope(f))),
2519-
caller_bounds: predicates,
2519+
caller_bounds: tcx.intern_predicates(&predicates),
25202520
free_id_outlive: free_id_outlive,
25212521
is_copy_cache: RefCell::new(FxHashMap()),
25222522
is_sized_cache: RefCell::new(FxHashMap()),

src/librustc/ty/util.rs

+3
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
313313
///
314314
/// Requires that trait definitions have been processed so that we can
315315
/// elaborate predicates and walk supertraits.
316+
///
317+
/// FIXME callers may only have a &[Predicate], not a Vec, so that's
318+
/// what this code should accept.
316319
pub fn required_region_bounds(self,
317320
erased_self_ty: Ty<'tcx>,
318321
predicates: Vec<ty::Predicate<'tcx>>)

src/librustc_typeck/check/compare_method.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
218218
// The key step here is to update the caller_bounds's predicates to be
219219
// the new hybrid bounds we computed.
220220
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
221-
let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates);
221+
let trait_param_env = impl_param_env.with_caller_bounds(
222+
tcx.intern_predicates(&hybrid_preds.predicates));
222223
let trait_param_env = traits::normalize_param_env_or_error(tcx,
223224
impl_m.def_id,
224225
trait_param_env,

src/librustc_typeck/check/method/probe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
893893
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
894894
trait_def_id);
895895

896-
let caller_predicates = self.parameter_environment.caller_bounds.clone();
896+
let caller_predicates = self.parameter_environment.caller_bounds.to_vec();
897897
for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates)
898898
.filter_map(|p| p.to_opt_poly_trait_ref())
899899
.filter(|b| b.def_id() == trait_def_id) {

src/librustc_typeck/check/regionck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1687,7 +1687,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
16871687

16881688
// To start, collect bounds from user:
16891689
let mut param_bounds = self.tcx.required_region_bounds(generic.to_ty(self.tcx),
1690-
param_env.caller_bounds.clone());
1690+
param_env.caller_bounds.to_vec());
16911691

16921692
// Next, collect regions we scraped from the well-formedness
16931693
// constraints in the fn signature. To do that, we walk the list

0 commit comments

Comments
 (0)