Skip to content

Commit 087ae97

Browse files
committed
Auto merge of rust-lang#123058 - lukas-code:clauses, r=lcnr
[perf] cache type info for ParamEnv This is an attempt to mitigate some of the perf regressions in rust-lang#122553 (comment), but seems worth to test and land separately, since it is mostly unrelated to that PR.
2 parents 6f83750 + 94d61d8 commit 087ae97

File tree

14 files changed

+284
-110
lines changed

14 files changed

+284
-110
lines changed

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,7 @@ pub(super) fn explicit_item_bounds_with_filter(
165165
ty::EarlyBinder::bind(bounds)
166166
}
167167

168-
pub(super) fn item_bounds(
169-
tcx: TyCtxt<'_>,
170-
def_id: DefId,
171-
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
168+
pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<ty::Clauses<'_>> {
172169
tcx.explicit_item_bounds(def_id).map_bound(|bounds| {
173170
tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)))
174171
})
@@ -177,7 +174,7 @@ pub(super) fn item_bounds(
177174
pub(super) fn item_super_predicates(
178175
tcx: TyCtxt<'_>,
179176
def_id: DefId,
180-
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
177+
) -> ty::EarlyBinder<ty::Clauses<'_>> {
181178
tcx.explicit_item_super_predicates(def_id).map_bound(|bounds| {
182179
tcx.mk_clauses_from_iter(
183180
util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)).filter_only_self(),
@@ -188,12 +185,12 @@ pub(super) fn item_super_predicates(
188185
pub(super) fn item_non_self_assumptions(
189186
tcx: TyCtxt<'_>,
190187
def_id: DefId,
191-
) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
188+
) -> ty::EarlyBinder<ty::Clauses<'_>> {
192189
let all_bounds: FxIndexSet<_> = tcx.item_bounds(def_id).skip_binder().iter().collect();
193190
let own_bounds: FxIndexSet<_> =
194191
tcx.item_super_predicates(def_id).skip_binder().iter().collect();
195192
if all_bounds.len() == own_bounds.len() {
196-
ty::EarlyBinder::bind(ty::List::empty())
193+
ty::EarlyBinder::bind(ty::ListWithCachedTypeInfo::empty())
197194
} else {
198195
ty::EarlyBinder::bind(tcx.mk_clauses_from_iter(all_bounds.difference(&own_bounds).copied()))
199196
}

compiler/rustc_middle/src/query/erase.rs

+4
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ impl<T> EraseType for &'_ ty::List<T> {
6767
type Result = [u8; size_of::<&'static ty::List<()>>()];
6868
}
6969

70+
impl<T> EraseType for &'_ ty::ListWithCachedTypeInfo<T> {
71+
type Result = [u8; size_of::<&'static ty::ListWithCachedTypeInfo<()>>()];
72+
}
73+
7074
impl<I: rustc_index::Idx, T> EraseType for &'_ rustc_index::IndexSlice<I, T> {
7175
type Result = [u8; size_of::<&'static rustc_index::IndexSlice<u32, ()>>()];
7276
}

compiler/rustc_middle/src/query/keys.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
432432
}
433433
}
434434

435-
impl<'tcx> Key for &'tcx ty::List<ty::Clause<'tcx>> {
435+
impl<'tcx> Key for ty::Clauses<'tcx> {
436436
type Cache<V> = DefaultCache<Self, V>;
437437

438438
fn default_span(&self, _: TyCtxt<'_>) -> Span {

compiler/rustc_middle/src/query/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -398,15 +398,15 @@ rustc_queries! {
398398
/// ```
399399
///
400400
/// Bounds from the parent (e.g. with nested impl trait) are not included.
401-
query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> {
401+
query item_bounds(key: DefId) -> ty::EarlyBinder<ty::Clauses<'tcx>> {
402402
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
403403
}
404404

405-
query item_super_predicates(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> {
405+
query item_super_predicates(key: DefId) -> ty::EarlyBinder<ty::Clauses<'tcx>> {
406406
desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) }
407407
}
408408

409-
query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> {
409+
query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder<ty::Clauses<'tcx>> {
410410
desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) }
411411
}
412412

