Skip to content

Commit 36c9f62

Browse files
GC support for solver types
A GC is triggered every X revisions, and is synchronous, unfortunately.
1 parent 776c818 commit 36c9f62

File tree

18 files changed

+566
-50
lines changed

18 files changed

+566
-50
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir-ty/src/next_solver/consts.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ pub struct Const<'db> {
2929
pub(super) interned: InternedRef<'db, ConstInterned>,
3030
}
3131

32-
#[derive(PartialEq, Eq, Hash)]
32+
#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
3333
#[repr(align(4))] // Required for `GenericArg` bit-tagging.
34-
pub(super) struct ConstInterned(WithCachedTypeInfo<ConstKind<'static>>);
34+
pub(super) struct ConstInterned(pub(super) WithCachedTypeInfo<ConstKind<'static>>);
3535

3636
impl_internable!(gc; ConstInterned);
3737
impl_stored_interned!(ConstInterned, Const, StoredConst);
@@ -219,15 +219,14 @@ pub struct Valtree<'db> {
219219

220220
impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Valtree<'db> {
221221
fn generic_visit_with(&self, visitor: &mut V) {
222-
visitor.on_interned(self.interned);
223-
self.inner().generic_visit_with(visitor);
222+
if visitor.on_interned(self.interned).is_continue() {
223+
self.inner().generic_visit_with(visitor);
224+
}
224225
}
225226
}
226227

227-
#[derive(Debug, PartialEq, Eq, Hash)]
228-
struct ValtreeInterned {
229-
bytes: ConstBytes<'static>,
230-
}
228+
#[derive(Debug, PartialEq, Eq, Hash, GenericTypeVisitable)]
229+
pub(super) struct ValtreeInterned(ConstBytes<'static>);
231230

232231
impl_internable!(gc; ValtreeInterned);
233232

@@ -240,12 +239,12 @@ impl<'db> Valtree<'db> {
240239
#[inline]
241240
pub fn new(bytes: ConstBytes<'db>) -> Self {
242241
let bytes = unsafe { std::mem::transmute::<ConstBytes<'db>, ConstBytes<'static>>(bytes) };
243-
Self { interned: Interned::new_gc(ValtreeInterned { bytes }) }
242+
Self { interned: Interned::new_gc(ValtreeInterned(bytes)) }
244243
}
245244

246245
#[inline]
247246
pub fn inner(&self) -> &ConstBytes<'db> {
248-
let inner = &self.interned.bytes;
247+
let inner = &self.interned.0;
249248
unsafe { std::mem::transmute::<&ConstBytes<'static>, &ConstBytes<'db>>(inner) }
250249
}
251250
}
@@ -277,8 +276,9 @@ impl<'db> IntoKind for Const<'db> {
277276

278277
impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Const<'db> {
279278
fn generic_visit_with(&self, visitor: &mut V) {
280-
visitor.on_interned(self.interned);
281-
self.kind().generic_visit_with(visitor);
279+
if visitor.on_interned(self.interned).is_continue() {
280+
self.kind().generic_visit_with(visitor);
281+
}
282282
}
283283
}
284284

crates/hir-ty/src/next_solver/interner.rs

Lines changed: 122 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//! Things related to the Interner in the next-trait-solver.
22
3-
use std::fmt;
3+
use std::{fmt, ops::ControlFlow};
44

55
use intern::{Interned, InternedRef, InternedSliceRef, impl_internable};
6+
use macros::GenericTypeVisitable;
67
use rustc_ast_ir::{FloatTy, IntTy, UintTy};
78
pub use tls_cache::clear_tls_solver_cache;
89
pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db};
@@ -21,8 +22,8 @@ use rustc_hash::FxHashSet;
2122
use rustc_index::bit_set::DenseBitSet;
2223
use rustc_type_ir::{
2324
AliasTermKind, AliasTyKind, BoundVar, CollectAndApply, CoroutineWitnessTypes, DebruijnIndex,
24-
EarlyBinder, FlagComputation, Flags, GenericArgKind, ImplPolarity, InferTy, Interner, TraitRef,
25-
TypeFlags, TypeVisitableExt, UniverseIndex, Upcast, Variance,
25+
EarlyBinder, FlagComputation, Flags, GenericArgKind, GenericTypeVisitable, ImplPolarity,
26+
InferTy, Interner, TraitRef, TypeFlags, TypeVisitableExt, UniverseIndex, Upcast, Variance,
2627
elaborate::elaborate,
2728
error::TypeError,
2829
fast_reject,
@@ -169,8 +170,9 @@ macro_rules! interned_slice {
169170
{
170171
#[inline]
171172
fn generic_visit_with(&self, visitor: &mut V) {
172-
visitor.on_interned_slice(self.interned);
173-
self.as_slice().iter().for_each(|it| it.generic_visit_with(visitor));
173+
if visitor.on_interned_slice(self.interned).is_continue() {
174+
self.as_slice().iter().for_each(|it| it.generic_visit_with(visitor));
175+
}
174176
}
175177
}
176178
};
@@ -293,8 +295,14 @@ macro_rules! impl_stored_interned {
293295
pub(crate) use impl_stored_interned;
294296

295297
pub trait WorldExposer {
296-
fn on_interned<T: intern::Internable>(&mut self, interned: InternedRef<'_, T>);
297-
fn on_interned_slice<T: intern::SliceInternable>(&mut self, interned: InternedSliceRef<'_, T>);
298+
fn on_interned<T: intern::Internable>(
299+
&mut self,
300+
interned: InternedRef<'_, T>,
301+
) -> ControlFlow<()>;
302+
fn on_interned_slice<T: intern::SliceInternable>(
303+
&mut self,
304+
interned: InternedSliceRef<'_, T>,
305+
) -> ControlFlow<()>;
298306
}
299307

300308
#[derive(Debug, Copy, Clone)]
@@ -803,7 +811,7 @@ pub struct Pattern<'db> {
803811
interned: InternedRef<'db, PatternInterned>,
804812
}
805813

806-
#[derive(PartialEq, Eq, Hash)]
814+
#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
807815
struct PatternInterned(PatternKind<'static>);
808816

809817
impl_internable!(gc; PatternInterned);
@@ -884,8 +892,9 @@ impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for Pattern<'db> {
884892

885893
impl<'db, V: WorldExposer> rustc_type_ir::GenericTypeVisitable<V> for Pattern<'db> {
886894
fn generic_visit_with(&self, visitor: &mut V) {
887-
visitor.on_interned(self.interned);
888-
self.kind().generic_visit_with(visitor);
895+
if visitor.on_interned(self.interned).is_continue() {
896+
self.kind().generic_visit_with(visitor);
897+
}
889898
}
890899
}
891900

@@ -2559,3 +2568,106 @@ mod tls_cache {
25592568
GLOBAL_CACHE.with_borrow_mut(|handle| *handle = None);
25602569
}
25612570
}
2571+
2572+
impl WorldExposer for intern::GarbageCollector {
2573+
fn on_interned<T: intern::Internable>(
2574+
&mut self,
2575+
interned: InternedRef<'_, T>,
2576+
) -> ControlFlow<()> {
2577+
self.mark_interned_alive(interned)
2578+
}
2579+
2580+
fn on_interned_slice<T: intern::SliceInternable>(
2581+
&mut self,
2582+
interned: InternedSliceRef<'_, T>,
2583+
) -> ControlFlow<()> {
2584+
self.mark_interned_slice_alive(interned)
2585+
}
2586+
}
2587+
2588+
/// # Safety
2589+
///
2590+
/// This cannot be called if there are some not-yet-recorded type values. Generally, if you have a mutable
2591+
/// reference to the database, and there are no other database - then you can call this safely, but you
2592+
/// also need to make sure to maintain the mutable reference while this is running.
2593+
pub unsafe fn collect_ty_garbage() {
2594+
let mut gc = intern::GarbageCollector::default();
2595+
2596+
gc.add_storage::<super::consts::ConstInterned>();
2597+
gc.add_storage::<super::consts::ValtreeInterned>();
2598+
gc.add_storage::<PatternInterned>();
2599+
gc.add_storage::<super::opaques::ExternalConstraintsInterned>();
2600+
gc.add_storage::<super::predicate::PredicateInterned>();
2601+
gc.add_storage::<super::region::RegionInterned>();
2602+
gc.add_storage::<super::ty::TyInterned>();
2603+
2604+
gc.add_slice_storage::<super::predicate::ClausesStorage>();
2605+
gc.add_slice_storage::<super::generic_arg::GenericArgsStorage>();
2606+
gc.add_slice_storage::<BoundVarKindsStorage>();
2607+
gc.add_slice_storage::<VariancesOfStorage>();
2608+
gc.add_slice_storage::<CanonicalVarsStorage>();
2609+
gc.add_slice_storage::<PatListStorage>();
2610+
gc.add_slice_storage::<super::opaques::PredefinedOpaquesStorage>();
2611+
gc.add_slice_storage::<super::opaques::SolverDefIdsStorage>();
2612+
gc.add_slice_storage::<super::predicate::BoundExistentialPredicatesStorage>();
2613+
gc.add_slice_storage::<super::region::RegionAssumptionsStorage>();
2614+
gc.add_slice_storage::<super::ty::TysStorage>();
2615+
2616+
unsafe { gc.collect() };
2617+
}
2618+
2619+
macro_rules! impl_gc_visit {
2620+
( $($ty:ty),* $(,)? ) => {
2621+
$(
2622+
impl ::intern::GcInternedVisit for $ty {
2623+
#[inline]
2624+
fn visit_with(&self, gc: &mut ::intern::GarbageCollector) {
2625+
self.generic_visit_with(gc);
2626+
}
2627+
}
2628+
)*
2629+
};
2630+
}
2631+
2632+
impl_gc_visit!(
2633+
super::consts::ConstInterned,
2634+
super::consts::ValtreeInterned,
2635+
PatternInterned,
2636+
super::opaques::ExternalConstraintsInterned,
2637+
super::predicate::PredicateInterned,
2638+
super::region::RegionInterned,
2639+
super::ty::TyInterned,
2640+
super::predicate::ClausesCachedTypeInfo,
2641+
);
2642+
2643+
macro_rules! impl_gc_visit_slice {
2644+
( $($ty:ty),* $(,)? ) => {
2645+
$(
2646+
impl ::intern::GcInternedSliceVisit for $ty {
2647+
#[inline]
2648+
fn visit_header(header: &<Self as ::intern::SliceInternable>::Header, gc: &mut ::intern::GarbageCollector) {
2649+
header.generic_visit_with(gc);
2650+
}
2651+
2652+
#[inline]
2653+
fn visit_slice(header: &[<Self as ::intern::SliceInternable>::SliceType], gc: &mut ::intern::GarbageCollector) {
2654+
header.generic_visit_with(gc);
2655+
}
2656+
}
2657+
)*
2658+
};
2659+
}
2660+
2661+
impl_gc_visit_slice!(
2662+
super::predicate::ClausesStorage,
2663+
super::generic_arg::GenericArgsStorage,
2664+
BoundVarKindsStorage,
2665+
VariancesOfStorage,
2666+
CanonicalVarsStorage,
2667+
PatListStorage,
2668+
super::opaques::PredefinedOpaquesStorage,
2669+
super::opaques::SolverDefIdsStorage,
2670+
super::predicate::BoundExistentialPredicatesStorage,
2671+
super::region::RegionAssumptionsStorage,
2672+
super::ty::TysStorage,
2673+
);

crates/hir-ty/src/next_solver/opaques.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Things related to opaques in the next-trait-solver.
22
33
use intern::{Interned, InternedRef, impl_internable};
4+
use macros::GenericTypeVisitable;
45
use rustc_ast_ir::try_visit;
56
use rustc_type_ir::inherent::SliceLike;
67

@@ -30,8 +31,8 @@ pub struct ExternalConstraints<'db> {
3031
interned: InternedRef<'db, ExternalConstraintsInterned>,
3132
}
3233

33-
#[derive(PartialEq, Eq, Hash)]
34-
struct ExternalConstraintsInterned(ExternalConstraintsData<'static>);
34+
#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
35+
pub(super) struct ExternalConstraintsInterned(ExternalConstraintsData<'static>);
3536

3637
impl_internable!(gc; ExternalConstraintsInterned);
3738

crates/hir-ty/src/next_solver/predicate.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ pub struct Predicate<'db> {
186186
interned: InternedRef<'db, PredicateInterned>,
187187
}
188188

189-
#[derive(PartialEq, Eq, Hash)]
190-
struct PredicateInterned(WithCachedTypeInfo<Binder<'static, PredicateKind<'static>>>);
189+
#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
190+
pub(super) struct PredicateInterned(WithCachedTypeInfo<Binder<'static, PredicateKind<'static>>>);
191191

192192
impl_internable!(gc; PredicateInterned);
193193

@@ -252,7 +252,10 @@ impl<'db> std::fmt::Debug for Predicate<'db> {
252252
}
253253
}
254254

255-
impl_slice_internable!(gc; ClausesStorage, WithCachedTypeInfo<()>, Clause<'static>);
255+
#[derive(Clone, Copy, PartialEq, Eq, Hash, GenericTypeVisitable)]
256+
pub struct ClausesCachedTypeInfo(WithCachedTypeInfo<()>);
257+
258+
impl_slice_internable!(gc; ClausesStorage, ClausesCachedTypeInfo, Clause<'static>);
256259
impl_stored_interned_slice!(ClausesStorage, Clauses, StoredClauses);
257260

258261
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
@@ -277,11 +280,11 @@ impl<'db> Clauses<'db> {
277280
pub fn new_from_slice(slice: &[Clause<'db>]) -> Self {
278281
let slice = unsafe { ::std::mem::transmute::<&[Clause<'db>], &[Clause<'static>]>(slice) };
279282
let flags = FlagComputation::<DbInterner<'db>>::for_clauses(slice);
280-
let flags = WithCachedTypeInfo {
283+
let flags = ClausesCachedTypeInfo(WithCachedTypeInfo {
281284
internee: (),
282285
flags: flags.flags,
283286
outer_exclusive_binder: flags.outer_exclusive_binder,
284-
};
287+
});
285288
Self { interned: InternedSlice::from_header_and_slice(flags, slice) }
286289
}
287290

@@ -400,20 +403,21 @@ impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for Clauses<'db> {
400403

401404
impl<'db, V: super::WorldExposer> rustc_type_ir::GenericTypeVisitable<V> for Clauses<'db> {
402405
fn generic_visit_with(&self, visitor: &mut V) {
403-
visitor.on_interned_slice(self.interned);
404-
self.as_slice().iter().for_each(|it| it.generic_visit_with(visitor));
406+
if visitor.on_interned_slice(self.interned).is_continue() {
407+
self.as_slice().iter().for_each(|it| it.generic_visit_with(visitor));
408+
}
405409
}
406410
}
407411

408412
impl<'db> rustc_type_ir::Flags for Clauses<'db> {
409413
#[inline]
410414
fn flags(&self) -> rustc_type_ir::TypeFlags {
411-
self.interned.header.header.flags
415+
self.interned.header.header.0.flags
412416
}
413417

414418
#[inline]
415419
fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
416-
self.interned.header.header.outer_exclusive_binder
420+
self.interned.header.header.0.outer_exclusive_binder
417421
}
418422
}
419423

@@ -430,7 +434,9 @@ impl<'db> rustc_type_ir::TypeSuperVisitable<DbInterner<'db>> for Clauses<'db> {
430434
pub struct Clause<'db>(pub(crate) Predicate<'db>);
431435

432436
// We could cram the reveal into the clauses like rustc does, probably
433-
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeVisitable, TypeFoldable)]
437+
#[derive(
438+
Copy, Clone, Debug, Hash, PartialEq, Eq, TypeVisitable, TypeFoldable, GenericTypeVisitable,
439+
)]
434440
pub struct ParamEnv<'db> {
435441
pub(crate) clauses: Clauses<'db>,
436442
}
@@ -474,8 +480,9 @@ impl<'db> TypeVisitable<DbInterner<'db>> for Predicate<'db> {
474480

