Skip to content

Commit 4709f45

Browse files
committed
Cache flags and escaping vars for predicates
Also hash predicates by address
1 parent 4eef51a commit 4709f45

File tree

6 files changed

+202
-28
lines changed

6 files changed

+202
-28
lines changed

src/librustc_middle/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ macro_rules! arena_types {
100100

101101
// Interned types
102102
[] tys: rustc_middle::ty::TyS<$tcx>, rustc_middle::ty::TyS<'_x>;
103+
[] predicates: rustc_middle::ty::PredicateInner<$tcx>, rustc_middle::ty::PredicateInner<'_x>;
103104

104105
// HIR query types
105106
[few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>, rustc_middle::hir::map::IndexedHir<'_x>;

src/librustc_middle/ty/context.rs

+47-10
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ use crate::ty::TyKind::*;
1919
use crate::ty::{
2020
self, query, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid,
2121
DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy,
22-
IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, ProjectionTy,
23-
Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut,
22+
IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
23+
ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
24+
TyVid, TypeAndMut,
2425
};
2526
use rustc_ast::ast;
2627
use rustc_ast::expand::allocator::AllocatorKind;
@@ -76,7 +77,7 @@ pub struct CtxtInterners<'tcx> {
7677
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo>>,
7778
region: InternedSet<'tcx, RegionKind>,
7879
existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
79-
predicate_kind: InternedSet<'tcx, PredicateKind<'tcx>>,
80+
predicate: InternedSet<'tcx, PredicateInner<'tcx>>,
8081
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
8182
projs: InternedSet<'tcx, List<ProjectionKind>>,
8283
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
@@ -95,7 +96,7 @@ impl<'tcx> CtxtInterners<'tcx> {
9596
region: Default::default(),
9697
existential_predicates: Default::default(),
9798
canonical_var_infos: Default::default(),
98-
predicate_kind: Default::default(),
99+
predicate: Default::default(),
99100
predicates: Default::default(),
100101
projs: Default::default(),
101102
place_elems: Default::default(),
@@ -123,6 +124,23 @@ impl<'tcx> CtxtInterners<'tcx> {
123124
})
124125
.0
125126
}
127+
128+
#[inline(never)]
129+
fn intern_predicate(&self, kind: PredicateKind<'tcx>) -> &'tcx PredicateInner<'tcx> {
130+
self.predicate
131+
.intern(kind, |kind| {
132+
let flags = super::flags::FlagComputation::for_predicate(&kind);
133+
134+
let predicate_struct = PredicateInner {
135+
kind,
136+
flags: flags.flags,
137+
outer_exclusive_binder: flags.outer_exclusive_binder,
138+
};
139+
140+
Interned(self.arena.alloc(predicate_struct))
141+
})
142+
.0
143+
}
126144
}
127145

128146
pub struct CommonTypes<'tcx> {
@@ -1598,7 +1616,7 @@ macro_rules! nop_list_lift {
15981616
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
15991617
nop_lift! {region; Region<'a> => Region<'tcx>}
16001618
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
1601-
nop_lift! {predicate_kind; &'a PredicateKind<'a> => &'tcx PredicateKind<'tcx>}
1619+
nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
16021620

16031621
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
16041622
nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
@@ -1957,6 +1975,26 @@ impl<'tcx> Borrow<TyKind<'tcx>> for Interned<'tcx, TyS<'tcx>> {
19571975
&self.0.kind
19581976
}
19591977
}
1978+
// N.B., an `Interned<PredicateInner>` compares and hashes as a `PredicateKind`.
1979+
impl<'tcx> PartialEq for Interned<'tcx, PredicateInner<'tcx>> {
1980+
fn eq(&self, other: &Interned<'tcx, PredicateInner<'tcx>>) -> bool {
1981+
self.0.kind == other.0.kind
1982+
}
1983+
}
1984+
1985+
impl<'tcx> Eq for Interned<'tcx, PredicateInner<'tcx>> {}
1986+
1987+
impl<'tcx> Hash for Interned<'tcx, PredicateInner<'tcx>> {
1988+
fn hash<H: Hasher>(&self, s: &mut H) {
1989+
self.0.kind.hash(s)
1990+
}
1991+
}
1992+
1993+
impl<'tcx> Borrow<PredicateKind<'tcx>> for Interned<'tcx, PredicateInner<'tcx>> {
1994+
fn borrow<'a>(&'a self) -> &'a PredicateKind<'tcx> {
1995+
&self.0.kind
1996+
}
1997+
}
19601998