@@ -2156,7 +2156,7 @@ rustc_queries! {
21562156
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
21572157
}
21582158

2159-
query reveal_opaque_types_in_bounds(key: &'tcx ty::List<ty::Clause<'tcx>>) -> &'tcx ty::List<ty::Clause<'tcx>> {
2159+
query reveal_opaque_types_in_bounds(key: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
21602160
desc { "revealing opaque types in `{:?}`", key }
21612161
}
21622162

compiler/rustc_middle/src/ty/codec.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,9 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty
414414
}
415415
}
416416

417-
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Clause<'tcx>> {
417+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
418+
for ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>
419+
{
418420
fn decode(decoder: &mut D) -> &'tcx Self {
419421
let len = decoder.read_usize();
420422
decoder.interner().mk_clauses_from_iter(
@@ -461,7 +463,7 @@ impl_decodable_via_ref! {
461463
&'tcx mir::BorrowCheckResult<'tcx>,
462464
&'tcx mir::coverage::CodeRegion,
463465
&'tcx ty::List<ty::BoundVariableKind>,
464-
&'tcx ty::List<ty::Clause<'tcx>>,
466+
&'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>,
465467
&'tcx ty::List<FieldIdx>,
466468
&'tcx ty::List<(VariantIdx, FieldIdx)>,
467469
}

compiler/rustc_middle/src/ty/context.rs

+51-10
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ use crate::traits::solve::{
2525
ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
2626
};
2727
use crate::ty::{
28-
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind,
29-
ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate,
30-
PredicateKind, PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty,
31-
TyKind, TyVid, TypeVisitable, Visibility,
28+
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
29+
GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy,
30+
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, Region,
31+
RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, TypeVisitable, Visibility,
3232
};
3333
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
3434
use rustc_ast::{self as ast, attr};
@@ -130,6 +130,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
130130
type SubtypePredicate = ty::SubtypePredicate<'tcx>;
131131
type CoercePredicate = ty::CoercePredicate<'tcx>;
132132
type ClosureKind = ty::ClosureKind;
133+
type Clauses = ty::Clauses<'tcx>;
133134

134135
fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
135136
self.mk_canonical_var_infos(infos)
@@ -152,7 +153,7 @@ pub struct CtxtInterners<'tcx> {
152153
region: InternedSet<'tcx, RegionKind<'tcx>>,
153154
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
154155
predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
155-
clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
156+
clauses: InternedSet<'tcx, ListWithCachedTypeInfo<Clause<'tcx>>>,
156157
projs: InternedSet<'tcx, List<ProjectionKind>>,
157158
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
158159
const_: InternedSet<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>,
@@ -286,6 +287,24 @@ impl<'tcx> CtxtInterners<'tcx> {
286287
.0,
287288
))
288289
}
290+
291+
fn intern_clauses(&self, clauses: &[Clause<'tcx>]) -> Clauses<'tcx> {
292+
if clauses.is_empty() {
293+
ListWithCachedTypeInfo::empty()
294+
} else {
295+
self.clauses
296+
.intern_ref(clauses, || {
297+
let flags = super::flags::FlagComputation::for_clauses(clauses);
298+
299+
InternedInSet(ListWithCachedTypeInfo::from_arena(
300+
&*self.arena,
301+
flags.into(),
302+
clauses,
303+
))
304+
})
305+
.0
306+
}
307+
}
289308
}
290309

291310
// For these preinterned values, an alternative would be to have
@@ -1783,6 +1802,29 @@ impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> {
17831802
}
17841803
}
17851804