475481
impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Predicate<'db> {
476482
fn generic_visit_with(&self, visitor: &mut V) {
477-
visitor.on_interned(self.interned);
478-
self.kind().generic_visit_with(visitor);
483+
if visitor.on_interned(self.interned).is_continue() {
484+
self.kind().generic_visit_with(visitor);
485+
}
479486
}
480487
}
481488

crates/hir-ty/src/next_solver/region.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use hir_def::LifetimeParamId;
44
use intern::{Interned, InternedRef, Symbol, impl_internable};
5+
use macros::GenericTypeVisitable;
56
use rustc_type_ir::{
67
BoundVar, BoundVarIndexKind, DebruijnIndex, Flags, GenericTypeVisitable, INNERMOST, RegionVid,
78
TypeFlags, TypeFoldable, TypeVisitable,
@@ -25,7 +26,7 @@ pub struct Region<'db> {
2526
pub(super) interned: InternedRef<'db, RegionInterned>,
2627
}
2728

28-
#[derive(PartialEq, Eq, Hash)]
29+
#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
2930
#[repr(align(4))] // Required for `GenericArg` bit-tagging.
3031
pub(super) struct RegionInterned(RegionKind<'static>);
3132

@@ -388,8 +389,9 @@ impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderRegion {
388389

389390
impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Region<'db> {
390391
fn generic_visit_with(&self, visitor: &mut V) {
391-
visitor.on_interned(self.interned);
392-
self.kind().generic_visit_with(visitor);
392+
if visitor.on_interned(self.interned).is_continue() {
393+
self.kind().generic_visit_with(visitor);
394+
}
393395
}
394396
}
395397

0 commit comments

Comments
 (0)