19611999
// N.B., an `Interned<List<T>>` compares and hashes as its elements.
19622000
impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List<T>> {
@@ -2023,11 +2061,10 @@ macro_rules! direct_interners {
20232061
}
20242062
}
20252063

2026-
direct_interners!(
2064+
direct_interners! {
20272065
region: mk_region(RegionKind),
20282066
const_: mk_const(Const<'tcx>),
2029-
predicate_kind: intern_predicate_kind(PredicateKind<'tcx>),
2030-
);
2067+
}
20312068

20322069
macro_rules! slice_interners {
20332070
($($field:ident: $method:ident($ty:ty)),+) => (
@@ -2091,8 +2128,8 @@ impl<'tcx> TyCtxt<'tcx> {
20912128

20922129
#[inline]
20932130
pub fn mk_predicate(&self, kind: PredicateKind<'tcx>) -> Predicate<'tcx> {
2094-
let kind = self.intern_predicate_kind(kind);
2095-
Predicate { kind }
2131+
let inner = self.interners.intern_predicate(kind);
2132+
Predicate { inner }
20962133
}
20972134

20982135
pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {

src/librustc_middle/ty/flags.rs

+73-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::ty::subst::{GenericArg, GenericArgKind};
22
use crate::ty::{self, InferConst, Ty, TypeFlags};
3+
use std::slice;
34

45
#[derive(Debug)]
56
pub struct FlagComputation {
@@ -21,6 +22,12 @@ impl FlagComputation {
2122
result
2223
}
2324

25+
pub fn for_predicate(kind: &ty::PredicateKind<'_>) -> FlagComputation {
26+
let mut result = FlagComputation::new();
27+
result.add_predicate_kind(kind);
28+
result
29+
}
30+
2431
pub fn for_const(c: &ty::Const<'_>) -> TypeFlags {
2532
let mut result = FlagComputation::new();
2633
result.add_const(c);
@@ -32,7 +39,7 @@ impl FlagComputation {
3239
}
3340

3441
/// indicates that `self` refers to something at binding level `binder`
35-
fn add_binder(&mut self, binder: ty::DebruijnIndex) {
42+
fn add_bound_var(&mut self, binder: ty::DebruijnIndex) {
3643
let exclusive_binder = binder.shifted_in(1);
3744
self.add_exclusive_binder(exclusive_binder);
3845
}
@@ -46,7 +53,7 @@ impl FlagComputation {
4653

4754
/// Adds the flags/depth from a set of types that appear within the current type, but within a
4855
/// region binder.
49-
fn add_bound_computation(&mut self, computation: &FlagComputation) {
56+
fn add_bound_computation(&mut self, computation: FlagComputation) {
5057
self.add_flags(computation.flags);
5158

5259
// The types that contributed to `computation` occurred within
@@ -84,15 +91,15 @@ impl FlagComputation {
8491
&ty::GeneratorWitness(ref ts) => {
8592
let mut computation = FlagComputation::new();
8693
computation.add_tys(&ts.skip_binder()[..]);
87-
self.add_bound_computation(&computation);
94+
self.add_bound_computation(computation);
8895
}
8996

9097
&ty::Closure(_, ref substs) => {
9198
self.add_substs(substs);
9299
}
93100

94101
&ty::Bound(debruijn, _) => {
95-
self.add_binder(debruijn);
102+
self.add_bound_var(debruijn);
96103
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
97104
}
98105

@@ -134,12 +141,12 @@ impl FlagComputation {
134141
ty::ExistentialPredicate::Projection(p) => {
135142
let mut proj_computation = FlagComputation::new();
136143
proj_computation.add_existential_projection(&p);
137-
self.add_bound_computation(&proj_computation);
144+
self.add_bound_computation(proj_computation);
138145
}
139146
ty::ExistentialPredicate::AutoTrait(_) => {}
140147
}
141148
}
142-
self.add_bound_computation(&computation);
149+
self.add_bound_computation(computation);
143150
self.add_region(r);
144151
}
145152

@@ -173,6 +180,63 @@ impl FlagComputation {
173180
}
174181
}
175182

183+
fn add_predicate_kind(&mut self, kind: &ty::PredicateKind<'_>) {
184+
match kind {
185+
ty::PredicateKind::Trait(trait_pred, _constness) => {
186+
let mut computation = FlagComputation::new();
187+
computation.add_substs(trait_pred.skip_binder().trait_ref.substs);
188+
189+
self.add_bound_computation(computation);
190+
}
191+
ty::PredicateKind::RegionOutlives(poly_outlives) => {
192+
let mut computation = FlagComputation::new();
193+
let ty::OutlivesPredicate(a, b) = poly_outlives.skip_binder();
194+
computation.add_region(a);
195+
computation.add_region(b);
196+
197+
self.add_bound_computation(computation);
198+
}
199+
ty::PredicateKind::TypeOutlives(poly_outlives) => {
200+
let mut computation = FlagComputation::new();
201+
let ty::OutlivesPredicate(ty, region) = poly_outlives.skip_binder();
202+
computation.add_ty(ty);
203+
computation.add_region(region);
204+
205+
self.add_bound_computation(computation);
206+
}
207+
ty::PredicateKind::Subtype(poly_subtype) => {
208+
let mut computation = FlagComputation::new();
209+
let ty::SubtypePredicate { a_is_expected: _, a, b } = poly_subtype.skip_binder();
210+
computation.add_ty(a);
211+
computation.add_ty(b);
212+
213+
self.add_bound_computation(computation);
214+
}
215+
ty::PredicateKind::Projection(projection) => {
216+
let mut computation = FlagComputation::new();
217+
let ty::ProjectionPredicate { projection_ty, ty } = projection.skip_binder();
218+
computation.add_projection_ty(projection_ty);
219+
computation.add_ty(ty);
220+
221+
self.add_bound_computation(computation);
222+
}
223+
ty::PredicateKind::WellFormed(arg) => {
224+
self.add_substs(slice::from_ref(arg));
225+
}
226+
ty::PredicateKind::ObjectSafe(_def_id) => {}
227+
ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
228+
self.add_substs(substs);
229+
}
230+
ty::PredicateKind::ConstEvaluatable(_def_id, substs) => {
231+
self.add_substs(substs);
232+
}
233+
ty::PredicateKind::ConstEquate(expected, found) => {
234+
self.add_const(expected);
235+
self.add_const(found);
236+
}
237+
}
238+
}
239+
176240
fn add_ty(&mut self, ty: Ty<'_>) {
177241
self.add_flags(ty.flags);
178242
self.add_exclusive_binder(ty.outer_exclusive_binder);
@@ -190,13 +254,13 @@ impl FlagComputation {
190254
computation.add_tys(fn_sig.skip_binder().inputs());
191255
computation.add_ty(fn_sig.skip_binder().output());
192256

193-
self.add_bound_computation(&computation);
257+
self.add_bound_computation(computation);
194258
}
195259

196260
fn add_region(&mut self, r: ty::Region<'_>) {
197261
self.add_flags(r.type_flags());
198262
if let ty::ReLateBound(debruijn, _) = *r {
199-
self.add_binder(debruijn);
263+
self.add_bound_var(debruijn);
200264
}
201265
}
202266

@@ -215,7 +279,7 @@ impl FlagComputation {
215279
}
216280
}
217281
ty::ConstKind::Bound(debruijn, _) => {
218-
self.add_binder(debruijn);
282+
self.add_bound_var(debruijn);
219283
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
220284
}
221285
ty::ConstKind::Param(_) => {

src/librustc_middle/ty/fold.rs

+16
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
//! These methods return true to indicate that the visitor has found what it is
3232
//! looking for, and does not need to visit anything else.
3333
34+
use crate::ty::structural_impls::PredicateVisitor;
3435
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
3536
use rustc_hir as hir;
3637
use rustc_hir::def_id::DefId;
@@ -905,6 +906,12 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
905906
}
906907
}
907908

909+
impl<'tcx> PredicateVisitor<'tcx> for HasEscapingVarsVisitor {
910+
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool {
911+
predicate.inner.outer_exclusive_binder > self.outer_index
912+
}
913+
}
914+
908915
// FIXME: Optimize for checking for infer flags
909916
struct HasTypeFlagsVisitor {
910917
flags: ty::TypeFlags,
@@ -929,6 +936,15 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
929936
}
930937
}
931938

939+
impl<'tcx> PredicateVisitor<'tcx> for HasTypeFlagsVisitor {
940+
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool {
941+
debug!(
942+
"HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
943+
predicate, predicate.inner.flags, self.flags
944+
);
945+
predicate.inner.flags.intersects(self.flags)
946+
}
947+
}
932948
/// Collects all the late-bound regions at the innermost binding level
933949
/// into a hash set.
934950
struct LateBoundRegionsCollector {

src/librustc_middle/ty/mod.rs

+40-6
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ impl<'tcx> Hash for TyS<'tcx> {
628628
}
629629
}
630630

631-
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::TyS<'tcx> {
631+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
632632
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
633633
let ty::TyS {
634634
ref kind,
@@ -1002,16 +1002,35 @@ impl<'tcx> GenericPredicates<'tcx> {
10021002
}
10031003
}
10041004

1005-
#[derive(Clone, Copy, Hash, RustcEncodable, RustcDecodable, Lift)]
1006-
#[derive(HashStable)]
1005+
#[derive(Debug)]
1006+
crate struct PredicateInner<'tcx> {
1007+
kind: PredicateKind<'tcx>,
1008+
flags: TypeFlags,
1009+
/// See the comment for the corresponding field of [TyS].
1010+
outer_exclusive_binder: ty::DebruijnIndex,
1011+
}
1012+
1013+
#[cfg(target_arch = "x86_64")]
1014+
static_assert_size!(PredicateInner<'_>, 40);
1015+
1016+
#[derive(Clone, Copy, Lift)]
10071017
pub struct Predicate<'tcx> {
1008-
kind: &'tcx PredicateKind<'tcx>,
1018+
inner: &'tcx PredicateInner<'tcx>,
10091019
}
10101020

1021+
impl rustc_serialize::UseSpecializedEncodable for Predicate<'_> {}
1022+
impl rustc_serialize::UseSpecializedDecodable for Predicate<'_> {}
1023+
10111024
impl<'tcx> PartialEq for Predicate<'tcx> {
10121025
fn eq(&self, other: &Self) -> bool {
10131026
// `self.kind` is always interned.
1014-
ptr::eq(self.kind, other.kind)
1027+
ptr::eq(self.inner, other.inner)
1028+
}
1029+
}
1030+
1031+
impl Hash for Predicate<'_> {
1032+
fn hash<H: Hasher>(&self, s: &mut H) {
1033+
(self.inner as *const PredicateInner<'_>).hash(s)
10151034
}
10161035
}
10171036

@@ -1020,7 +1039,22 @@ impl<'tcx> Eq for Predicate<'tcx> {}
10201039
impl<'tcx> Predicate<'tcx> {
10211040
#[inline(always)]
10221041
pub fn kind(self) -> &'tcx PredicateKind<'tcx> {
1023-
self.kind
1042+
&self.inner.kind
1043+
}
1044+
}
1045+
1046+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
1047+
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
1048+
let PredicateInner {
1049+
ref kind,
1050+
1051+
// The other fields just provide fast access to information that is
1052+
// also contained in `kind`, so no need to hash them.
1053+
flags: _,
1054+
outer_exclusive_binder: _,
1055+
} = self.inner;
1056+
1057+
kind.hash_stable(hcx, hasher);
10241058
}
10251059
}
10261060

0 commit comments

Comments
 (0)