1805+
impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {
1806+
fn borrow(&self) -> &[T] {
1807+
&self.0[..]
1808+
}
1809+
}
1810+
1811+
impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {
1812+
fn eq(&self, other: &InternedInSet<'tcx, ListWithCachedTypeInfo<T>>) -> bool {
1813+
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1814+
// `x == y`.
1815+
self.0[..] == other.0[..]
1816+
}
1817+
}
1818+
1819+
impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {}
1820+
1821+
impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {
1822+
fn hash<H: Hasher>(&self, s: &mut H) {
1823+
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1824+
self.0[..].hash(s)
1825+
}
1826+
}
1827+
17861828
macro_rules! direct_interners {
17871829
($($name:ident: $vis:vis $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
17881830
$(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
@@ -1841,7 +1883,7 @@ macro_rules! slice_interners {
18411883
List::empty()
18421884
} else {
18431885
self.interners.$field.intern_ref(v, || {
1844-
InternedInSet(List::from_arena(&*self.arena, v))
1886+
InternedInSet(List::from_arena(&*self.arena, (), v))
18451887
}).0
18461888
}
18471889
})+
@@ -1858,7 +1900,6 @@ slice_interners!(
18581900
type_lists: pub mk_type_list(Ty<'tcx>),
18591901
canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
18601902
poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
1861-
clauses: intern_clauses(Clause<'tcx>),
18621903
projs: pub mk_projs(ProjectionKind),
18631904
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
18641905
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
@@ -2163,11 +2204,11 @@ impl<'tcx> TyCtxt<'tcx> {
21632204
self.intern_poly_existential_predicates(eps)
21642205
}
21652206

2166-
pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> {
2207+
pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> Clauses<'tcx> {
21672208
// FIXME consider asking the input slice to be sorted to avoid
21682209
// re-interning permutations, in which case that would be asserted
21692210
// here.
2170-
self.intern_clauses(clauses)
2211+
self.interners.intern_clauses(clauses)
21712212
}
21722213

21732214
pub fn mk_local_def_ids(self, clauses: &[LocalDefId]) -> &'tcx List<LocalDefId> {
@@ -2231,7 +2272,7 @@ impl<'tcx> TyCtxt<'tcx> {
22312272
pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
22322273
where
22332274
I: Iterator<Item = T>,
2234-
T: CollectAndApply<Clause<'tcx>, &'tcx List<Clause<'tcx>>>,
2275+
T: CollectAndApply<Clause<'tcx>, Clauses<'tcx>>,
22352276
{
22362277
T::collect_and_apply(iter, |xs| self.mk_clauses(xs))
22372278
}

compiler/rustc_middle/src/ty/flags.rs

+9
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ impl FlagComputation {
3535
result
3636
}
3737

38+
pub fn for_clauses(clauses: &[ty::Clause<'_>]) -> FlagComputation {
39+
let mut result = FlagComputation::new();
40+
for c in clauses {
41+
result.add_flags(c.as_predicate().flags());
42+
result.add_exclusive_binder(c.as_predicate().outer_exclusive_binder());
43+
}
44+
result
45+
}
46+
3847
fn add_flags(&mut self, flags: TypeFlags) {
3948
self.flags = self.flags | flags;
4049
}

compiler/rustc_middle/src/ty/impls_ty.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@ use rustc_data_structures::stable_hasher::HashingControls;
1111
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
1212
use rustc_query_system::ich::StableHashingContext;
1313
use std::cell::RefCell;
14+
use std::ptr;
1415

15-
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for &'tcx ty::List<T>
16+
impl<'a, 'tcx, H, T> HashStable<StableHashingContext<'a>> for &'tcx ty::list::RawList<H, T>
1617
where
1718
T: HashStable<StableHashingContext<'a>>,
1819
{
1920
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
2021
thread_local! {
21-
static CACHE: RefCell<FxHashMap<(usize, usize, HashingControls), Fingerprint>> =
22+
static CACHE: RefCell<FxHashMap<(*const (), HashingControls), Fingerprint>> =
2223
RefCell::new(Default::default());
2324
}
2425

2526
let hash = CACHE.with(|cache| {
26-
let key = (self.as_ptr() as usize, self.len(), hcx.hashing_controls());
27+
let key = (ptr::from_ref(*self).cast::<()>(), hcx.hashing_controls());
2728
if let Some(&hash) = cache.borrow().get(&key) {
2829
return hash;
2930
}
@@ -40,7 +41,7 @@ where
4041
}
4142
}
4243

43-
impl<'a, 'tcx, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::List<T>
44+
impl<'a, 'tcx, H, T> ToStableHashKey<StableHashingContext<'a>> for &'tcx ty::list::RawList<H, T>
4445
where
4546
T: HashStable<StableHashingContext<'a>>,
4647
{

0 commit comments

Comments
 (0)