Skip to main content

hir_ty/next_solver/
interner.rs

1//! Things related to the Interner in the next-trait-solver.
2
3use std::{fmt, ops::ControlFlow};
4
5use either::Either;
6use intern::{Interned, InternedRef, InternedSliceRef, impl_internable};
7use macros::GenericTypeVisitable;
8use rustc_abi::ReprOptions;
9use rustc_ast_ir::{FloatTy, IntTy, UintTy};
10pub use tls_cache::clear_tls_solver_cache;
11pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db};
12
13use base_db::Crate;
14use hir_def::{
15    AdtId, CallableDefId, EnumId, GenericDefId, GenericParamId, HasModule, ItemContainerId,
16    StructId, UnionId, VariantId,
17    attrs::AttrFlags,
18    expr_store::{ExpressionStore, StoreVisitor},
19    hir::{ClosureKind as HirClosureKind, CoroutineKind as HirCoroutineKind, ExprId, PatId},
20    lang_item::LangItems,
21    signatures::{
22        EnumFlags, EnumSignature, FnFlags, FunctionSignature, ImplFlags, ImplSignature,
23        StructFlags, StructSignature, TraitFlags, TraitSignature, UnionSignature,
24    },
25};
26use rustc_abi::ExternAbi;
27use rustc_index::bit_set::DenseBitSet;
28use rustc_type_ir::{
29    AliasTy, BoundVar, CoroutineWitnessTypes, DebruijnIndex, EarlyBinder, FlagComputation, Flags,
30    FnSigKind, GenericArgKind, GenericTypeVisitable, ImplPolarity, InferTy, Interner, TraitRef,
31    TypeFlags, TypeVisitableExt, Variance, VisitorResult,
32    error::TypeError,
33    fast_reject,
34    inherent::{self, Const as _, GenericsOf, IntoKind, SliceLike as _, Span as _, Ty as _},
35    lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem},
36    solve::{AdtDestructorKind, SizedTraitKind},
37    try_visit,
38};
39
40use crate::{
41    InferBodyId, Span,
42    db::{HirDatabase, InternedClosure, InternedCoroutineId},
43    lower::GenericPredicates,
44    method_resolution::TraitImpls,
45    next_solver::{
46        AdtIdWrapper, AliasTermKind, AliasTyKind, AnyImplId, BoundConst, CallableIdWrapper,
47        CanonicalVarKind, ClosureIdWrapper, Consts, CoroutineClosureIdWrapper, CoroutineIdWrapper,
48        Ctor, FnSig, FreeConstAliasId, FreeTermAliasId, FreeTyAliasId, FxIndexMap,
49        GeneralConstIdWrapper, ImplOrTraitAssocConstId, ImplOrTraitAssocTermId,
50        ImplOrTraitAssocTyId, InherentAssocConstId, InherentAssocTermId, InherentAssocTyId,
51        LateParamRegion, OpaqueTyIdWrapper, OpaqueTypeKey, RegionAssumptions, ScalarInt,
52        SimplifiedType, SolverContext, SolverDefIds, TermId, TraitAssocConstId, TraitAssocTermId,
53        TraitAssocTyId, TraitIdWrapper, TypeAliasIdWrapper, UnevaluatedConst,
54        util::{ItemBounds, impl_super_outlives},
55    },
56};
57
58use super::{
59    Binder, BoundExistentialPredicates, BoundTy, BoundTyKind, Clause, ClauseKind, Clauses, Const,
60    ErrorGuaranteed, ExprConst, ExternalConstraints, GenericArg, GenericArgs, ParamConst, ParamEnv,
61    ParamTy, PredefinedOpaques, Predicate, SolverDefId, Term, Ty, TyKind, Tys, ValTree, ValueConst,
62    abi::Safety,
63    fold::{BoundVarReplacer, BoundVarReplacerDelegate, FnMutDelegate},
64    generics::{Generics, generics},
65    region::{BoundRegion, BoundRegionKind, EarlyParamRegion, Region},
66    util::sizedness_constraint_for_ty,
67};
68
69macro_rules! interned_slice {
70    ($storage:ident, $name:ident, $stored_name:ident, $default_types_field:ident, $ty_db:ty, $ty_static:ty $(,)?) => {
71        const _: () = {
72            #[allow(unused_lifetimes)]
73            fn _ensure_correct_types<'db: 'static>(v: $ty_db) -> $ty_static { v }
74        };
75
76        ::intern::impl_slice_internable!(gc; $storage, (), $ty_static);
77
78        #[derive(Clone, Copy, PartialEq, Eq, Hash)]
79        pub struct $name<'db> {
80            interned: ::intern::InternedSliceRef<'db, $storage>,
81        }
82
83        impl<'db> std::fmt::Debug for $name<'db> {
84            fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85                self.as_slice().fmt(fmt)
86            }
87        }
88
89        impl<'db> $name<'db> {
90            #[inline]
91            pub fn empty() -> Self {
92                $crate::next_solver::default_types().empty.$default_types_field
93            }
94
95            #[inline]
96            pub fn new_from_slice(slice: &[$ty_db]) -> Self {
97                if slice.is_empty() {
98                    // Common case: avoid looking up the empty slice.
99                    Self::empty()
100                } else {
101                    Self::new_from_slice_no_empty_check(slice)
102                }
103            }
104
105            /// Same as [`Self::new_from_slice()`] but won't use the global empty slice `slice.is_empty()`, because someone
106            /// needs to intern the global slice as well.
107            #[inline]
108            pub(crate) fn new_from_slice_no_empty_check(slice: &[$ty_db]) -> Self {
109                let slice = unsafe { ::std::mem::transmute::<&[$ty_db], &[$ty_static]>(slice) };
110                Self { interned: ::intern::InternedSlice::from_header_and_slice((), slice) }
111            }
112
113            #[inline]
114            pub fn new_from_iter<I, T>(args: I) -> T::Output
115            where
116                I: IntoIterator<Item = T>,
117                T: ::rustc_type_ir::CollectAndApply<$ty_db, Self>,
118            {
119                ::rustc_type_ir::CollectAndApply::collect_and_apply(args.into_iter(), |g| {
120                    Self::new_from_slice(g)
121                })
122            }
123
124            #[inline]
125            pub fn as_slice(self) -> &'db [$ty_db] {
126                let slice = &self.interned.get().slice;
127                unsafe { ::std::mem::transmute::<&[$ty_static], &[$ty_db]>(slice) }
128            }
129
130            #[inline]
131            pub fn iter(self) -> ::std::iter::Copied<::std::slice::Iter<'db, $ty_db>> {
132                self.as_slice().iter().copied()
133            }
134
135            #[inline]
136            pub fn len(self) -> usize {
137                self.as_slice().len()
138            }
139
140            #[inline]
141            pub fn is_empty(self) -> bool {
142                self.as_slice().is_empty()
143            }
144        }
145
146        impl<'db> IntoIterator for $name<'db> {
147            type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, $ty_db>>;
148            type Item = $ty_db;
149            #[inline]
150            fn into_iter(self) -> Self::IntoIter { self.iter() }
151        }
152
153        impl<'db> ::std::ops::Deref for $name<'db> {
154            type Target = [$ty_db];
155
156            #[inline]
157            fn deref(&self) -> &Self::Target {
158                (*self).as_slice()
159            }
160        }
161
162        impl<'db> rustc_type_ir::inherent::SliceLike for $name<'db> {
163            type Item = $ty_db;
164
165            type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, $ty_db>>;
166
167            #[inline]
168            fn iter(self) -> Self::IntoIter {
169                self.iter()
170            }
171
172            #[inline]
173            fn as_slice(&self) -> &[Self::Item] {
174                (*self).as_slice()
175            }
176        }
177
178        impl<'db> Default for $name<'db> {
179            #[inline]
180            fn default() -> Self {
181                $name::empty()
182            }
183        }
184
185
186        impl<'db, V: $crate::next_solver::interner::WorldExposer>
187            rustc_type_ir::GenericTypeVisitable<V> for $name<'db>
188        {
189            #[inline]
190            fn generic_visit_with(&self, visitor: &mut V) {
191                if visitor.on_interned_slice(self.interned).is_continue() {
192                    self.as_slice().iter().for_each(|it| it.generic_visit_with(visitor));
193                }
194            }
195        }
196
197        $crate::next_solver::interner::impl_stored_interned_slice!($storage, $name, $stored_name);
198    };
199}
200pub(crate) use interned_slice;
201
202macro_rules! impl_stored_interned_slice {
203    ( $storage:ident, $name:ident, $stored_name:ident $(,)? ) => {
204        #[derive(Clone, PartialEq, Eq, Hash)]
205        pub struct $stored_name {
206            interned: ::intern::InternedSlice<$storage>,
207        }
208
209        impl $stored_name {
210            #[inline]
211            fn new(it: $name<'_>) -> Self {
212                Self { interned: it.interned.to_owned() }
213            }
214
215            // FIXME: This transmute is not safe as is!
216            #[inline]
217            pub fn as_ref<'a, 'db>(&'a self) -> $name<'db> {
218                let it = $name { interned: self.interned.as_ref() };
219                unsafe { std::mem::transmute::<$name<'a>, $name<'db>>(it) }
220            }
221        }
222
223        // SAFETY: It is safe to store this type in queries (but not `$name`).
224        unsafe impl salsa::SalsaValue for $stored_name {}
225
226        impl std::fmt::Debug for $stored_name {
227            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228                self.as_ref().fmt(f)
229            }
230        }
231
232        impl $name<'_> {
233            #[inline]
234            pub fn store(self) -> $stored_name {
235                $stored_name::new(self)
236            }
237        }
238    };
239}
240pub(crate) use impl_stored_interned_slice;
241
242macro_rules! impl_foldable_for_interned_slice {
243    ($name:ident) => {
244        impl<'db> ::rustc_type_ir::TypeVisitable<DbInterner<'db>> for $name<'db> {
245            fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
246                &self,
247                visitor: &mut V,
248            ) -> V::Result {
249                use rustc_ast_ir::visit::VisitorResult;
250                rustc_ast_ir::walk_visitable_list!(visitor, (*self).iter());
251                V::Result::output()
252            }
253        }
254
255        impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $name<'db> {
256            fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
257                self,
258                folder: &mut F,
259            ) -> Result<Self, F::Error> {
260                Self::new_from_iter(self.iter().map(|it| it.try_fold_with(folder)))
261            }
262            fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
263                self,
264                folder: &mut F,
265            ) -> Self {
266                Self::new_from_iter(self.iter().map(|it| it.fold_with(folder)))
267            }
268        }
269    };
270}
271pub(crate) use impl_foldable_for_interned_slice;
272
273macro_rules! impl_foldable_for_stored_type {
274    ($name:ident) => {
275        impl<'db> ::rustc_type_ir::TypeVisitable<DbInterner<'db>> for $name {
276            fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
277                &self,
278                visitor: &mut V,
279            ) -> V::Result {
280                self.as_ref().visit_with(visitor)
281            }
282        }
283
284        impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $name {
285            fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
286                self,
287                folder: &mut F,
288            ) -> Result<Self, F::Error> {
289                Ok(self.as_ref().try_fold_with(folder)?.store())
290            }
291            fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
292                self,
293                folder: &mut F,
294            ) -> Self {
295                self.as_ref().fold_with(folder).store()
296            }
297        }
298    };
299}
300pub(crate) use impl_foldable_for_stored_type;
301
302macro_rules! impl_stored_interned {
303    ( $storage:ident, $name:ident, $stored_name:ident $(,)? ) => {
304        #[derive(Clone, PartialEq, Eq, Hash, ::salsa::SalsaValue)]
305        pub struct $stored_name {
306            interned: ::intern::Interned<$storage>,
307        }
308
309        impl $stored_name {
310            #[inline]
311            fn new(it: $name<'_>) -> Self {
312                Self { interned: it.interned.to_owned() }
313            }
314
315            #[inline]
316            pub fn as_ref<'a, 'db>(&'a self) -> $name<'db> {
317                let it = $name { interned: self.interned.as_ref() };
318                unsafe { std::mem::transmute::<$name<'a>, $name<'db>>(it) }
319            }
320        }
321
322        impl std::fmt::Debug for $stored_name {
323            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
324                self.as_ref().fmt(f)
325            }
326        }
327
328        impl $name<'_> {
329            #[inline]
330            pub fn store(self) -> $stored_name {
331                $stored_name::new(self)
332            }
333        }
334    };
335}
336pub(crate) use impl_stored_interned;
337
338/// This is a visitor trait that treats any interned thing specifically. Visitables are expected to call
339/// the trait's methods when encountering an interned. This is used to implement marking in GC.
340pub trait WorldExposer {
341    fn on_interned<T: intern::Internable>(
342        &mut self,
343        interned: InternedRef<'_, T>,
344    ) -> ControlFlow<()>;
345    fn on_interned_slice<T: intern::SliceInternable>(
346        &mut self,
347        interned: InternedSliceRef<'_, T>,
348    ) -> ControlFlow<()>;
349}
350
351#[derive(Debug, Copy, Clone)]
352pub struct DbInterner<'db> {
353    pub db: &'db dyn HirDatabase,
354    krate: Option<Crate>,
355    lang_items: Option<&'db LangItems>,
356}
357
358// FIXME: very wrong, see https://github.com/rust-lang/rust/pull/144808
359unsafe impl Send for DbInterner<'_> {}
360unsafe impl Sync for DbInterner<'_> {}
361
362impl<'db> DbInterner<'db> {
363    // FIXME(next-solver): remove this method
364    #[doc(hidden)]
365    pub fn conjure() -> DbInterner<'db> {
366        // Here we can not reinit the cache since we do that when we attach the db.
367        crate::with_attached_db(|db| DbInterner {
368            db: unsafe { std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(db) },
369            krate: None,
370            lang_items: None,
371        })
372    }
373
374    /// Creates a new interner without an active crate. Good only for interning things, not for trait solving etc..
375    /// As a rule of thumb, when you create an `InferCtxt`, you need to provide the crate (and the block).
376    ///
377    /// Elaboration is a special kind: it needs lang items (for `Sized`), therefore it needs `new_with()`.
378    pub fn new_no_crate(db: &'db dyn HirDatabase) -> Self {
379        // We do not reinit the cache here, since anything accessing the cache needs an InferCtxt,
380        // and we panic when trying to construct an InferCtxt for an Interner without a crate.
381        DbInterner { db, krate: None, lang_items: None }
382    }
383
384    pub fn new_with(db: &'db dyn HirDatabase, krate: Crate) -> DbInterner<'db> {
385        tls_cache::reinit_cache(db);
386        DbInterner {
387            db,
388            krate: Some(krate),
389            // As an approximation, when we call `new_with` we're trait solving, therefore we need the lang items.
390            // This is also convenient since here we have a starting crate but not in `new_no_crate`.
391            lang_items: Some(hir_def::lang_item::lang_items(db, krate)),
392        }
393    }
394
395    #[inline]
396    pub fn db(&self) -> &'db dyn HirDatabase {
397        self.db
398    }
399
400    #[inline]
401    #[track_caller]
402    pub fn lang_items(&self) -> &'db LangItems {
403        self.lang_items.expect(
404            "Must have `DbInterner::lang_items`.\n\n\
405            Note: you might have called `DbInterner::new_no_crate()` \
406            where you should've called `DbInterner::new_with()`",
407        )
408    }
409
410    #[inline]
411    pub fn default_types(&self) -> &'db crate::next_solver::DefaultAny<'db> {
412        crate::next_solver::default_types()
413    }
414
415    #[inline]
416    pub(crate) fn expect_crate(&self) -> Crate {
417        self.krate.expect("should have a crate")
418    }
419}
420
421impl<'db> inherent::Span<DbInterner<'db>> for Span {
422    fn dummy() -> Self {
423        Span::Dummy
424    }
425}
426
427interned_slice!(
428    BoundVarKindsStorage,
429    BoundVarKinds,
430    StoredBoundVarKinds,
431    bound_var_kinds,
432    BoundVariableKind<'db>,
433    BoundVariableKind<'static>,
434);
435
436pub type BoundVariableKind<'db> = rustc_type_ir::BoundVariableKind<DbInterner<'db>>;
437
438interned_slice!(
439    CanonicalVarsStorage,
440    CanonicalVarKinds,
441    StoredCanonicalVars,
442    canonical_vars,
443    CanonicalVarKind<'db>,
444    CanonicalVarKind<'static>
445);
446
447pub struct DepNodeIndex;
448
449#[derive(Debug)]
450pub struct Tracked<T: fmt::Debug + Clone>(T);
451
452#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
453pub struct AllocId;
454
455interned_slice!(VariancesOfStorage, VariancesOf, StoredVariancesOf, variances, Variance, Variance);
456
457bitflags::bitflags! {
458    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
459    struct AdtFlags: u8 {
460        const IS_FUNDAMENTAL = 1 << 0;
461        const IS_PACKED = 1 << 1;
462        const HAS_REPR = 1 << 2;
463        const IS_PHANTOM_DATA = 1 << 3;
464        const IS_MANUALLY_DROP = 1 << 4;
465        const IS_BOX = 1 << 5;
466    }
467}
468
469#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
470enum AdtDefInner {
471    Struct { id: StructId, flags: AdtFlags },
472    Union { id: UnionId, flags: AdtFlags },
473    Enum { id: EnumId, flags: AdtFlags },
474}
475
476#[derive(Clone, Copy, PartialEq, Eq, Hash)]
477pub struct AdtDef(AdtDefInner);
478
479const _: () = assert!(size_of::<AdtDef>() == 12);
480
481impl AdtDef {
482    pub fn new<'db>(def_id: AdtId, interner: DbInterner<'db>) -> Self {
483        let db = interner.db();
484        let inner = match def_id {
485            AdtId::StructId(id) => {
486                let data = StructSignature::of(db, id);
487                let mut flags = AdtFlags::empty();
488                if data.flags.contains(StructFlags::FUNDAMENTAL) {
489                    flags.insert(AdtFlags::IS_FUNDAMENTAL);
490                }
491                if data.flags.contains(StructFlags::IS_PHANTOM_DATA) {
492                    flags.insert(AdtFlags::IS_PHANTOM_DATA);
493                }
494                if data.flags.contains(StructFlags::IS_MANUALLY_DROP) {
495                    flags.insert(AdtFlags::IS_MANUALLY_DROP);
496                }
497                if data.flags.contains(StructFlags::IS_BOX) {
498                    flags.insert(AdtFlags::IS_BOX);
499                }
500                if data.flags.contains(StructFlags::HAS_REPR) {
501                    flags.insert(AdtFlags::HAS_REPR);
502                    if data.repr(db, id).is_some_and(|repr| repr.packed()) {
503                        flags.insert(AdtFlags::IS_PACKED);
504                    }
505                }
506                AdtDefInner::Struct { id, flags }
507            }
508            AdtId::UnionId(id) => {
509                let data = UnionSignature::of(db, id);
510                let mut flags = AdtFlags::empty();
511                if data.flags.contains(StructFlags::FUNDAMENTAL) {
512                    flags.insert(AdtFlags::IS_FUNDAMENTAL);
513                }
514                if data.flags.contains(StructFlags::HAS_REPR) {
515                    flags.insert(AdtFlags::HAS_REPR);
516                    if data.repr(db, id).is_some_and(|repr| repr.packed()) {
517                        flags.insert(AdtFlags::IS_PACKED);
518                    }
519                }
520                AdtDefInner::Union { id, flags }
521            }
522            AdtId::EnumId(id) => {
523                let data = EnumSignature::of(db, id);
524                let mut flags = AdtFlags::empty();
525                if data.flags.contains(EnumFlags::FUNDAMENTAL) {
526                    flags.insert(AdtFlags::IS_FUNDAMENTAL);
527                }
528                if data.flags.contains(EnumFlags::HAS_REPR) {
529                    flags.insert(AdtFlags::HAS_REPR);
530                    if data.repr(db, id).is_some_and(|repr| repr.packed()) {
531                        flags.insert(AdtFlags::IS_PACKED);
532                    }
533                }
534                AdtDefInner::Enum { id, flags }
535            }
536        };
537        AdtDef(inner)
538    }
539
540    #[inline]
541    pub fn def_id(self) -> AdtId {
542        match self.0 {
543            AdtDefInner::Struct { id, .. } => AdtId::StructId(id),
544            AdtDefInner::Union { id, .. } => AdtId::UnionId(id),
545            AdtDefInner::Enum { id, .. } => AdtId::EnumId(id),
546        }
547    }
548
549    #[inline]
550    fn flags(self) -> AdtFlags {
551        match self.0 {
552            AdtDefInner::Struct { flags, .. }
553            | AdtDefInner::Union { flags, .. }
554            | AdtDefInner::Enum { flags, .. } => flags,
555        }
556    }
557
558    #[inline]
559    pub fn is_struct(self) -> bool {
560        matches!(self.0, AdtDefInner::Struct { .. })
561    }
562
563    #[inline]
564    pub fn is_union(self) -> bool {
565        matches!(self.0, AdtDefInner::Union { .. })
566    }
567
568    #[inline]
569    pub fn is_enum(self) -> bool {
570        matches!(self.0, AdtDefInner::Enum { .. })
571    }
572
573    #[inline]
574    pub fn is_box(self) -> bool {
575        matches!(self.0, AdtDefInner::Struct { flags, .. } if flags.contains(AdtFlags::IS_BOX))
576    }
577
578    #[inline]
579    pub fn repr(self, db: &dyn HirDatabase) -> ReprOptions {
580        if self.flags().contains(AdtFlags::HAS_REPR) {
581            AttrFlags::repr_assume_has(db, self.def_id()).unwrap_or_default()
582        } else {
583            ReprOptions::default()
584        }
585    }
586}
587
588impl<'db> inherent::AdtDef<DbInterner<'db>> for AdtDef {
589    fn def_id(self) -> AdtIdWrapper {
590        self.def_id().into()
591    }
592
593    fn is_struct(self) -> bool {
594        self.is_struct()
595    }
596
597    fn is_phantom_data(self) -> bool {
598        matches!(self.0, AdtDefInner::Struct { flags, .. } if flags.contains(AdtFlags::IS_PHANTOM_DATA))
599    }
600
601    fn is_manually_drop(self) -> bool {
602        matches!(self.0, AdtDefInner::Struct { flags, .. } if flags.contains(AdtFlags::IS_MANUALLY_DROP))
603    }
604
605    fn is_packed(self) -> bool {
606        self.flags().contains(AdtFlags::IS_PACKED)
607    }
608
609    fn is_fundamental(self) -> bool {
610        self.flags().contains(AdtFlags::IS_FUNDAMENTAL)
611    }
612
613    fn struct_tail_ty(
614        self,
615        interner: DbInterner<'db>,
616    ) -> Option<EarlyBinder<DbInterner<'db>, Ty<'db>>> {
617        let hir_def::AdtId::StructId(struct_id) = self.def_id() else {
618            return None;
619        };
620        let id: VariantId = struct_id.into();
621        let field_types = interner.db().field_types(id);
622
623        field_types.iter().last().map(|f| f.1.ty())
624    }
625
626    fn all_field_tys(
627        self,
628        interner: DbInterner<'db>,
629    ) -> EarlyBinder<DbInterner<'db>, impl IntoIterator<Item = Ty<'db>>> {
630        let db = interner.db();
631        let field_tys =
632            |id: VariantId| db.field_types(id).iter().map(|(_, ty)| ty.ty().skip_binder());
633        let tys = match self.def_id() {
634            hir_def::AdtId::StructId(id) => Either::Left(field_tys(id.into())),
635            hir_def::AdtId::UnionId(id) => Either::Left(field_tys(id.into())),
636            hir_def::AdtId::EnumId(id) => Either::Right(
637                id.enum_variants(db)
638                    .variants
639                    .values()
640                    .flat_map(move |&(variant_id, _)| field_tys(variant_id.into())),
641            ),
642        };
643
644        EarlyBinder::bind(tys)
645    }
646
647    fn sizedness_constraint(
648        self,
649        interner: DbInterner<'db>,
650        sizedness: SizedTraitKind,
651    ) -> Option<EarlyBinder<DbInterner<'db>, Ty<'db>>> {
652        let tail_ty = self.struct_tail_ty(interner)?;
653        tail_ty
654            .map_bound(|tail_ty| sizedness_constraint_for_ty(interner, sizedness, tail_ty))
655            .transpose()
656    }
657
658    fn destructor(self, interner: DbInterner<'db>) -> Option<AdtDestructorKind> {
659        crate::drop::destructor(interner.db, self.def_id()).map(|_| AdtDestructorKind::NotConst)
660    }
661
662    fn field_representing_type_info(
663        self,
664        _interner: DbInterner<'db>,
665        _args: GenericArgs<'db>,
666    ) -> Option<rustc_type_ir::FieldInfo<DbInterner<'db>>> {
667        // FIXME
668        None
669    }
670}
671
672impl fmt::Debug for AdtDef {
673    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
674        crate::with_attached_db(|db| match self.0 {
675            AdtDefInner::Struct { id, .. } => {
676                let data = StructSignature::of(db, id);
677                f.write_str(data.name.as_str())
678            }
679            AdtDefInner::Union { id, .. } => {
680                let data = UnionSignature::of(db, id);
681                f.write_str(data.name.as_str())
682            }
683            AdtDefInner::Enum { id, .. } => {
684                let data = EnumSignature::of(db, id);
685                f.write_str(data.name.as_str())
686            }
687        })
688    }
689}
690
691#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
692pub struct Features;
693
694impl<'db> inherent::Features<DbInterner<'db>> for Features {
695    fn generic_const_exprs(self) -> bool {
696        false
697    }
698
699    fn coroutine_clone(self) -> bool {
700        false
701    }
702
703    fn generic_const_args(self) -> bool {
704        false
705    }
706
707    fn feature_bound_holds_in_crate(self, _symbol: Symbol) -> bool {
708        false
709    }
710}
711
712#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, GenericTypeVisitable)]
713pub struct Symbol;
714
715impl<'db> inherent::Symbol<DbInterner<'db>> for Symbol {
716    fn is_kw_underscore_lifetime(self) -> bool {
717        false
718    }
719}
720
721#[derive(Debug, Clone, Eq, PartialEq, Hash)]
722pub struct UnsizingParams(pub(crate) DenseBitSet<u32>);
723
724impl std::ops::Deref for UnsizingParams {
725    type Target = DenseBitSet<u32>;
726
727    fn deref(&self) -> &Self::Target {
728        &self.0
729    }
730}
731
732pub type PatternKind<'db> = rustc_type_ir::PatternKind<DbInterner<'db>>;
733
734#[derive(Clone, Copy, PartialEq, Eq, Hash)]
735pub struct Pattern<'db> {
736    interned: InternedRef<'db, PatternInterned>,
737}
738
739#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
740struct PatternInterned(PatternKind<'static>);
741
742impl_internable!(gc; PatternInterned);
743
744const _: () = {
745    const fn is_copy<T: Copy>() {}
746    is_copy::<Pattern<'static>>();
747};
748
749impl<'db> Pattern<'db> {
750    pub fn new(_interner: DbInterner<'db>, kind: PatternKind<'db>) -> Self {
751        let kind = unsafe { std::mem::transmute::<PatternKind<'db>, PatternKind<'static>>(kind) };
752        Self { interned: Interned::new_gc(PatternInterned(kind)) }
753    }
754
755    pub fn inner(&self) -> &PatternKind<'db> {
756        let inner = &self.interned.0;
757        unsafe { std::mem::transmute::<&PatternKind<'static>, &PatternKind<'db>>(inner) }
758    }
759}
760
761impl<'db> std::fmt::Debug for Pattern<'db> {
762    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
763        self.kind().fmt(f)
764    }
765}
766
767impl<'db> Flags for Pattern<'db> {
768    fn flags(&self) -> TypeFlags {
769        match self.inner() {
770            PatternKind::Range { start, end } => {
771                FlagComputation::for_const_kind(&start.kind()).flags
772                    | FlagComputation::for_const_kind(&end.kind()).flags
773            }
774            PatternKind::Or(pats) => {
775                let mut flags = pats.as_slice()[0].flags();
776                for pat in pats.as_slice()[1..].iter() {
777                    flags |= pat.flags();
778                }
779                flags
780            }
781            PatternKind::NotNull => TypeFlags::empty(),
782        }
783    }
784
785    fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
786        match self.inner() {
787            PatternKind::Range { start, end } => {
788                start.outer_exclusive_binder().max(end.outer_exclusive_binder())
789            }
790            PatternKind::Or(pats) => {
791                let mut idx = pats.as_slice()[0].outer_exclusive_binder();
792                for pat in pats.as_slice()[1..].iter() {
793                    idx = idx.max(pat.outer_exclusive_binder());
794                }
795                idx
796            }
797            PatternKind::NotNull => rustc_type_ir::INNERMOST,
798        }
799    }
800}
801
802impl<'db> rustc_type_ir::inherent::IntoKind for Pattern<'db> {
803    type Kind = rustc_type_ir::PatternKind<DbInterner<'db>>;
804    fn kind(self) -> Self::Kind {
805        *self.inner()
806    }
807}
808
809impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for Pattern<'db> {
810    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
811        &self,
812        visitor: &mut V,
813    ) -> V::Result {
814        self.kind().visit_with(visitor)
815    }
816}
817
818impl<'db, V: WorldExposer> rustc_type_ir::GenericTypeVisitable<V> for Pattern<'db> {
819    fn generic_visit_with(&self, visitor: &mut V) {
820        if visitor.on_interned(self.interned).is_continue() {
821            self.kind().generic_visit_with(visitor);
822        }
823    }
824}
825
826impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for Pattern<'db> {
827    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
828        self,
829        folder: &mut F,
830    ) -> Result<Self, F::Error> {
831        Ok(Pattern::new(folder.cx(), self.kind().try_fold_with(folder)?))
832    }
833
834    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
835        Pattern::new(folder.cx(), self.kind().fold_with(folder))
836    }
837}
838
839impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for Pattern<'db> {
840    fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
841        relation: &mut R,
842        a: Self,
843        b: Self,
844    ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
845        let tcx = relation.cx();
846        match (a.kind(), b.kind()) {
847            (
848                PatternKind::Range { start: start_a, end: end_a },
849                PatternKind::Range { start: start_b, end: end_b },
850            ) => {
851                let start = relation.relate(start_a, start_b)?;
852                let end = relation.relate(end_a, end_b)?;
853                Ok(Pattern::new(tcx, PatternKind::Range { start, end }))
854            }
855            (PatternKind::Or(a), PatternKind::Or(b)) => {
856                if a.len() != b.len() {
857                    return Err(TypeError::Mismatch);
858                }
859                let pats = PatList::new_from_iter(
860                    std::iter::zip(a.iter(), b.iter()).map(|(a, b)| relation.relate(a, b)),
861                )?;
862                Ok(Pattern::new(tcx, PatternKind::Or(pats)))
863            }
864            (PatternKind::NotNull, PatternKind::NotNull) => Ok(a),
865            (PatternKind::Range { .. } | PatternKind::Or(_) | PatternKind::NotNull, _) => {
866                Err(TypeError::Mismatch)
867            }
868        }
869    }
870}
871
872interned_slice!(PatListStorage, PatList, StoredPatList, pat_list, Pattern<'db>, Pattern<'static>);
873impl_foldable_for_interned_slice!(PatList);
874
875impl<'db> Interner for DbInterner<'db> {
876    type DefId = SolverDefId<'db>;
877    type LocalDefId = SolverDefId<'db>;
878    type LocalDefIds = SolverDefIds<'db>;
879    type TraitId = TraitIdWrapper;
880    type ForeignId = TypeAliasIdWrapper;
881    type FunctionId = CallableIdWrapper;
882    type ClosureId = ClosureIdWrapper<'db>;
883    type CoroutineClosureId = CoroutineClosureIdWrapper<'db>;
884    type CoroutineId = CoroutineIdWrapper<'db>;
885    type AdtId = AdtIdWrapper;
886    type ImplId = AnyImplId;
887    type UnevaluatedConstId = GeneralConstIdWrapper<'db>;
888    type TraitAssocTyId = TraitAssocTyId;
889    type TraitAssocConstId = TraitAssocConstId;
890    type TraitAssocTermId = TraitAssocTermId;
891    type OpaqueTyId = OpaqueTyIdWrapper<'db>;
892    type LocalOpaqueTyId = OpaqueTyIdWrapper<'db>;
893    type FreeTyAliasId = FreeTyAliasId;
894    type FreeConstAliasId = FreeConstAliasId;
895    type FreeTermAliasId = FreeTermAliasId;
896    type ImplOrTraitAssocTyId = ImplOrTraitAssocTyId;
897    type ImplOrTraitAssocConstId = ImplOrTraitAssocConstId;
898    type ImplOrTraitAssocTermId = ImplOrTraitAssocTermId;
899    type InherentAssocTyId = InherentAssocTyId;
900    type InherentAssocConstId = InherentAssocConstId;
901    type InherentAssocTermId = InherentAssocTermId;
902    type Span = Span;
903
904    type GenericArgs = GenericArgs<'db>;
905    type GenericArgsSlice = &'db [GenericArg<'db>];
906    type GenericArg = GenericArg<'db>;
907
908    type Term = Term<'db>;
909
910    type BoundVarKinds = BoundVarKinds<'db>;
911
912    type PredefinedOpaques = PredefinedOpaques<'db>;
913
914    fn mk_predefined_opaques_in_body(
915        self,
916        data: &[(OpaqueTypeKey<'db>, Self::Ty)],
917    ) -> Self::PredefinedOpaques {
918        PredefinedOpaques::new_from_slice(data)
919    }
920
921    type CanonicalVarKinds = CanonicalVarKinds<'db>;
922
923    fn mk_canonical_var_kinds(
924        self,
925        kinds: &[rustc_type_ir::CanonicalVarKind<Self>],
926    ) -> Self::CanonicalVarKinds {
927        CanonicalVarKinds::new_from_slice(kinds)
928    }
929
930    type ExternalConstraints = ExternalConstraints<'db>;
931
932    fn mk_external_constraints(
933        self,
934        data: rustc_type_ir::solve::ExternalConstraintsData<Self>,
935    ) -> Self::ExternalConstraints {
936        ExternalConstraints::new(self, data)
937    }
938
939    type DepNodeIndex = DepNodeIndex;
940
941    type Tracked<T: fmt::Debug + Clone> = Tracked<T>;
942
943    type Ty = Ty<'db>;
944    type Tys = Tys<'db>;
945    type FnInputTys = &'db [Ty<'db>];
946    type ParamTy = ParamTy;
947    type Symbol = Symbol;
948
949    type ErrorGuaranteed = ErrorGuaranteed;
950    type BoundExistentialPredicates = BoundExistentialPredicates<'db>;
951    type AllocId = AllocId;
952    type Pat = Pattern<'db>;
953    type PatList = PatList<'db>;
954    type Safety = Safety;
955
956    type Const = Const<'db>;
957    type ParamConst = ParamConst;
958    type ValueConst = ValueConst<'db>;
959    type ValTree = ValTree<'db>;
960    type Consts = Consts<'db>;
961    type ScalarInt = ScalarInt;
962    type ExprConst = ExprConst;
963
964    type Region = Region<'db>;
965    type EarlyParamRegion = EarlyParamRegion;
966    type LateParamRegion = LateParamRegion<'db>;
967
968    type RegionAssumptions = RegionAssumptions<'db>;
969
970    type ParamEnv = ParamEnv<'db>;
971    type Predicate = Predicate<'db>;
972    type Clause = Clause<'db>;
973    type Clauses = Clauses<'db>;
974
975    type GenericsOf = Generics<'db>;
976
977    type VariancesOf = VariancesOf<'db>;
978
979    type AdtDef = AdtDef;
980
981    type Features = Features;
982
983    fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs {
984        GenericArgs::new_from_slice(args)
985    }
986
987    fn mk_args_from_iter<I, T>(self, args: I) -> T::Output
988    where
989        I: Iterator<Item = T>,
990        T: rustc_type_ir::CollectAndApply<Self::GenericArg, Self::GenericArgs>,
991    {
992        GenericArgs::new_from_iter(args)
993    }
994
995    type UnsizingParams = UnsizingParams;
996
997    fn mk_tracked<T: fmt::Debug + Clone>(
998        self,
999        data: T,
1000        _dep_node: Self::DepNodeIndex,
1001    ) -> Self::Tracked<T> {
1002        Tracked(data)
1003    }
1004
1005    fn get_tracked<T: fmt::Debug + Clone>(self, tracked: &Self::Tracked<T>) -> T {
1006        tracked.0.clone()
1007    }
1008
1009    fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, Self::DepNodeIndex) {
1010        (task(), DepNodeIndex)
1011    }
1012
1013    fn with_global_cache<R>(
1014        self,
1015        f: impl FnOnce(&mut rustc_type_ir::search_graph::GlobalCache<Self>) -> R,
1016    ) -> R {
1017        // We make sure to reinit the cache when constructing the Interner.
1018        tls_cache::borrow_assume_valid(self.db, f)
1019    }
1020
1021    fn canonical_param_env_cache_get_or_insert<R>(
1022        self,
1023        _param_env: Self::ParamEnv,
1024        f: impl FnOnce() -> rustc_type_ir::CanonicalParamEnvCacheEntry<Self>,
1025        from_entry: impl FnOnce(&rustc_type_ir::CanonicalParamEnvCacheEntry<Self>) -> R,
1026    ) -> R {
1027        from_entry(&f())
1028    }
1029
1030    fn assert_evaluation_is_concurrent(&self) {
1031        // Turns out, the assumption for this function isn't perfect.
1032        // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/234
1033    }
1034
1035    fn expand_abstract_consts<T: rustc_type_ir::TypeFoldable<Self>>(self, _: T) -> T {
1036        unreachable!("only used by the old trait solver in rustc");
1037    }
1038
1039    fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf {
1040        generics(self, def_id)
1041    }
1042
1043    fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
1044        let generic_def = match def_id {
1045            SolverDefId::Ctor(Ctor::Enum(def_id)) | SolverDefId::EnumVariantId(def_id) => {
1046                def_id.loc(self.db).parent.into()
1047            }
1048            SolverDefId::InternedOpaqueTyId(_def_id) => {
1049                // FIXME(next-solver): track variances
1050                //
1051                // We compute them based on the only `Ty` level info in rustc,
1052                // move `variances_of_opaque` into `rustc_next_trait_solver` for reuse.
1053                return VariancesOf::new_from_iter(
1054                    (0..self.generics_of(def_id).count()).map(|_| Variance::Invariant),
1055                );
1056            }
1057            SolverDefId::Ctor(Ctor::Struct(def_id)) => def_id.into(),
1058            SolverDefId::AdtId(def_id) => def_id.into(),
1059            SolverDefId::FunctionId(def_id) => def_id.into(),
1060            SolverDefId::ConstId(_)
1061            | SolverDefId::StaticId(_)
1062            | SolverDefId::TraitId(_)
1063            | SolverDefId::TypeAliasId(_)
1064            | SolverDefId::ImplId(_)
1065            | SolverDefId::BuiltinDeriveImplId(_)
1066            | SolverDefId::InternedClosureId(_)
1067            | SolverDefId::InternedCoroutineId(_)
1068            | SolverDefId::InternedCoroutineClosureId(_)
1069            | SolverDefId::AnonConstId(_) => {
1070                return VariancesOf::empty();
1071            }
1072        };
1073        self.db.variances_of(generic_def)
1074    }
1075
1076    fn type_of(self, def_id: Self::DefId) -> EarlyBinder<Self, Self::Ty> {
1077        match def_id {
1078            SolverDefId::TypeAliasId(id) => self.db().ty(id.into()),
1079            SolverDefId::AdtId(id) => self.db().ty(id.into()),
1080            // FIXME(next-solver): This uses the types of `query mir_borrowck` in rustc.
1081            //
1082            // We currently always use the type from HIR typeck which ignores regions. This
1083            // should be fine.
1084            SolverDefId::InternedOpaqueTyId(def_id) => {
1085                self.type_of_opaque_hir_typeck(def_id.into())
1086            }
1087            SolverDefId::FunctionId(id) => self.db.value_ty(id.into()).unwrap(),
1088            SolverDefId::Ctor(id) => {
1089                let id = match id {
1090                    Ctor::Struct(id) => id.into(),
1091                    Ctor::Enum(id) => id.into(),
1092                };
1093                self.db.value_ty(id).expect("`SolverDefId::Ctor` should have a function-like ctor")
1094            }
1095            _ => panic!("Unexpected def_id `{def_id:?}` provided for `type_of`"),
1096        }
1097    }
1098
1099    fn adt_def(self, def_id: Self::AdtId) -> Self::AdtDef {
1100        AdtDef::new(def_id.0, self)
1101    }
1102
1103    fn alias_term_kind_from_def_id(self, def_id: SolverDefId<'db>) -> AliasTermKind<'db> {
1104        match def_id {
1105            SolverDefId::InternedOpaqueTyId(def_id) => {
1106                AliasTermKind::OpaqueTy { def_id: def_id.into() }
1107            }
1108            SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
1109                ItemContainerId::ImplId(impl_)
1110                    if ImplSignature::of(self.db, impl_).target_trait.is_none() =>
1111                {
1112                    AliasTermKind::InherentTy { def_id: type_alias.into() }
1113                }
1114                ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => {
1115                    AliasTermKind::ProjectionTy { def_id: type_alias.into() }
1116                }
1117                _ => AliasTermKind::FreeTy { def_id: type_alias.into() },
1118            },
1119            // rustc creates an `AnonConst` for consts, and evaluates them with CTFE (normalizing projections
1120            // via selection, similar to ours `find_matching_impl()`, and not with the trait solver), so mimic it.
1121            SolverDefId::ConstId(def_id) => {
1122                AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1123            }
1124            SolverDefId::StaticId(def_id) => {
1125                AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1126            }
1127            SolverDefId::AnonConstId(def_id) => {
1128                AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1129            }
1130            _ => unimplemented!("Unexpected alias: {:?}", def_id),
1131        }
1132    }
1133
1134    fn trait_ref_and_own_args_for_alias(
1135        self,
1136        def_id: Self::TraitAssocTermId,
1137        args: Self::GenericArgs,
1138    ) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
1139        let trait_def_id = self.projection_parent(def_id);
1140        let trait_ref = TraitRef::from_assoc(self, trait_def_id, args);
1141        (trait_ref, &args.as_slice()[trait_ref.args.len()..])
1142    }
1143
1144    fn check_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs) -> bool {
1145        let generics = self.generics_of(def_id);
1146        generics.count() == args.len()
1147            && std::iter::zip(generics.iter(), args).all(|((param, _), arg)| {
1148                matches!(
1149                    (param, arg.kind()),
1150                    (GenericParamId::LifetimeParamId(_), GenericArgKind::Lifetime(_))
1151                        | (GenericParamId::TypeParamId(_), GenericArgKind::Type(_))
1152                        | (GenericParamId::ConstParamId(_), GenericArgKind::Const(_))
1153                )
1154            })
1155    }
1156
1157    fn debug_assert_args_compatible(self, _def_id: Self::DefId, _args: Self::GenericArgs) {}
1158
1159    fn debug_assert_existential_args_compatible(
1160        self,
1161        _def_id: Self::DefId,
1162        _args: Self::GenericArgs,
1163    ) {
1164    }
1165
1166    fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
1167    where
1168        I: Iterator<Item = T>,
1169        T: rustc_type_ir::CollectAndApply<Self::Ty, Self::Tys>,
1170    {
1171        Tys::new_from_iter(args)
1172    }
1173
1174    fn projection_parent(self, def_id: Self::TraitAssocTermId) -> Self::TraitId {
1175        let container = match def_id.0 {
1176            TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1177            TermId::ConstId(def_id) => def_id.loc(self.db).container,
1178        };
1179        let ItemContainerId::TraitId(trait_) = container else {
1180            panic!("a TraitAssocTermId can only come from a trait")
1181        };
1182        trait_.into()
1183    }
1184
1185    fn impl_or_trait_assoc_term_parent(self, def_id: Self::ImplOrTraitAssocTermId) -> Self::DefId {
1186        let container = match def_id.0 {
1187            TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1188            TermId::ConstId(def_id) => def_id.loc(self.db).container,
1189        };
1190        match container {
1191            ItemContainerId::ImplId(impl_) => impl_.into(),
1192            ItemContainerId::TraitId(trait_) => trait_.into(),
1193            ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
1194                panic!("only impl or trait can be the parent of ImplOrTraitAssocTermId")
1195            }
1196        }
1197    }
1198
1199    fn inherent_alias_term_parent(self, def_id: Self::InherentAssocTermId) -> Self::ImplId {
1200        let container = match def_id.0 {
1201            TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1202            TermId::ConstId(def_id) => def_id.loc(self.db).container,
1203        };
1204        match container {
1205            ItemContainerId::ImplId(impl_) => impl_.into(),
1206            ItemContainerId::ExternBlockId(_)
1207            | ItemContainerId::ModuleId(_)
1208            | ItemContainerId::TraitId(_) => {
1209                panic!("only impl can be the parent of InherentAliasTermId")
1210            }
1211        }
1212    }
1213
1214    fn recursion_limit(self) -> usize {
1215        50
1216    }
1217
1218    fn is_type_const(self, _def_id: Self::DefId) -> bool {
1219        false
1220    }
1221
1222    fn features(self) -> Features {
1223        Features
1224    }
1225
1226    fn fn_sig(
1227        self,
1228        def_id: Self::FunctionId,
1229    ) -> EarlyBinder<Self, rustc_type_ir::Binder<Self, rustc_type_ir::FnSig<Self>>> {
1230        self.db().callable_item_signature(def_id.0)
1231    }
1232
1233    fn coroutine_movability(self, def_id: Self::CoroutineId) -> rustc_ast_ir::Movability {
1234        match def_id.0.loc(self.db).kind {
1235            hir_def::hir::ClosureKind::OldCoroutine(movability) => match movability {
1236                hir_def::hir::Movability::Static => rustc_ast_ir::Movability::Static,
1237                hir_def::hir::Movability::Movable => rustc_ast_ir::Movability::Movable,
1238            },
1239            hir_def::hir::ClosureKind::Coroutine { .. } => rustc_ast_ir::Movability::Static,
1240            kind => panic!("unexpected kind for a coroutine: {kind:?}"),
1241        }
1242    }
1243
1244    fn coroutine_for_closure(self, def_id: Self::CoroutineClosureId) -> Self::CoroutineId {
1245        let InternedClosure { owner, expr: coroutine_closure_expr, kind: coroutine_closure_kind } =
1246            def_id.0.loc(self.db);
1247        let coroutine_closure_kind = match coroutine_closure_kind {
1248            HirClosureKind::CoroutineClosure(it) => it,
1249            _ => {
1250                panic!("invalid kind closure kind {coroutine_closure_kind:?} for coroutine closure")
1251            }
1252        };
1253        let coroutine_expr = ExpressionStore::coroutine_for_closure(coroutine_closure_expr);
1254        let coroutine_kind = hir_def::hir::ClosureKind::Coroutine {
1255            kind: coroutine_closure_kind,
1256            source: hir_def::hir::CoroutineSource::Closure,
1257        };
1258        InternedCoroutineId::new(
1259            self.db,
1260            InternedClosure { owner, expr: coroutine_expr, kind: coroutine_kind },
1261        )
1262        .into()
1263    }
1264
1265    fn generics_require_sized_self(self, def_id: Self::DefId) -> bool {
1266        match GenericDefId::try_from(def_id) {
1267            Ok(def_id) => crate::dyn_compatibility::generics_require_sized_self(self.db, def_id),
1268            Err(_) => false,
1269        }
1270    }
1271
1272    #[tracing::instrument(skip(self))]
1273    fn item_bounds(
1274        self,
1275        def_id: Self::DefId,
1276    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1277        ItemBounds::of_solver_def(self.db, def_id).all_bounds()
1278    }
1279
1280    #[tracing::instrument(skip(self))]
1281    fn item_self_bounds(
1282        self,
1283        def_id: Self::DefId,
1284    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1285        ItemBounds::of_solver_def(self.db, def_id).self_bounds()
1286    }
1287
1288    fn item_non_self_bounds(
1289        self,
1290        def_id: Self::DefId,
1291    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1292        ItemBounds::of_solver_def(self.db, def_id).non_self_bounds()
1293    }
1294
1295    fn predicates_of(
1296        self,
1297        def_id: Self::DefId,
1298    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1299        predicates_of(self.db, def_id).all_predicates()
1300    }
1301
1302    fn own_predicates_of(
1303        self,
1304        def_id: Self::DefId,
1305    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1306        predicates_of(self.db, def_id).own_explicit_predicates()
1307    }
1308
1309    fn explicit_super_predicates_of(
1310        self,
1311        def_id: Self::TraitId,
1312    ) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
1313        GenericPredicates::query(self.db, def_id.0.into())
1314            .explicit_non_assoc_types_predicates()
1315            .map_bound(move |predicates| {
1316                predicates.filter(|p| is_clause_at_ty(p, is_ty_self)).map(|p| (p, Span::dummy()))
1317            })
1318    }
1319
1320    fn explicit_implied_predicates_of(
1321        self,
1322        def_id: Self::DefId,
1323    ) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
1324        fn is_ty_assoc_of_self(ty: Ty<'_>) -> bool {
1325            // FIXME: Is this correct wrt. combined kind of assoc type bounds, i.e. `where Self::Assoc: Trait<Assoc2: Trait>`
1326            // wrt. `Assoc2`, which we should exclude?
1327            if let TyKind::Alias(alias @ AliasTy { kind: AliasTyKind::Projection { .. }, .. }) =
1328                ty.kind()
1329            {
1330                is_ty_assoc_of_self(alias.self_ty())
1331            } else {
1332                is_ty_self(ty)
1333            }
1334        }
1335
1336        let predicates = predicates_of(self.db, def_id);
1337        let non_assoc_types = predicates
1338            .explicit_non_assoc_types_predicates()
1339            .skip_binder()
1340            .filter(|p| is_clause_at_ty(p, is_ty_self));
1341        let assoc_types = predicates
1342            .explicit_assoc_types_predicates()
1343            .skip_binder()
1344            .filter(|p| is_clause_at_ty(p, is_ty_assoc_of_self));
1345        EarlyBinder::bind(non_assoc_types.chain(assoc_types).map(|it| (it, Span::dummy())))
1346    }
1347
1348    fn impl_super_outlives(
1349        self,
1350        impl_id: Self::ImplId,
1351    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1352        let bounds = match impl_id {
1353            AnyImplId::ImplId(id) => {
1354                impl_super_outlives(self.db, id).get().map_bound(|it| it.as_slice())
1355            }
1356            AnyImplId::BuiltinDeriveImplId(id) => {
1357                crate::builtin_derive::impl_super_outlives(self, id)
1358            }
1359        };
1360        bounds.map_bound(|it| it.iter().copied())
1361    }
1362
1363    #[expect(unreachable_code)]
1364    fn const_conditions(
1365        self,
1366        _def_id: Self::DefId,
1367    ) -> EarlyBinder<
1368        Self,
1369        impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
1370    > {
1371        EarlyBinder::bind([unimplemented!()])
1372    }
1373
1374    fn has_target_features(self, _def_id: Self::FunctionId) -> bool {
1375        false
1376    }
1377
1378    fn require_projection_lang_item(
1379        self,
1380        lang_item: SolverProjectionLangItem,
1381    ) -> Self::TraitAssocTyId {
1382        self.lang_items()
1383            .get_solver_projection(lang_item)
1384            .expect("Lang item required but not found.")
1385            .into()
1386    }
1387
1388    fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> TraitIdWrapper {
1389        self.lang_items()
1390            .get_solver_trait(lang_item)
1391            .expect("Lang item required but not found.")
1392            .into()
1393    }
1394
1395    fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> AdtIdWrapper {
1396        self.lang_items()
1397            .get_solver_adt(lang_item)
1398            .expect("Lang item required but not found.")
1399            .into()
1400    }
1401
1402    fn is_projection_lang_item(
1403        self,
1404        def_id: Self::TraitAssocTyId,
1405        lang_item: SolverProjectionLangItem,
1406    ) -> bool {
1407        self.lang_items().get_solver_projection(lang_item) == Some(def_id.0)
1408    }
1409
1410    fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool {
1411        self.lang_items().get_solver_trait(lang_item) == Some(def_id.0)
1412    }
1413
1414    fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool {
1415        self.lang_items().get_solver_adt(lang_item) == Some(def_id.0)
1416    }
1417
1418    fn as_projection_lang_item(
1419        self,
1420        def_id: Self::TraitAssocTyId,
1421    ) -> Option<SolverProjectionLangItem> {
1422        self.lang_items().get_reverse_solver_projection(def_id.0)
1423    }
1424
1425    fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem> {
1426        self.lang_items().get_reverse_solver_trait(def_id.0)
1427    }
1428
1429    fn as_adt_lang_item(self, def_id: Self::AdtId) -> Option<SolverAdtLangItem> {
1430        self.lang_items().get_reverse_solver_adt(def_id.0)
1431    }
1432
1433    fn associated_type_def_ids(
1434        self,
1435        def_id: Self::TraitId,
1436    ) -> impl IntoIterator<Item = Self::DefId> {
1437        def_id.0.trait_items(self.db()).associated_types().map(|id| id.into())
1438    }
1439
1440    fn for_each_relevant_impl<R: VisitorResult>(
1441        self,
1442        trait_def_id: Self::TraitId,
1443        self_ty: Self::Ty,
1444        mut f: impl FnMut(Self::ImplId) -> R,
1445    ) -> R {
1446        let krate = self.krate.expect("trait solving requires setting `DbInterner::krate`");
1447        let trait_block = trait_def_id.0.loc(self.db).container.block(self.db);
1448        let mut consider_impls_for_simplified_type = |simp: SimplifiedType<'_>| {
1449            let type_block = simp.def().and_then(|def_id| {
1450                let module = match def_id {
1451                    SolverDefId::AdtId(AdtId::StructId(id)) => id.module(self.db),
1452                    SolverDefId::AdtId(AdtId::EnumId(id)) => id.module(self.db),
1453                    SolverDefId::AdtId(AdtId::UnionId(id)) => id.module(self.db),
1454                    SolverDefId::TraitId(id) => id.module(self.db),
1455                    SolverDefId::TypeAliasId(id) => id.module(self.db),
1456                    SolverDefId::ConstId(_)
1457                    | SolverDefId::FunctionId(_)
1458                    | SolverDefId::ImplId(_)
1459                    | SolverDefId::BuiltinDeriveImplId(_)
1460                    | SolverDefId::StaticId(_)
1461                    | SolverDefId::InternedClosureId(_)
1462                    | SolverDefId::InternedCoroutineId(_)
1463                    | SolverDefId::InternedCoroutineClosureId(_)
1464                    | SolverDefId::InternedOpaqueTyId(_)
1465                    | SolverDefId::EnumVariantId(_)
1466                    | SolverDefId::AnonConstId(_)
1467                    | SolverDefId::Ctor(_) => return None,
1468                };
1469                module.block(self.db)
1470            });
1471            TraitImpls::for_each_crate_and_block_trait_and_type(
1472                self.db,
1473                krate,
1474                type_block,
1475                trait_block,
1476                &mut |impls| {
1477                    let (regular_impls, builtin_derive_impls) =
1478                        impls.for_trait_and_self_ty(trait_def_id.0, &simp);
1479                    for &impl_ in regular_impls {
1480                        try_visit!(f(impl_.into()));
1481                    }
1482                    for &impl_ in builtin_derive_impls {
1483                        try_visit!(f(impl_.into()));
1484                    }
1485                    R::output()
1486                },
1487            )
1488        };
1489
1490        match self_ty.kind() {
1491            TyKind::Bool
1492            | TyKind::Char
1493            | TyKind::Int(_)
1494            | TyKind::Uint(_)
1495            | TyKind::Float(_)
1496            | TyKind::Adt(_, _)
1497            | TyKind::Foreign(_)
1498            | TyKind::Str
1499            | TyKind::Array(_, _)
1500            | TyKind::Pat(_, _)
1501            | TyKind::Slice(_)
1502            | TyKind::RawPtr(_, _)
1503            | TyKind::Ref(_, _, _)
1504            | TyKind::FnDef(_, _)
1505            | TyKind::FnPtr(..)
1506            | TyKind::Dynamic(_, _)
1507            | TyKind::Closure(..)
1508            | TyKind::CoroutineClosure(..)
1509            | TyKind::Coroutine(_, _)
1510            | TyKind::Never
1511            | TyKind::Tuple(_)
1512            | TyKind::UnsafeBinder(_) => {
1513                let simp =
1514                    fast_reject::simplify_type(self, self_ty, fast_reject::TreatParams::AsRigid)
1515                        .unwrap();
1516                try_visit!(consider_impls_for_simplified_type(simp));
1517            }
1518
1519            // HACK: For integer and float variables we have to manually look at all impls
1520            // which have some integer or float as a self type.
1521            TyKind::Infer(InferTy::IntVar(_)) => {
1522                use IntTy::*;
1523                use UintTy::*;
1524                // This causes a compiler error if any new integer kinds are added.
1525                let (I8 | I16 | I32 | I64 | I128 | Isize): IntTy;
1526                let (U8 | U16 | U32 | U64 | U128 | Usize): UintTy;
1527                let possible_integers = [
1528                    // signed integers
1529                    SimplifiedType::Int(I8),
1530                    SimplifiedType::Int(I16),
1531                    SimplifiedType::Int(I32),
1532                    SimplifiedType::Int(I64),
1533                    SimplifiedType::Int(I128),
1534                    SimplifiedType::Int(Isize),
1535                    // unsigned integers
1536                    SimplifiedType::Uint(U8),
1537                    SimplifiedType::Uint(U16),
1538                    SimplifiedType::Uint(U32),
1539                    SimplifiedType::Uint(U64),
1540                    SimplifiedType::Uint(U128),
1541                    SimplifiedType::Uint(Usize),
1542                ];
1543                for simp in possible_integers {
1544                    try_visit!(consider_impls_for_simplified_type(simp));
1545                }
1546            }
1547
1548            TyKind::Infer(InferTy::FloatVar(_)) => {
1549                // This causes a compiler error if any new float kinds are added.
1550                let (FloatTy::F16 | FloatTy::F32 | FloatTy::F64 | FloatTy::F128);
1551                let possible_floats = [
1552                    SimplifiedType::Float(FloatTy::F16),
1553                    SimplifiedType::Float(FloatTy::F32),
1554                    SimplifiedType::Float(FloatTy::F64),
1555                    SimplifiedType::Float(FloatTy::F128),
1556                ];
1557
1558                for simp in possible_floats {
1559                    try_visit!(consider_impls_for_simplified_type(simp));
1560                }
1561            }
1562
1563            // The only traits applying to aliases and placeholders are blanket impls.
1564            //
1565            // Impls which apply to an alias after normalization are handled by
1566            // `assemble_candidates_after_normalizing_self_ty`.
1567            TyKind::Alias(..) | TyKind::Placeholder(..) | TyKind::Error(_) => (),
1568
1569            // FIXME: These should ideally not exist as a self type. It would be nice for
1570            // the builtin auto trait impls of coroutines to instead directly recurse
1571            // into the witness.
1572            TyKind::CoroutineWitness(..) => (),
1573
1574            // These variants should not exist as a self type.
1575            TyKind::Infer(
1576                InferTy::TyVar(_)
1577                | InferTy::FreshTy(_)
1578                | InferTy::FreshIntTy(_)
1579                | InferTy::FreshFloatTy(_),
1580            )
1581            | TyKind::Param(_)
1582            | TyKind::Bound(_, _) => panic!("unexpected self type: {self_ty:?}"),
1583        }
1584
1585        self.for_each_blanket_impl(trait_def_id, f)
1586    }
1587
1588    fn for_each_blanket_impl<R: VisitorResult>(
1589        self,
1590        trait_def_id: Self::TraitId,
1591        mut f: impl FnMut(Self::ImplId) -> R,
1592    ) -> R {
1593        let Some(krate) = self.krate else {
1594            return R::output();
1595        };
1596        let block = trait_def_id.0.loc(self.db).container.block(self.db);
1597
1598        TraitImpls::for_each_crate_and_block(self.db, krate, block, &mut |impls| {
1599            for &impl_ in impls.blanket_impls(trait_def_id.0) {
1600                try_visit!(f(impl_.into()));
1601            }
1602            R::output()
1603        })
1604    }
1605
1606    fn has_item_definition(self, _def_id: Self::ImplOrTraitAssocTermId) -> bool {
1607        // FIXME(next-solver): should check if the associated item has a value.
1608        true
1609    }
1610
1611    fn impl_is_default(self, impl_def_id: Self::ImplId) -> bool {
1612        match impl_def_id {
1613            AnyImplId::ImplId(impl_id) => ImplSignature::of(self.db, impl_id).is_default(),
1614            AnyImplId::BuiltinDeriveImplId(_) => false,
1615        }
1616    }
1617
1618    #[tracing::instrument(skip(self), ret)]
1619    fn impl_trait_ref(
1620        self,
1621        impl_id: Self::ImplId,
1622    ) -> EarlyBinder<Self, rustc_type_ir::TraitRef<Self>> {
1623        match impl_id {
1624            AnyImplId::ImplId(impl_id) => {
1625                let db = self.db();
1626                db.impl_trait(impl_id)
1627                    // ImplIds for impls where the trait ref can't be resolved should never reach trait solving
1628                    .expect("invalid impl passed to trait solver")
1629            }
1630            AnyImplId::BuiltinDeriveImplId(impl_id) => {
1631                crate::builtin_derive::impl_trait(self, impl_id)
1632            }
1633        }
1634    }
1635
1636    fn impl_polarity(self, impl_id: Self::ImplId) -> rustc_type_ir::ImplPolarity {
1637        let AnyImplId::ImplId(impl_id) = impl_id else {
1638            return ImplPolarity::Positive;
1639        };
1640        let impl_data = ImplSignature::of(self.db(), impl_id);
1641        if impl_data.flags.contains(ImplFlags::NEGATIVE) {
1642            ImplPolarity::Negative
1643        } else {
1644            ImplPolarity::Positive
1645        }
1646    }
1647
1648    fn trait_is_auto(self, trait_: Self::TraitId) -> bool {
1649        let trait_data = TraitSignature::of(self.db(), trait_.0);
1650        trait_data.flags.contains(TraitFlags::AUTO)
1651    }
1652
1653    fn trait_is_alias(self, trait_: Self::TraitId) -> bool {
1654        let trait_data = TraitSignature::of(self.db(), trait_.0);
1655        trait_data.flags.contains(TraitFlags::ALIAS)
1656    }
1657
1658    fn trait_is_dyn_compatible(self, trait_: Self::TraitId) -> bool {
1659        crate::dyn_compatibility::dyn_compatibility(self.db(), trait_.0).is_none()
1660    }
1661
1662    fn trait_is_fundamental(self, trait_: Self::TraitId) -> bool {
1663        let trait_data = TraitSignature::of(self.db(), trait_.0);
1664        trait_data.flags.contains(TraitFlags::FUNDAMENTAL)
1665    }
1666
1667    fn is_impl_trait_in_trait(self, _def_id: Self::DefId) -> bool {
1668        // FIXME(next-solver)
1669        false
1670    }
1671
1672    fn delay_bug(self, _msg: impl ToString) -> Self::ErrorGuaranteed {
1673        ErrorGuaranteed
1674    }
1675
1676    fn is_general_coroutine(self, def_id: Self::CoroutineId) -> bool {
1677        matches!(def_id.0.loc(self.db).kind, HirClosureKind::OldCoroutine(_))
1678    }
1679
1680    fn coroutine_is_async(self, def_id: Self::CoroutineId) -> bool {
1681        matches!(
1682            def_id.0.loc(self.db).kind,
1683            HirClosureKind::Coroutine { kind: HirCoroutineKind::Async, .. }
1684        )
1685    }
1686
1687    fn coroutine_is_gen(self, def_id: Self::CoroutineId) -> bool {
1688        matches!(
1689            def_id.0.loc(self.db).kind,
1690            HirClosureKind::Coroutine { kind: HirCoroutineKind::Gen, .. }
1691        )
1692    }
1693
1694    fn coroutine_is_async_gen(self, def_id: Self::CoroutineId) -> bool {
1695        matches!(
1696            def_id.0.loc(self.db).kind,
1697            HirClosureKind::Coroutine { kind: HirCoroutineKind::AsyncGen, .. }
1698        )
1699    }
1700
1701    fn unsizing_params_for_adt(self, id: Self::AdtId) -> Self::UnsizingParams {
1702        let def = AdtDef::new(id.0, self);
1703        let num_params = self.generics_of(id.into()).count();
1704
1705        let maybe_unsizing_param_idx = |arg: GenericArg<'db>| match arg.kind() {
1706            GenericArgKind::Type(ty) => match ty.kind() {
1707                rustc_type_ir::TyKind::Param(p) => Some(p.index),
1708                _ => None,
1709            },
1710            GenericArgKind::Lifetime(_) => None,
1711            GenericArgKind::Const(ct) => match ct.kind() {
1712                rustc_type_ir::ConstKind::Param(p) => Some(p.index),
1713                _ => None,
1714            },
1715        };
1716
1717        // The last field of the structure has to exist and contain type/const parameters.
1718        let variant = match def.def_id() {
1719            AdtId::StructId(id) => VariantId::from(id),
1720            AdtId::UnionId(id) => id.into(),
1721            AdtId::EnumId(_) => panic!("expected a struct or a union"),
1722        };
1723        let fields = variant.fields(self.db());
1724        let mut prefix_fields = fields.fields().iter();
1725        let Some(tail_field) = prefix_fields.next_back() else {
1726            return UnsizingParams(DenseBitSet::new_empty(num_params));
1727        };
1728
1729        let field_types = self.db().field_types(variant);
1730        let mut unsizing_params = DenseBitSet::new_empty(num_params);
1731        let ty = field_types[tail_field.0].ty();
1732        for arg in ty.instantiate_identity().skip_norm_wip().walk() {
1733            if let Some(i) = maybe_unsizing_param_idx(arg) {
1734                unsizing_params.insert(i);
1735            }
1736        }
1737
1738        // Ensure none of the other fields mention the parameters used
1739        // in unsizing.
1740        for field in prefix_fields {
1741            for arg in field_types[field.0].ty().instantiate_identity().skip_norm_wip().walk() {
1742                if let Some(i) = maybe_unsizing_param_idx(arg) {
1743                    unsizing_params.remove(i);
1744                }
1745            }
1746        }
1747
1748        UnsizingParams(unsizing_params)
1749    }
1750
1751    fn anonymize_bound_vars<T: rustc_type_ir::TypeFoldable<Self>>(
1752        self,
1753        value: rustc_type_ir::Binder<Self, T>,
1754    ) -> rustc_type_ir::Binder<Self, T> {
1755        struct Anonymize<'a, 'db> {
1756            interner: DbInterner<'db>,
1757            map: &'a mut FxIndexMap<BoundVar, BoundVariableKind<'db>>,
1758        }
1759        impl<'db> BoundVarReplacerDelegate<'db> for Anonymize<'_, 'db> {
1760            fn replace_region(&mut self, br: BoundRegion<'db>) -> Region<'db> {
1761                let entry = self.map.entry(br.var);
1762                let index = entry.index();
1763                let var = BoundVar::from_usize(index);
1764                let kind = (*entry
1765                    .or_insert_with(|| BoundVariableKind::Region(BoundRegionKind::Anon)))
1766                .expect_region();
1767                let br = BoundRegion { var, kind };
1768                Region::new_bound(self.interner, DebruijnIndex::ZERO, br)
1769            }
1770            fn replace_ty(&mut self, bt: BoundTy<'db>) -> Ty<'db> {
1771                let entry = self.map.entry(bt.var);
1772                let index = entry.index();
1773                let var = BoundVar::from_usize(index);
1774                let kind = (*entry.or_insert_with(|| BoundVariableKind::Ty(BoundTyKind::Anon)))
1775                    .expect_ty();
1776                Ty::new_bound(self.interner, DebruijnIndex::ZERO, BoundTy { var, kind })
1777            }
1778            fn replace_const(&mut self, bv: BoundConst<'db>) -> Const<'db> {
1779                let entry = self.map.entry(bv.var);
1780                let index = entry.index();
1781                let var = BoundVar::from_usize(index);
1782                let () = (*entry.or_insert_with(|| BoundVariableKind::Const)).expect_const();
1783                Const::new_bound(self.interner, DebruijnIndex::ZERO, BoundConst::new(var))
1784            }
1785        }
1786
1787        let mut map = Default::default();
1788        let delegate = Anonymize { interner: self, map: &mut map };
1789        let inner = self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate);
1790        let bound_vars = BoundVarKinds::new_from_iter(map.into_values());
1791        Binder::bind_with_vars(inner, bound_vars)
1792    }
1793
1794    fn opaque_types_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
1795        let Ok(def_id) = InferBodyId::try_from(def_id) else {
1796            return SolverDefIds::default();
1797        };
1798        let mut result = Vec::new();
1799        crate::opaques::opaque_types_defined_by(self.db, def_id, &mut result);
1800        SolverDefIds::new_from_slice(&result)
1801    }
1802
1803    fn opaque_types_and_coroutines_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
1804        let db = self.db;
1805
1806        let Ok(def_id) = InferBodyId::try_from(def_id) else {
1807            return SolverDefIds::default();
1808        };
1809        let mut result = Vec::new();
1810
1811        crate::opaques::opaque_types_defined_by(db, def_id, &mut result);
1812
1813        // Collect coroutines.
1814        let (store, root_expr) = def_id.store_and_root_expr(db);
1815        // We can't just visit all exprs, since this may end up in unrelated anon consts.
1816        CoroutinesVisitor { db: self.db, owner: def_id, store, coroutines: &mut result }
1817            .on_expr(root_expr);
1818
1819        return SolverDefIds::new_from_slice(&result);
1820
1821        struct CoroutinesVisitor<'a, 'db> {
1822            db: &'db dyn HirDatabase,
1823            owner: InferBodyId<'db>,
1824            store: &'db ExpressionStore,
1825            coroutines: &'a mut Vec<SolverDefId<'db>>,
1826        }
1827
1828        impl<'db> StoreVisitor for CoroutinesVisitor<'_, 'db> {
1829            fn on_expr(&mut self, expr: ExprId) {
1830                if let hir_def::hir::Expr::Closure {
1831                    closure_kind:
1832                        kind @ (hir_def::hir::ClosureKind::Coroutine { .. }
1833                        | hir_def::hir::ClosureKind::OldCoroutine(_)),
1834                    ..
1835                } = self.store[expr]
1836                {
1837                    let coroutine = InternedCoroutineId::new(
1838                        self.db,
1839                        InternedClosure { owner: self.owner, expr, kind },
1840                    );
1841                    self.coroutines.push(coroutine.into());
1842                }
1843
1844                self.store.visit_expr_children(expr, self);
1845            }
1846            fn on_pat(&mut self, pat: PatId) {
1847                self.store.visit_pat_children(pat, self);
1848            }
1849            // Do not visit anon consts, they're separate bodies.
1850            fn on_anon_const_expr(&mut self, _expr: ExprId) {}
1851        }
1852    }
1853
1854    fn alias_has_const_conditions(self, _def_id: Self::DefId) -> bool {
1855        // FIXME(next-solver)
1856        false
1857    }
1858
1859    fn explicit_implied_const_bounds(
1860        self,
1861        _def_id: Self::DefId,
1862    ) -> EarlyBinder<
1863        Self,
1864        impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
1865    > {
1866        // FIXME(next-solver)
1867        EarlyBinder::bind([])
1868    }
1869
1870    fn fn_is_const(self, id: Self::FunctionId) -> bool {
1871        let id = match id.0 {
1872            CallableDefId::FunctionId(id) => id,
1873            _ => return false,
1874        };
1875        FunctionSignature::of(self.db(), id).flags.contains(FnFlags::CONST)
1876    }
1877
1878    fn impl_is_const(self, _def_id: Self::ImplId) -> bool {
1879        false
1880    }
1881
1882    fn opt_alias_variances(
1883        self,
1884        _kind: impl Into<AliasTermKind<'db>>,
1885    ) -> Option<Self::VariancesOf> {
1886        None
1887    }
1888
1889    fn type_of_opaque_hir_typeck(
1890        self,
1891        opaque: Self::LocalOpaqueTyId,
1892    ) -> EarlyBinder<Self, Self::Ty> {
1893        let impl_trait_id = opaque.0.loc(self.db);
1894        // The entry is missing when this call cycles back into the still-running inference
1895        // of the defining body, as the cycle fallback is an empty result.
1896        let hidden_type = match impl_trait_id {
1897            crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
1898                crate::opaques::rpit_hidden_types(self.db, func).get(idx)
1899            }
1900            crate::ImplTraitId::TypeAliasImplTrait(type_alias, idx) => {
1901                crate::opaques::tait_hidden_types(self.db, type_alias).get(idx)
1902            }
1903        };
1904        match hidden_type {
1905            Some(hidden_type) => hidden_type.get(),
1906            None => EarlyBinder::bind(Ty::new_error(self, ErrorGuaranteed)),
1907        }
1908    }
1909
1910    fn coroutine_hidden_types(
1911        self,
1912        _def_id: Self::CoroutineId,
1913    ) -> EarlyBinder<Self, Binder<'db, CoroutineWitnessTypes<Self>>> {
1914        // FIXME: Actually implement this.
1915        EarlyBinder::bind(Binder::dummy(CoroutineWitnessTypes {
1916            types: Tys::default(),
1917            assumptions: RegionAssumptions::default(),
1918        }))
1919    }
1920
1921    fn is_default_trait(self, def_id: Self::TraitId) -> bool {
1922        self.as_trait_lang_item(def_id).map_or(false, |l| matches!(l, SolverTraitLangItem::Sized))
1923    }
1924
1925    fn trait_is_coinductive(self, trait_: Self::TraitId) -> bool {
1926        TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::COINDUCTIVE)
1927    }
1928
1929    fn trait_is_unsafe(self, trait_: Self::TraitId) -> bool {
1930        TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::UNSAFE)
1931    }
1932
1933    fn impl_self_is_guaranteed_unsized(self, _def_id: Self::ImplId) -> bool {
1934        false
1935    }
1936
1937    fn impl_specializes(
1938        self,
1939        specializing_impl_def_id: Self::ImplId,
1940        parent_impl_def_id: Self::ImplId,
1941    ) -> bool {
1942        let (AnyImplId::ImplId(specializing_impl_def_id), AnyImplId::ImplId(parent_impl_def_id)) =
1943            (specializing_impl_def_id, parent_impl_def_id)
1944        else {
1945            // No builtin derive allow specialization currently.
1946            return false;
1947        };
1948        crate::specialization::specializes(self.db, specializing_impl_def_id, parent_impl_def_id)
1949    }
1950
1951    fn next_trait_solver_globally(self) -> bool {
1952        true
1953    }
1954
1955    type Probe = rustc_type_ir::solve::inspect::Probe<DbInterner<'db>>;
1956    fn mk_probe(self, probe: rustc_type_ir::solve::inspect::Probe<Self>) -> Self::Probe {
1957        probe
1958    }
1959    fn evaluate_root_goal_for_proof_tree_raw(
1960        self,
1961        canonical_goal: rustc_type_ir::solve::CanonicalInput<Self>,
1962    ) -> (rustc_type_ir::solve::QueryResult<Self>, Self::Probe) {
1963        rustc_next_trait_solver::solve::evaluate_root_goal_for_proof_tree_raw_provider::<
1964            SolverContext<'db>,
1965            Self,
1966        >(self, canonical_goal)
1967    }
1968
1969    fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool {
1970        matches!(
1971            self.as_trait_lang_item(def_id),
1972            Some(SolverTraitLangItem::Sized | SolverTraitLangItem::MetaSized)
1973        )
1974    }
1975
1976    fn const_of_item(self, def_id: Self::DefId) -> rustc_type_ir::EarlyBinder<Self, Self::Const> {
1977        let id = match def_id {
1978            SolverDefId::StaticId(id) => id.into(),
1979            SolverDefId::ConstId(id) => id.into(),
1980            _ => unreachable!(),
1981        };
1982        EarlyBinder::bind(Const::new_unevaluated(
1983            self,
1984            UnevaluatedConst { def: GeneralConstIdWrapper(id), args: GenericArgs::empty() },
1985        ))
1986    }
1987
1988    fn anon_const_kind(self, _def_id: Self::DefId) -> rustc_type_ir::AnonConstKind {
1989        // FIXME
1990        rustc_type_ir::AnonConstKind::GCE
1991    }
1992
1993    fn alias_ty_kind_from_def_id(self, def_id: Self::DefId) -> AliasTyKind<'db> {
1994        match def_id {
1995            SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
1996                ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
1997                    AliasTyKind::Free { def_id: type_alias.into() }
1998                }
1999                ItemContainerId::ImplId(_) => AliasTyKind::Inherent { def_id: type_alias.into() },
2000                ItemContainerId::TraitId(_) => {
2001                    AliasTyKind::Projection { def_id: type_alias.into() }
2002                }
2003            },
2004            SolverDefId::InternedOpaqueTyId(def_id) => {
2005                AliasTyKind::Opaque { def_id: def_id.into() }
2006            }
2007            _ => unreachable!(),
2008        }
2009    }
2010
2011    fn closure_is_const(self, _def_id: Self::ClosureId) -> bool {
2012        // FIXME
2013        false
2014    }
2015
2016    fn item_name(self, _item_index: Self::DefId) -> Self::Symbol {
2017        Symbol
2018    }
2019}
2020
2021fn is_ty_self(ty: Ty<'_>) -> bool {
2022    match ty.kind() {
2023        TyKind::Param(param) => param.index == 0,
2024        _ => false,
2025    }
2026}
2027fn is_clause_at_ty(p: &Clause<'_>, filter: impl FnOnce(Ty<'_>) -> bool) -> bool {
2028    match p.kind().skip_binder() {
2029        // rustc has the following assertion:
2030        // https://github.com/rust-lang/rust/blob/52618eb338609df44978b0ca4451ab7941fd1c7a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs#L525-L608
2031        ClauseKind::Trait(it) => filter(it.self_ty()),
2032        ClauseKind::TypeOutlives(it) => filter(it.0),
2033        ClauseKind::Projection(it) => filter(it.self_ty()),
2034        ClauseKind::HostEffect(it) => filter(it.self_ty()),
2035        _ => false,
2036    }
2037}
2038
2039impl<'db> DbInterner<'db> {
2040    pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
2041    where
2042        T: rustc_type_ir::TypeFoldable<Self>,
2043    {
2044        let shift_bv = |bv: BoundVar| BoundVar::from_usize(bv.as_usize() + bound_vars);
2045        self.replace_escaping_bound_vars_uncached(
2046            value,
2047            FnMutDelegate {
2048                regions: &mut |r: BoundRegion<'db>| {
2049                    Region::new_bound(
2050                        self,
2051                        DebruijnIndex::ZERO,
2052                        BoundRegion { var: shift_bv(r.var), kind: r.kind },
2053                    )
2054                },
2055                types: &mut |t: BoundTy<'db>| {
2056                    Ty::new_bound(
2057                        self,
2058                        DebruijnIndex::ZERO,
2059                        BoundTy { var: shift_bv(t.var), kind: t.kind },
2060                    )
2061                },
2062                consts: &mut |c| {
2063                    Const::new_bound(self, DebruijnIndex::ZERO, BoundConst::new(shift_bv(c.var)))
2064                },
2065            },
2066        )
2067    }
2068
2069    pub fn replace_escaping_bound_vars_uncached<T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
2070        self,
2071        value: T,
2072        delegate: impl BoundVarReplacerDelegate<'db>,
2073    ) -> T {
2074        if !value.has_escaping_bound_vars() {
2075            value
2076        } else {
2077            let mut replacer = BoundVarReplacer::new(self, delegate);
2078            value.fold_with(&mut replacer)
2079        }
2080    }
2081
2082    pub fn replace_bound_vars_uncached<T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
2083        self,
2084        value: Binder<'db, T>,
2085        delegate: impl BoundVarReplacerDelegate<'db>,
2086    ) -> T {
2087        self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate)
2088    }
2089
2090    // FIXME: add splat support when the experiment is complete
2091    pub fn mk_fn_sig<I>(
2092        self,
2093        inputs: I,
2094        output: Ty<'db>,
2095        c_variadic: bool,
2096        safety: Safety,
2097        abi: ExternAbi,
2098    ) -> FnSig<'db>
2099    where
2100        I: IntoIterator<Item = Ty<'db>>,
2101    {
2102        FnSig {
2103            inputs_and_output: Tys::new_from_iter(
2104                inputs.into_iter().chain(std::iter::once(output)),
2105            ),
2106            fn_sig_kind: FnSigKind::new(abi, safety, c_variadic),
2107        }
2108    }
2109
2110    /// `mk_fn_sig`, but with a safe Rust ABI, and no C-variadic argument.
2111    pub fn mk_fn_sig_safe_rust_abi<I>(self, inputs: I, output: Ty<'db>) -> FnSig<'db>
2112    where
2113        I: IntoIterator<Item = Ty<'db>>,
2114    {
2115        self.mk_fn_sig(inputs, output, false, Safety::Safe, ExternAbi::Rust)
2116    }
2117}
2118
2119fn predicates_of<'db>(
2120    db: &'db dyn HirDatabase,
2121    def_id: SolverDefId<'db>,
2122) -> &'db GenericPredicates {
2123    match def_id {
2124        SolverDefId::BuiltinDeriveImplId(impl_) => crate::builtin_derive::predicates(db, impl_),
2125        SolverDefId::AnonConstId(anon_const) => {
2126            let loc = anon_const.loc(db);
2127            if loc.allow_using_generic_params {
2128                GenericPredicates::query(db, loc.owner.generic_def(db))
2129            } else {
2130                GenericPredicates::empty()
2131            }
2132        }
2133        _ => GenericPredicates::query(db, def_id.try_into().unwrap()),
2134    }
2135}
2136
2137macro_rules! TrivialTypeTraversalImpls {
2138    ($($ty:ty,)+) => {
2139        $(
2140            impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $ty {
2141                fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
2142                    self,
2143                    _: &mut F,
2144                ) -> ::std::result::Result<Self, F::Error> {
2145                    Ok(self)
2146                }
2147
2148                #[inline]
2149                fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
2150                    self,
2151                    _: &mut F,
2152                ) -> Self {
2153                    self
2154                }
2155            }
2156
2157            impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for $ty {
2158                #[inline]
2159                fn visit_with<F: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
2160                    &self,
2161                    _: &mut F)
2162                    -> F::Result
2163                {
2164                    <F::Result as rustc_ast_ir::visit::VisitorResult>::output()
2165                }
2166            }
2167
2168            impl<V> rustc_type_ir::GenericTypeVisitable<V> for $ty {
2169                #[inline]
2170                fn generic_visit_with(&self, _visitor: &mut V) {}
2171            }
2172        )+
2173    };
2174}
2175
2176TrivialTypeTraversalImpls! {
2177    SolverDefId<'_>,
2178    TraitIdWrapper,
2179    TypeAliasIdWrapper,
2180    CallableIdWrapper,
2181    ClosureIdWrapper<'_>,
2182    CoroutineIdWrapper<'_>,
2183    CoroutineClosureIdWrapper<'_>,
2184    AdtIdWrapper,
2185    TraitAssocTyId,
2186    TraitAssocConstId,
2187    TraitAssocTermId,
2188    ImplOrTraitAssocTyId,
2189    ImplOrTraitAssocConstId,
2190    ImplOrTraitAssocTermId,
2191    FreeTyAliasId,
2192    FreeConstAliasId,
2193    FreeTermAliasId,
2194    InherentAssocTyId,
2195    InherentAssocConstId,
2196    InherentAssocTermId,
2197    OpaqueTyIdWrapper<'_>,
2198    AnyImplId,
2199    GeneralConstIdWrapper<'_>,
2200    Safety,
2201    Span,
2202    ParamConst,
2203    ParamTy,
2204    EarlyParamRegion,
2205    AdtDef,
2206    ScalarInt,
2207}
2208
2209mod tls_db {
2210    use std::{cell::Cell, ptr::NonNull};
2211
2212    use crate::db::HirDatabase;
2213
2214    struct Attached {
2215        database: Cell<Option<NonNull<dyn HirDatabase>>>,
2216    }
2217
2218    impl Attached {
2219        #[inline]
2220        fn attach<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2221            struct DbGuard<'s> {
2222                state: Option<&'s Attached>,
2223            }
2224
2225            impl<'s> DbGuard<'s> {
2226                #[inline]
2227                fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
2228                    match attached.database.get() {
2229                        Some(current_db) => {
2230                            let new_db = NonNull::from(db);
2231                            if !std::ptr::addr_eq(current_db.as_ptr(), new_db.as_ptr()) {
2232                                panic!(
2233                                    "Cannot change attached database. This is likely a bug.\n\
2234                                    If this is not a bug, you can use `attach_db_allow_change()`."
2235                                );
2236                            }
2237                            Self { state: None }
2238                        }
2239                        None => {
2240                            // Otherwise, set the database.
2241                            attached.database.set(Some(NonNull::from(db)));
2242                            Self { state: Some(attached) }
2243                        }
2244                    }
2245                }
2246            }
2247
2248            impl Drop for DbGuard<'_> {
2249                #[inline]
2250                fn drop(&mut self) {
2251                    // Reset database to null if we did anything in `DbGuard::new`.
2252                    if let Some(attached) = self.state {
2253                        attached.database.set(None);
2254                    }
2255                }
2256            }
2257
2258            let _guard = DbGuard::new(self, db);
2259            super::tls_cache::reinit_cache(db);
2260            op()
2261        }
2262
2263        #[inline]
2264        fn attach_allow_change<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2265            struct DbGuard<'s> {
2266                state: &'s Attached,
2267                prev: Option<NonNull<dyn HirDatabase>>,
2268            }
2269
2270            impl<'s> DbGuard<'s> {
2271                #[inline]
2272                fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
2273                    let prev = attached.database.replace(Some(NonNull::from(db)));
2274                    Self { state: attached, prev }
2275                }
2276            }
2277
2278            impl Drop for DbGuard<'_> {
2279                #[inline]
2280                fn drop(&mut self) {
2281                    self.state.database.set(self.prev);
2282                    if let Some(prev) = self.prev {
2283                        super::tls_cache::reinit_cache(unsafe { prev.as_ref() });
2284                    }
2285                }
2286            }
2287
2288            let _guard = DbGuard::new(self, db);
2289            super::tls_cache::reinit_cache(db);
2290            op()
2291        }
2292
2293        #[inline]
2294        fn with<R>(&self, op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
2295            let db = self.database.get().expect("Tried to use attached db, but no db is attached");
2296
2297            // SAFETY: The db is attached, so it must be valid.
2298            op(unsafe { db.as_ref() })
2299        }
2300    }
2301
2302    thread_local! {
2303        static GLOBAL_DB: Attached = const { Attached { database: Cell::new(None) } };
2304    }
2305
2306    #[inline]
2307    pub fn attach_db<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2308        GLOBAL_DB.with(|global_db| global_db.attach(db, op))
2309    }
2310
2311    #[inline]
2312    pub fn attach_db_allow_change<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2313        GLOBAL_DB.with(|global_db| global_db.attach_allow_change(db, op))
2314    }
2315
2316    #[inline]
2317    pub fn with_attached_db<R>(op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
2318        GLOBAL_DB.with(
2319            #[inline]
2320            |a| a.with(op),
2321        )
2322    }
2323}
2324
2325mod tls_cache {
2326    use crate::db::HirDatabase;
2327
2328    use super::DbInterner;
2329    use base_db::Nonce;
2330    use rustc_type_ir::search_graph::GlobalCache;
2331    use salsa::Revision;
2332    use std::cell::RefCell;
2333
2334    struct Cache {
2335        cache: GlobalCache<DbInterner<'static>>,
2336        revision: Revision,
2337        db_nonce: Nonce,
2338    }
2339
2340    impl Cache {
2341        const fn default() -> Cache {
2342            Cache {
2343                cache: GlobalCache::new(),
2344                revision: Revision::max(),
2345                db_nonce: Nonce::invalid(),
2346            }
2347        }
2348    }
2349
2350    thread_local! {
2351        static GLOBAL_CACHE: RefCell<Cache> = const { RefCell::new(Cache::default()) };
2352    }
2353
2354    pub(super) fn reinit_cache(db: &dyn HirDatabase) {
2355        GLOBAL_CACHE.with_borrow_mut(|handle| {
2356            let (db_nonce, revision) = db.nonce_and_revision();
2357            if handle.revision != revision || db_nonce != handle.db_nonce {
2358                *handle = Cache { cache: GlobalCache::default(), revision, db_nonce };
2359            }
2360        })
2361    }
2362
2363    #[inline]
2364    pub(super) fn borrow_assume_valid<'db, T>(
2365        db: &'db dyn HirDatabase,
2366        f: impl FnOnce(&mut GlobalCache<DbInterner<'db>>) -> T,
2367    ) -> T {
2368        if cfg!(debug_assertions) {
2369            let get_state =
2370                || GLOBAL_CACHE.with_borrow(|handle| (handle.db_nonce, handle.revision));
2371            let old_state = get_state();
2372            reinit_cache(db);
2373            let new_state = get_state();
2374            assert_eq!(old_state, new_state, "you assumed the cache is valid!");
2375        }
2376
2377        GLOBAL_CACHE.with_borrow_mut(|handle| {
2378            // SAFETY: No idea
2379            f(unsafe {
2380                std::mem::transmute::<
2381                    &mut GlobalCache<DbInterner<'static>>,
2382                    &mut GlobalCache<DbInterner<'db>>,
2383                >(&mut handle.cache)
2384            })
2385        })
2386    }
2387
2388    /// Clears the thread-local trait solver cache.
2389    ///
2390    /// Should be called before getting memory usage estimations, as the solver cache
2391    /// is per-revision and usually should be excluded from estimations.
2392    pub fn clear_tls_solver_cache() {
2393        GLOBAL_CACHE.with_borrow_mut(|handle| *handle = Cache::default());
2394    }
2395}
2396
2397impl WorldExposer for intern::GarbageCollector {
2398    fn on_interned<T: intern::Internable>(
2399        &mut self,
2400        interned: InternedRef<'_, T>,
2401    ) -> ControlFlow<()> {
2402        self.mark_interned_alive(interned)
2403    }
2404
2405    fn on_interned_slice<T: intern::SliceInternable>(
2406        &mut self,
2407        interned: InternedSliceRef<'_, T>,
2408    ) -> ControlFlow<()> {
2409        self.mark_interned_slice_alive(interned)
2410    }
2411}
2412
2413/// # Safety
2414///
2415/// This cannot be called if there are some not-yet-recorded type values. Generally, if you have a mutable
2416/// reference to the database, and there are no other database - then you can call this safely, but you
2417/// also need to make sure to maintain the mutable reference while this is running.
2418pub unsafe fn collect_ty_garbage() {
2419    let mut gc = intern::GarbageCollector::default();
2420
2421    gc.add_storage::<super::consts::ConstInterned>();
2422    gc.add_storage::<super::consts::ValTreeInterned>();
2423    gc.add_storage::<super::allocation::AllocationInterned>();
2424    gc.add_storage::<PatternInterned>();
2425    gc.add_storage::<super::opaques::ExternalConstraintsInterned>();
2426    gc.add_storage::<super::predicate::PredicateInterned>();
2427    gc.add_storage::<super::region::RegionInterned>();
2428    gc.add_storage::<super::ty::TyInterned>();
2429
2430    gc.add_slice_storage::<super::consts::ConstsStorage>();
2431    gc.add_slice_storage::<super::predicate::ClausesStorage>();
2432    gc.add_slice_storage::<super::generic_arg::GenericArgsStorage>();
2433    gc.add_slice_storage::<BoundVarKindsStorage>();
2434    gc.add_slice_storage::<VariancesOfStorage>();
2435    gc.add_slice_storage::<CanonicalVarsStorage>();
2436    gc.add_slice_storage::<PatListStorage>();
2437    gc.add_slice_storage::<super::opaques::PredefinedOpaquesStorage>();
2438    gc.add_slice_storage::<super::opaques::SolverDefIdsStorage>();
2439    gc.add_slice_storage::<super::predicate::BoundExistentialPredicatesStorage>();
2440    gc.add_slice_storage::<super::region::RegionAssumptionsStorage>();
2441    gc.add_slice_storage::<super::ty::TysStorage>();
2442    gc.add_slice_storage::<crate::mir::ProjectionStorage>();
2443
2444    // SAFETY:
2445    //  - By our precondition, there are no unrecorded types.
2446    //  - We implement `GcInternedVisit` and `GcInternedSliceVisit` correctly for all types.
2447    //  - We added all storages (FIXME: it's too easy to forget to add a new storage here).
2448    unsafe { gc.collect() };
2449}
2450
2451macro_rules! impl_gc_visit {
2452    ( $($ty:ty),* $(,)? ) => {
2453        $(
2454            impl ::intern::GcInternedVisit for $ty {
2455                #[inline]
2456                fn visit_with(&self, gc: &mut ::intern::GarbageCollector) {
2457                    self.generic_visit_with(gc);
2458                }
2459            }
2460        )*
2461    };
2462}
2463
2464impl_gc_visit!(
2465    super::consts::ConstInterned,
2466    super::consts::ValTreeInterned,
2467    super::allocation::AllocationInterned,
2468    PatternInterned,
2469    super::opaques::ExternalConstraintsInterned,
2470    super::predicate::PredicateInterned,
2471    super::region::RegionInterned,
2472    super::ty::TyInterned,
2473    super::predicate::ClausesCachedTypeInfo,
2474);
2475
2476macro_rules! impl_gc_visit_slice {
2477    ( $($ty:ty),* $(,)? ) => {
2478        $(
2479            impl ::intern::GcInternedSliceVisit for $ty {
2480                #[inline]
2481                fn visit_header(header: &<Self as ::intern::SliceInternable>::Header, gc: &mut ::intern::GarbageCollector) {
2482                    header.generic_visit_with(gc);
2483                }
2484
2485                #[inline]
2486                fn visit_slice(slice: &[<Self as ::intern::SliceInternable>::SliceType], gc: &mut ::intern::GarbageCollector) {
2487                    slice.generic_visit_with(gc);
2488                }
2489            }
2490        )*
2491    };
2492}
2493
2494impl_gc_visit_slice!(
2495    super::predicate::ClausesStorage,
2496    super::generic_arg::GenericArgsStorage,
2497    BoundVarKindsStorage,
2498    VariancesOfStorage,
2499    CanonicalVarsStorage,
2500    PatListStorage,
2501    super::opaques::PredefinedOpaquesStorage,
2502    super::opaques::SolverDefIdsStorage,
2503    super::predicate::BoundExistentialPredicatesStorage,
2504    super::region::RegionAssumptionsStorage,
2505    super::ty::TysStorage,
2506    super::consts::ConstsStorage,
2507    crate::mir::ProjectionStorage,
2508);