Skip to content

Commit f802ee1

Browse files
committed
Cache flags and escaping vars for predicates
Also hash predicates by address
1 parent 8ea55f1 commit f802ee1

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> {
@@ -1627,7 +1645,7 @@ macro_rules! nop_list_lift {
16271645
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
16281646
nop_lift! {region; Region<'a> => Region<'tcx>}
16291647
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
1630-
nop_lift! {predicate_kind; &'a PredicateKind<'a> => &'tcx PredicateKind<'tcx>}
1648+
nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
16311649

16321650
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
16331651
nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
@@ -1986,6 +2004,26 @@ impl<'tcx> Borrow<TyKind<'tcx>> for Interned<'tcx, TyS<'tcx>> {
19862004
&self.0.kind
19872005
}
19882006
}
2007+
// N.B., an `Interned<PredicateInner>` compares and hashes as a `PredicateKind`.
2008+
impl<'tcx> PartialEq for Interned<'tcx, PredicateInner<'tcx>> {
2009+
fn eq(&self, other: &Interned<'tcx, PredicateInner<'tcx>>) -> bool {
2010+
self.0.kind == other.0.kind
2011+
}
2012+
}
2013+
2014+
impl<'tcx> Eq for Interned<'tcx, PredicateInner<'tcx>> {}
2015+
2016+
impl<'tcx> Hash for Interned<'tcx, PredicateInner<'tcx>> {
2017+
fn hash<H: Hasher>(&self, s: &mut H) {
2018+
self.0.kind.hash(s)
2019+
}
2020+
}
2021+
2022+
impl<'tcx> Borrow<PredicateKind<'tcx>> for Interned<'tcx, PredicateInner<'tcx>> {
2023+
fn borrow<'a>(&'a self) -> &'a PredicateKind<'tcx> {
2024+
&self.0.kind
2025+
}
2026+
}
19892027

19902028
// N.B., an `Interned<List<T>>` compares and hashes as its elements.
19912029
impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List<T>> {
@@ -2052,11 +2090,10 @@ macro_rules! direct_interners {
20522090
}
20532091
}
20542092

2055-
direct_interners!(
2093+
direct_interners! {
20562094
region: mk_region(RegionKind),
20572095
const_: mk_const(Const<'tcx>),
2058-
predicate_kind: intern_predicate_kind(PredicateKind<'tcx>),
2059-
);
2096+
}
20602097

20612098
macro_rules! slice_interners {
20622099
($($field:ident: $method:ident($ty:ty)),+) => (
@@ -2127,8 +2164,8 @@ impl<'tcx> TyCtxt<'tcx> {
21272164

21282165
#[inline]
21292166
pub fn mk_predicate(&self, kind: PredicateKind<'tcx>) -> Predicate<'tcx> {
2130-
let kind = self.intern_predicate_kind(kind);
2131-
Predicate { kind }
2167+
let inner = self.interners.intern_predicate(kind);
2168+
Predicate { inner }
21322169
}
21332170

21342171
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
}
97104

98105
&ty::Placeholder(..) => {
@@ -133,12 +140,12 @@ impl FlagComputation {
133140
ty::ExistentialPredicate::Projection(p) => {
134141
let mut proj_computation = FlagComputation::new();
135142
proj_computation.add_existential_projection(&p);
136-
self.add_bound_computation(&proj_computation);
143+
self.add_bound_computation(proj_computation);
137144
}
138145
ty::ExistentialPredicate::AutoTrait(_) => {}
139146
}
140147
}
141-
self.add_bound_computation(&computation);
148+
self.add_bound_computation(computation);
142149
self.add_region(r);
143150
}
144151

@@ -172,6 +179,63 @@ impl FlagComputation {
172179
}
173180
}
174181

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

192-
self.add_bound_computation(&computation);
256+
self.add_bound_computation(computation);
193257
}
194258

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

@@ -214,7 +278,7 @@ impl FlagComputation {
214278
}
215279
}
216280
ty::ConstKind::Bound(debruijn, _) => {
217-
self.add_binder(debruijn);
281+
self.add_bound_var(debruijn);
218282
}
219283
ty::ConstKind::Param(_) => {
220284
self.add_flags(TypeFlags::HAS_CT_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;
@@ -908,6 +909,12 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
908909
}
909910
}
910911

912+
impl<'tcx> PredicateVisitor<'tcx> for HasEscapingVarsVisitor {
913+
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool {
914+
predicate.inner.outer_exclusive_binder > self.outer_index
915+
}
916+
}
917+
911918
// FIXME: Optimize for checking for infer flags
912919
struct HasTypeFlagsVisitor {
913920
flags: ty::TypeFlags,
@@ -932,6 +939,15 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
932939
}
933940
}
934941

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

src/librustc_middle/ty/mod.rs

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

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

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

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

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

0 commit comments

Comments
 (0)