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, TraitId, TypeAliasId, 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
875macro_rules! as_lang_item {
876    (
877        $solver_enum:ident, $self:ident, $def_id:expr, $id_ty:ty;
878
879        $( $variant:ident ),* $(,)?
880    ) => {{
881        let lang_items = $self.lang_items();
882        // Ensure exhaustiveness.
883        if let Some(it) = None::<$solver_enum> {
884            match it {
885                $( $solver_enum::$variant => {} )*
886            }
887        }
888        match $def_id {
889            $( def_id if let Some(it) = lang_items.$variant && <$id_ty>::from(it) == def_id => Some($solver_enum::$variant), )*
890            _ => None
891        }
892    }};
893}
894
895macro_rules! is_lang_item {
896    (
897        $solver_enum:ident, $self:ident, $def_id:expr, $expected_variant:ident;
898
899        $( $variant:ident ),* $(,)?
900    ) => {{
901        let lang_items = $self.lang_items();
902        let def_id = $def_id;
903        match $expected_variant {
904            $( $solver_enum::$variant => lang_items.$variant.is_some_and(|it| it == def_id), )*
905        }
906    }};
907}
908
909impl<'db> Interner for DbInterner<'db> {
910    type DefId = SolverDefId<'db>;
911    type LocalDefId = SolverDefId<'db>;
912    type LocalDefIds = SolverDefIds<'db>;
913    type TraitId = TraitIdWrapper;
914    type ForeignId = TypeAliasIdWrapper;
915    type FunctionId = CallableIdWrapper;
916    type ClosureId = ClosureIdWrapper<'db>;
917    type CoroutineClosureId = CoroutineClosureIdWrapper<'db>;
918    type CoroutineId = CoroutineIdWrapper<'db>;
919    type AdtId = AdtIdWrapper;
920    type ImplId = AnyImplId;
921    type UnevaluatedConstId = GeneralConstIdWrapper<'db>;
922    type TraitAssocTyId = TraitAssocTyId;
923    type TraitAssocConstId = TraitAssocConstId;
924    type TraitAssocTermId = TraitAssocTermId;
925    type OpaqueTyId = OpaqueTyIdWrapper<'db>;
926    type LocalOpaqueTyId = OpaqueTyIdWrapper<'db>;
927    type FreeTyAliasId = FreeTyAliasId;
928    type FreeConstAliasId = FreeConstAliasId;
929    type FreeTermAliasId = FreeTermAliasId;
930    type ImplOrTraitAssocTyId = ImplOrTraitAssocTyId;
931    type ImplOrTraitAssocConstId = ImplOrTraitAssocConstId;
932    type ImplOrTraitAssocTermId = ImplOrTraitAssocTermId;
933    type InherentAssocTyId = InherentAssocTyId;
934    type InherentAssocConstId = InherentAssocConstId;
935    type InherentAssocTermId = InherentAssocTermId;
936    type Span = Span;
937
938    type GenericArgs = GenericArgs<'db>;
939    type GenericArgsSlice = &'db [GenericArg<'db>];
940    type GenericArg = GenericArg<'db>;
941
942    type Term = Term<'db>;
943
944    type BoundVarKinds = BoundVarKinds<'db>;
945
946    type PredefinedOpaques = PredefinedOpaques<'db>;
947
948    fn mk_predefined_opaques_in_body(
949        self,
950        data: &[(OpaqueTypeKey<'db>, Self::Ty)],
951    ) -> Self::PredefinedOpaques {
952        PredefinedOpaques::new_from_slice(data)
953    }
954
955    type CanonicalVarKinds = CanonicalVarKinds<'db>;
956
957    fn mk_canonical_var_kinds(
958        self,
959        kinds: &[rustc_type_ir::CanonicalVarKind<Self>],
960    ) -> Self::CanonicalVarKinds {
961        CanonicalVarKinds::new_from_slice(kinds)
962    }
963
964    type ExternalConstraints = ExternalConstraints<'db>;
965
966    fn mk_external_constraints(
967        self,
968        data: rustc_type_ir::solve::ExternalConstraintsData<Self>,
969    ) -> Self::ExternalConstraints {
970        ExternalConstraints::new(self, data)
971    }
972
973    type DepNodeIndex = DepNodeIndex;
974
975    type Tracked<T: fmt::Debug + Clone> = Tracked<T>;
976
977    type Ty = Ty<'db>;
978    type Tys = Tys<'db>;
979    type FnInputTys = &'db [Ty<'db>];
980    type ParamTy = ParamTy;
981    type Symbol = Symbol;
982
983    type ErrorGuaranteed = ErrorGuaranteed;
984    type BoundExistentialPredicates = BoundExistentialPredicates<'db>;
985    type AllocId = AllocId;
986    type Pat = Pattern<'db>;
987    type PatList = PatList<'db>;
988    type Safety = Safety;
989
990    type Const = Const<'db>;
991    type ParamConst = ParamConst;
992    type ValueConst = ValueConst<'db>;
993    type ValTree = ValTree<'db>;
994    type Consts = Consts<'db>;
995    type ScalarInt = ScalarInt;
996    type ExprConst = ExprConst;
997
998    type Region = Region<'db>;
999    type EarlyParamRegion = EarlyParamRegion;
1000    type LateParamRegion = LateParamRegion<'db>;
1001
1002    type RegionAssumptions = RegionAssumptions<'db>;
1003
1004    type ParamEnv = ParamEnv<'db>;
1005    type Predicate = Predicate<'db>;
1006    type Clause = Clause<'db>;
1007    type Clauses = Clauses<'db>;
1008
1009    type GenericsOf = Generics<'db>;
1010
1011    type VariancesOf = VariancesOf<'db>;
1012
1013    type AdtDef = AdtDef;
1014
1015    type Features = Features;
1016
1017    fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs {
1018        GenericArgs::new_from_slice(args)
1019    }
1020
1021    fn mk_args_from_iter<I, T>(self, args: I) -> T::Output
1022    where
1023        I: Iterator<Item = T>,
1024        T: rustc_type_ir::CollectAndApply<Self::GenericArg, Self::GenericArgs>,
1025    {
1026        GenericArgs::new_from_iter(args)
1027    }
1028
1029    type UnsizingParams = UnsizingParams;
1030
1031    fn mk_tracked<T: fmt::Debug + Clone>(
1032        self,
1033        data: T,
1034        _dep_node: Self::DepNodeIndex,
1035    ) -> Self::Tracked<T> {
1036        Tracked(data)
1037    }
1038
1039    fn get_tracked<T: fmt::Debug + Clone>(self, tracked: &Self::Tracked<T>) -> T {
1040        tracked.0.clone()
1041    }
1042
1043    fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, Self::DepNodeIndex) {
1044        (task(), DepNodeIndex)
1045    }
1046
1047    fn with_global_cache<R>(
1048        self,
1049        f: impl FnOnce(&mut rustc_type_ir::search_graph::GlobalCache<Self>) -> R,
1050    ) -> R {
1051        // We make sure to reinit the cache when constructing the Interner.
1052        tls_cache::borrow_assume_valid(self.db, f)
1053    }
1054
1055    fn canonical_param_env_cache_get_or_insert<R>(
1056        self,
1057        _param_env: Self::ParamEnv,
1058        f: impl FnOnce() -> rustc_type_ir::CanonicalParamEnvCacheEntry<Self>,
1059        from_entry: impl FnOnce(&rustc_type_ir::CanonicalParamEnvCacheEntry<Self>) -> R,
1060    ) -> R {
1061        from_entry(&f())
1062    }
1063
1064    fn assert_evaluation_is_concurrent(&self) {
1065        // Turns out, the assumption for this function isn't perfect.
1066        // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/234
1067    }
1068
1069    fn expand_abstract_consts<T: rustc_type_ir::TypeFoldable<Self>>(self, _: T) -> T {
1070        unreachable!("only used by the old trait solver in rustc");
1071    }
1072
1073    fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf {
1074        generics(self, def_id)
1075    }
1076
1077    fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
1078        let generic_def = match def_id {
1079            SolverDefId::Ctor(Ctor::Enum(def_id)) | SolverDefId::EnumVariantId(def_id) => {
1080                def_id.loc(self.db).parent.into()
1081            }
1082            SolverDefId::InternedOpaqueTyId(_def_id) => {
1083                // FIXME(next-solver): track variances
1084                //
1085                // We compute them based on the only `Ty` level info in rustc,
1086                // move `variances_of_opaque` into `rustc_next_trait_solver` for reuse.
1087                return VariancesOf::new_from_iter(
1088                    (0..self.generics_of(def_id).count()).map(|_| Variance::Invariant),
1089                );
1090            }
1091            SolverDefId::Ctor(Ctor::Struct(def_id)) => def_id.into(),
1092            SolverDefId::AdtId(def_id) => def_id.into(),
1093            SolverDefId::FunctionId(def_id) => def_id.into(),
1094            SolverDefId::ConstId(_)
1095            | SolverDefId::StaticId(_)
1096            | SolverDefId::TraitId(_)
1097            | SolverDefId::TypeAliasId(_)
1098            | SolverDefId::ImplId(_)
1099            | SolverDefId::BuiltinDeriveImplId(_)
1100            | SolverDefId::InternedClosureId(_)
1101            | SolverDefId::InternedCoroutineId(_)
1102            | SolverDefId::InternedCoroutineClosureId(_)
1103            | SolverDefId::AnonConstId(_) => {
1104                return VariancesOf::empty();
1105            }
1106        };
1107        self.db.variances_of(generic_def)
1108    }
1109
1110    fn type_of(self, def_id: Self::DefId) -> EarlyBinder<Self, Self::Ty> {
1111        match def_id {
1112            SolverDefId::TypeAliasId(id) => self.db().ty(id.into()),
1113            SolverDefId::AdtId(id) => self.db().ty(id.into()),
1114            // FIXME(next-solver): This uses the types of `query mir_borrowck` in rustc.
1115            //
1116            // We currently always use the type from HIR typeck which ignores regions. This
1117            // should be fine.
1118            SolverDefId::InternedOpaqueTyId(def_id) => {
1119                self.type_of_opaque_hir_typeck(def_id.into())
1120            }
1121            SolverDefId::FunctionId(id) => self.db.value_ty(id.into()).unwrap(),
1122            SolverDefId::Ctor(id) => {
1123                let id = match id {
1124                    Ctor::Struct(id) => id.into(),
1125                    Ctor::Enum(id) => id.into(),
1126                };
1127                self.db.value_ty(id).expect("`SolverDefId::Ctor` should have a function-like ctor")
1128            }
1129            _ => panic!("Unexpected def_id `{def_id:?}` provided for `type_of`"),
1130        }
1131    }
1132
1133    fn adt_def(self, def_id: Self::AdtId) -> Self::AdtDef {
1134        AdtDef::new(def_id.0, self)
1135    }
1136
1137    fn alias_term_kind_from_def_id(self, def_id: SolverDefId<'db>) -> AliasTermKind<'db> {
1138        match def_id {
1139            SolverDefId::InternedOpaqueTyId(def_id) => {
1140                AliasTermKind::OpaqueTy { def_id: def_id.into() }
1141            }
1142            SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
1143                ItemContainerId::ImplId(impl_)
1144                    if ImplSignature::of(self.db, impl_).target_trait.is_none() =>
1145                {
1146                    AliasTermKind::InherentTy { def_id: type_alias.into() }
1147                }
1148                ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => {
1149                    AliasTermKind::ProjectionTy { def_id: type_alias.into() }
1150                }
1151                _ => AliasTermKind::FreeTy { def_id: type_alias.into() },
1152            },
1153            // rustc creates an `AnonConst` for consts, and evaluates them with CTFE (normalizing projections
1154            // via selection, similar to ours `find_matching_impl()`, and not with the trait solver), so mimic it.
1155            SolverDefId::ConstId(def_id) => {
1156                AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1157            }
1158            SolverDefId::StaticId(def_id) => {
1159                AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1160            }
1161            SolverDefId::AnonConstId(def_id) => {
1162                AliasTermKind::UnevaluatedConst { def_id: GeneralConstIdWrapper(def_id.into()) }
1163            }
1164            _ => unimplemented!("Unexpected alias: {:?}", def_id),
1165        }
1166    }
1167
1168    fn trait_ref_and_own_args_for_alias(
1169        self,
1170        def_id: Self::TraitAssocTermId,
1171        args: Self::GenericArgs,
1172    ) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
1173        let trait_def_id = self.projection_parent(def_id);
1174        let trait_ref = TraitRef::from_assoc(self, trait_def_id, args);
1175        (trait_ref, &args.as_slice()[trait_ref.args.len()..])
1176    }
1177
1178    fn check_args_compatible(self, def_id: Self::DefId, args: Self::GenericArgs) -> bool {
1179        let generics = self.generics_of(def_id);
1180        generics.count() == args.len()
1181            && std::iter::zip(generics.iter(), args).all(|((param, _), arg)| {
1182                matches!(
1183                    (param, arg.kind()),
1184                    (GenericParamId::LifetimeParamId(_), GenericArgKind::Lifetime(_))
1185                        | (GenericParamId::TypeParamId(_), GenericArgKind::Type(_))
1186                        | (GenericParamId::ConstParamId(_), GenericArgKind::Const(_))
1187                )
1188            })
1189    }
1190
1191    fn debug_assert_args_compatible(self, _def_id: Self::DefId, _args: Self::GenericArgs) {}
1192
1193    fn debug_assert_existential_args_compatible(
1194        self,
1195        _def_id: Self::DefId,
1196        _args: Self::GenericArgs,
1197    ) {
1198    }
1199
1200    fn mk_type_list_from_iter<I, T>(self, args: I) -> T::Output
1201    where
1202        I: Iterator<Item = T>,
1203        T: rustc_type_ir::CollectAndApply<Self::Ty, Self::Tys>,
1204    {
1205        Tys::new_from_iter(args)
1206    }
1207
1208    fn projection_parent(self, def_id: Self::TraitAssocTermId) -> Self::TraitId {
1209        let container = match def_id.0 {
1210            TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1211            TermId::ConstId(def_id) => def_id.loc(self.db).container,
1212        };
1213        let ItemContainerId::TraitId(trait_) = container else {
1214            panic!("a TraitAssocTermId can only come from a trait")
1215        };
1216        trait_.into()
1217    }
1218
1219    fn impl_or_trait_assoc_term_parent(self, def_id: Self::ImplOrTraitAssocTermId) -> Self::DefId {
1220        let container = match def_id.0 {
1221            TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1222            TermId::ConstId(def_id) => def_id.loc(self.db).container,
1223        };
1224        match container {
1225            ItemContainerId::ImplId(impl_) => impl_.into(),
1226            ItemContainerId::TraitId(trait_) => trait_.into(),
1227            ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
1228                panic!("only impl or trait can be the parent of ImplOrTraitAssocTermId")
1229            }
1230        }
1231    }
1232
1233    fn inherent_alias_term_parent(self, def_id: Self::InherentAssocTermId) -> Self::ImplId {
1234        let container = match def_id.0 {
1235            TermId::TypeAliasId(def_id) => def_id.loc(self.db).container,
1236            TermId::ConstId(def_id) => def_id.loc(self.db).container,
1237        };
1238        match container {
1239            ItemContainerId::ImplId(impl_) => impl_.into(),
1240            ItemContainerId::ExternBlockId(_)
1241            | ItemContainerId::ModuleId(_)
1242            | ItemContainerId::TraitId(_) => {
1243                panic!("only impl can be the parent of InherentAliasTermId")
1244            }
1245        }
1246    }
1247
1248    fn recursion_limit(self) -> usize {
1249        50
1250    }
1251
1252    fn is_type_const(self, _def_id: Self::DefId) -> bool {
1253        false
1254    }
1255
1256    fn features(self) -> Features {
1257        Features
1258    }
1259
1260    fn fn_sig(
1261        self,
1262        def_id: Self::FunctionId,
1263    ) -> EarlyBinder<Self, rustc_type_ir::Binder<Self, rustc_type_ir::FnSig<Self>>> {
1264        self.db().callable_item_signature(def_id.0)
1265    }
1266
1267    fn coroutine_movability(self, def_id: Self::CoroutineId) -> rustc_ast_ir::Movability {
1268        match def_id.0.loc(self.db).kind {
1269            hir_def::hir::ClosureKind::OldCoroutine(movability) => match movability {
1270                hir_def::hir::Movability::Static => rustc_ast_ir::Movability::Static,
1271                hir_def::hir::Movability::Movable => rustc_ast_ir::Movability::Movable,
1272            },
1273            hir_def::hir::ClosureKind::Coroutine { .. } => rustc_ast_ir::Movability::Static,
1274            kind => panic!("unexpected kind for a coroutine: {kind:?}"),
1275        }
1276    }
1277
1278    fn coroutine_for_closure(self, def_id: Self::CoroutineClosureId) -> Self::CoroutineId {
1279        let InternedClosure { owner, expr: coroutine_closure_expr, kind: coroutine_closure_kind } =
1280            def_id.0.loc(self.db);
1281        let coroutine_closure_kind = match coroutine_closure_kind {
1282            HirClosureKind::CoroutineClosure(it) => it,
1283            _ => {
1284                panic!("invalid kind closure kind {coroutine_closure_kind:?} for coroutine closure")
1285            }
1286        };
1287        let coroutine_expr = ExpressionStore::coroutine_for_closure(coroutine_closure_expr);
1288        let coroutine_kind = hir_def::hir::ClosureKind::Coroutine {
1289            kind: coroutine_closure_kind,
1290            source: hir_def::hir::CoroutineSource::Closure,
1291        };
1292        InternedCoroutineId::new(
1293            self.db,
1294            InternedClosure { owner, expr: coroutine_expr, kind: coroutine_kind },
1295        )
1296        .into()
1297    }
1298
1299    fn generics_require_sized_self(self, def_id: Self::DefId) -> bool {
1300        match GenericDefId::try_from(def_id) {
1301            Ok(def_id) => crate::dyn_compatibility::generics_require_sized_self(self.db, def_id),
1302            Err(_) => false,
1303        }
1304    }
1305
1306    #[tracing::instrument(skip(self))]
1307    fn item_bounds(
1308        self,
1309        def_id: Self::DefId,
1310    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1311        ItemBounds::of_solver_def(self.db, def_id).all_bounds()
1312    }
1313
1314    #[tracing::instrument(skip(self))]
1315    fn item_self_bounds(
1316        self,
1317        def_id: Self::DefId,
1318    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1319        ItemBounds::of_solver_def(self.db, def_id).self_bounds()
1320    }
1321
1322    fn item_non_self_bounds(
1323        self,
1324        def_id: Self::DefId,
1325    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1326        ItemBounds::of_solver_def(self.db, def_id).non_self_bounds()
1327    }
1328
1329    fn predicates_of(
1330        self,
1331        def_id: Self::DefId,
1332    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1333        predicates_of(self.db, def_id).all_predicates()
1334    }
1335
1336    fn own_predicates_of(
1337        self,
1338        def_id: Self::DefId,
1339    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1340        predicates_of(self.db, def_id).own_explicit_predicates()
1341    }
1342
1343    fn explicit_super_predicates_of(
1344        self,
1345        def_id: Self::TraitId,
1346    ) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
1347        GenericPredicates::query(self.db, def_id.0.into())
1348            .explicit_non_assoc_types_predicates()
1349            .map_bound(move |predicates| {
1350                predicates.filter(|p| is_clause_at_ty(p, is_ty_self)).map(|p| (p, Span::dummy()))
1351            })
1352    }
1353
1354    fn explicit_implied_predicates_of(
1355        self,
1356        def_id: Self::DefId,
1357    ) -> EarlyBinder<Self, impl IntoIterator<Item = (Self::Clause, Self::Span)>> {
1358        fn is_ty_assoc_of_self(ty: Ty<'_>) -> bool {
1359            // FIXME: Is this correct wrt. combined kind of assoc type bounds, i.e. `where Self::Assoc: Trait<Assoc2: Trait>`
1360            // wrt. `Assoc2`, which we should exclude?
1361            if let TyKind::Alias(alias @ AliasTy { kind: AliasTyKind::Projection { .. }, .. }) =
1362                ty.kind()
1363            {
1364                is_ty_assoc_of_self(alias.self_ty())
1365            } else {
1366                is_ty_self(ty)
1367            }
1368        }
1369
1370        let predicates = predicates_of(self.db, def_id);
1371        let non_assoc_types = predicates
1372            .explicit_non_assoc_types_predicates()
1373            .skip_binder()
1374            .filter(|p| is_clause_at_ty(p, is_ty_self));
1375        let assoc_types = predicates
1376            .explicit_assoc_types_predicates()
1377            .skip_binder()
1378            .filter(|p| is_clause_at_ty(p, is_ty_assoc_of_self));
1379        EarlyBinder::bind(non_assoc_types.chain(assoc_types).map(|it| (it, Span::dummy())))
1380    }
1381
1382    fn impl_super_outlives(
1383        self,
1384        impl_id: Self::ImplId,
1385    ) -> EarlyBinder<Self, impl IntoIterator<Item = Self::Clause>> {
1386        let bounds = match impl_id {
1387            AnyImplId::ImplId(id) => {
1388                impl_super_outlives(self.db, id).get().map_bound(|it| it.as_slice())
1389            }
1390            AnyImplId::BuiltinDeriveImplId(id) => {
1391                crate::builtin_derive::impl_super_outlives(self, id)
1392            }
1393        };
1394        bounds.map_bound(|it| it.iter().copied())
1395    }
1396
1397    #[expect(unreachable_code)]
1398    fn const_conditions(
1399        self,
1400        _def_id: Self::DefId,
1401    ) -> EarlyBinder<
1402        Self,
1403        impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
1404    > {
1405        EarlyBinder::bind([unimplemented!()])
1406    }
1407
1408    fn has_target_features(self, _def_id: Self::FunctionId) -> bool {
1409        false
1410    }
1411
1412    fn require_projection_lang_item(
1413        self,
1414        lang_item: SolverProjectionLangItem,
1415    ) -> Self::TraitAssocTyId {
1416        let lang_items = self.lang_items();
1417        let lang_item = match lang_item {
1418            SolverProjectionLangItem::AsyncFnKindUpvars => lang_items.AsyncFnKindUpvars,
1419            SolverProjectionLangItem::AsyncFnOnceOutput => lang_items.AsyncFnOnceOutput,
1420            SolverProjectionLangItem::CallOnceFuture => lang_items.CallOnceFuture,
1421            SolverProjectionLangItem::CallRefFuture => lang_items.CallRefFuture,
1422            SolverProjectionLangItem::CoroutineReturn => lang_items.CoroutineReturn,
1423            SolverProjectionLangItem::CoroutineYield => lang_items.CoroutineYield,
1424            SolverProjectionLangItem::FutureOutput => lang_items.FutureOutput,
1425            SolverProjectionLangItem::Metadata => lang_items.Metadata,
1426            SolverProjectionLangItem::FieldBase => lang_items.FieldBase,
1427            SolverProjectionLangItem::FieldType => lang_items.FieldType,
1428        };
1429        lang_item.expect("Lang item required but not found.").into()
1430    }
1431
1432    fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> TraitIdWrapper {
1433        let lang_items = self.lang_items();
1434        let lang_item = match lang_item {
1435            SolverTraitLangItem::AsyncFn => lang_items.AsyncFn,
1436            SolverTraitLangItem::AsyncFnKindHelper => lang_items.AsyncFnKindHelper,
1437            SolverTraitLangItem::AsyncFnMut => lang_items.AsyncFnMut,
1438            SolverTraitLangItem::AsyncFnOnce => lang_items.AsyncFnOnce,
1439            SolverTraitLangItem::AsyncIterator => lang_items.AsyncIterator,
1440            SolverTraitLangItem::Clone => lang_items.Clone,
1441            SolverTraitLangItem::Copy => lang_items.Copy,
1442            SolverTraitLangItem::Coroutine => lang_items.Coroutine,
1443            SolverTraitLangItem::Destruct => lang_items.Destruct,
1444            SolverTraitLangItem::DiscriminantKind => lang_items.DiscriminantKind,
1445            SolverTraitLangItem::Drop => lang_items.Drop,
1446            SolverTraitLangItem::Fn => lang_items.Fn,
1447            SolverTraitLangItem::FnMut => lang_items.FnMut,
1448            SolverTraitLangItem::FnOnce => lang_items.FnOnce,
1449            SolverTraitLangItem::FnPtrTrait => lang_items.FnPtrTrait,
1450            SolverTraitLangItem::FusedIterator => lang_items.FusedIterator,
1451            SolverTraitLangItem::Future => lang_items.Future,
1452            SolverTraitLangItem::Iterator => lang_items.Iterator,
1453            SolverTraitLangItem::PointeeTrait => lang_items.PointeeTrait,
1454            SolverTraitLangItem::Sized => lang_items.Sized,
1455            SolverTraitLangItem::MetaSized => lang_items.MetaSized,
1456            SolverTraitLangItem::PointeeSized => lang_items.PointeeSized,
1457            SolverTraitLangItem::TransmuteTrait => lang_items.TransmuteTrait,
1458            SolverTraitLangItem::Tuple => lang_items.Tuple,
1459            SolverTraitLangItem::Unpin => lang_items.Unpin,
1460            SolverTraitLangItem::Unsize => lang_items.Unsize,
1461            SolverTraitLangItem::BikeshedGuaranteedNoDrop => lang_items.BikeshedGuaranteedNoDrop,
1462            SolverTraitLangItem::TrivialClone => lang_items.TrivialClone,
1463            SolverTraitLangItem::Field => lang_items.Field,
1464        };
1465        lang_item.expect("Lang item required but not found.").into()
1466    }
1467
1468    fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> AdtIdWrapper {
1469        let lang_items = self.lang_items();
1470        let lang_item = match lang_item {
1471            SolverAdtLangItem::Option => lang_items.Option.map(Into::into),
1472            SolverAdtLangItem::Poll => lang_items.Poll.map(Into::into),
1473            SolverAdtLangItem::DynMetadata => lang_items.DynMetadata.map(Into::into),
1474        };
1475        AdtIdWrapper(lang_item.expect("Lang item required but not found."))
1476    }
1477
1478    fn is_projection_lang_item(
1479        self,
1480        def_id: Self::TraitAssocTyId,
1481        lang_item: SolverProjectionLangItem,
1482    ) -> bool {
1483        self.as_projection_lang_item(def_id)
1484            .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item))
1485    }
1486
1487    fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool {
1488        is_lang_item!(
1489            SolverTraitLangItem, self, def_id.0, lang_item;
1490
1491            Sized,
1492            MetaSized,
1493            PointeeSized,
1494            Unsize,
1495            Copy,
1496            Clone,
1497            DiscriminantKind,
1498            PointeeTrait,
1499            FnPtrTrait,
1500            Drop,
1501            Destruct,
1502            TransmuteTrait,
1503            Fn,
1504            FnMut,
1505            FnOnce,
1506            Future,
1507            Coroutine,
1508            Unpin,
1509            Tuple,
1510            Iterator,
1511            AsyncFn,
1512            AsyncFnMut,
1513            AsyncFnOnce,
1514            TrivialClone,
1515            AsyncFnKindHelper,
1516            AsyncIterator,
1517            BikeshedGuaranteedNoDrop,
1518            FusedIterator,
1519            Field,
1520        )
1521    }
1522
1523    fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool {
1524        // FIXME: derive PartialEq on SolverTraitLangItem
1525        self.as_adt_lang_item(def_id)
1526            .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item))
1527    }
1528
1529    fn as_projection_lang_item(
1530        self,
1531        def_id: Self::TraitAssocTyId,
1532    ) -> Option<SolverProjectionLangItem> {
1533        as_lang_item!(
1534            SolverProjectionLangItem, self, def_id.0, TypeAliasId;
1535
1536            Metadata,
1537            CoroutineReturn,
1538            CoroutineYield,
1539            FutureOutput,
1540            CallRefFuture,
1541            CallOnceFuture,
1542            AsyncFnOnceOutput,
1543            AsyncFnKindUpvars,
1544            FieldBase,
1545            FieldType,
1546        )
1547    }
1548
1549    fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem> {
1550        as_lang_item!(
1551            SolverTraitLangItem, self, def_id.0, TraitId;
1552
1553            Sized,
1554            MetaSized,
1555            PointeeSized,
1556            Unsize,
1557            Copy,
1558            Clone,
1559            DiscriminantKind,
1560            PointeeTrait,
1561            FnPtrTrait,
1562            Drop,
1563            Destruct,
1564            TransmuteTrait,
1565            Fn,
1566            FnMut,
1567            FnOnce,
1568            Future,
1569            Coroutine,
1570            Unpin,
1571            Tuple,
1572            Iterator,
1573            AsyncFn,
1574            AsyncFnMut,
1575            AsyncFnOnce,
1576            TrivialClone,
1577            AsyncFnKindHelper,
1578            AsyncIterator,
1579            BikeshedGuaranteedNoDrop,
1580            FusedIterator,
1581            Field,
1582        )
1583    }
1584
1585    fn as_adt_lang_item(self, def_id: Self::AdtId) -> Option<SolverAdtLangItem> {
1586        as_lang_item!(
1587            SolverAdtLangItem, self, def_id.0, AdtId;
1588
1589            Option,
1590            Poll,
1591            DynMetadata,
1592        )
1593    }
1594
1595    fn associated_type_def_ids(
1596        self,
1597        def_id: Self::TraitId,
1598    ) -> impl IntoIterator<Item = Self::DefId> {
1599        def_id.0.trait_items(self.db()).associated_types().map(|id| id.into())
1600    }
1601
1602    fn for_each_relevant_impl<R: VisitorResult>(
1603        self,
1604        trait_def_id: Self::TraitId,
1605        self_ty: Self::Ty,
1606        mut f: impl FnMut(Self::ImplId) -> R,
1607    ) -> R {
1608        let krate = self.krate.expect("trait solving requires setting `DbInterner::krate`");
1609        let trait_block = trait_def_id.0.loc(self.db).container.block(self.db);
1610        let mut consider_impls_for_simplified_type = |simp: SimplifiedType<'_>| {
1611            let type_block = simp.def().and_then(|def_id| {
1612                let module = match def_id {
1613                    SolverDefId::AdtId(AdtId::StructId(id)) => id.module(self.db),
1614                    SolverDefId::AdtId(AdtId::EnumId(id)) => id.module(self.db),
1615                    SolverDefId::AdtId(AdtId::UnionId(id)) => id.module(self.db),
1616                    SolverDefId::TraitId(id) => id.module(self.db),
1617                    SolverDefId::TypeAliasId(id) => id.module(self.db),
1618                    SolverDefId::ConstId(_)
1619                    | SolverDefId::FunctionId(_)
1620                    | SolverDefId::ImplId(_)
1621                    | SolverDefId::BuiltinDeriveImplId(_)
1622                    | SolverDefId::StaticId(_)
1623                    | SolverDefId::InternedClosureId(_)
1624                    | SolverDefId::InternedCoroutineId(_)
1625                    | SolverDefId::InternedCoroutineClosureId(_)
1626                    | SolverDefId::InternedOpaqueTyId(_)
1627                    | SolverDefId::EnumVariantId(_)
1628                    | SolverDefId::AnonConstId(_)
1629                    | SolverDefId::Ctor(_) => return None,
1630                };
1631                module.block(self.db)
1632            });
1633            TraitImpls::for_each_crate_and_block_trait_and_type(
1634                self.db,
1635                krate,
1636                type_block,
1637                trait_block,
1638                &mut |impls| {
1639                    let (regular_impls, builtin_derive_impls) =
1640                        impls.for_trait_and_self_ty(trait_def_id.0, &simp);
1641                    for &impl_ in regular_impls {
1642                        try_visit!(f(impl_.into()));
1643                    }
1644                    for &impl_ in builtin_derive_impls {
1645                        try_visit!(f(impl_.into()));
1646                    }
1647                    R::output()
1648                },
1649            )
1650        };
1651
1652        match self_ty.kind() {
1653            TyKind::Bool
1654            | TyKind::Char
1655            | TyKind::Int(_)
1656            | TyKind::Uint(_)
1657            | TyKind::Float(_)
1658            | TyKind::Adt(_, _)
1659            | TyKind::Foreign(_)
1660            | TyKind::Str
1661            | TyKind::Array(_, _)
1662            | TyKind::Pat(_, _)
1663            | TyKind::Slice(_)
1664            | TyKind::RawPtr(_, _)
1665            | TyKind::Ref(_, _, _)
1666            | TyKind::FnDef(_, _)
1667            | TyKind::FnPtr(..)
1668            | TyKind::Dynamic(_, _)
1669            | TyKind::Closure(..)
1670            | TyKind::CoroutineClosure(..)
1671            | TyKind::Coroutine(_, _)
1672            | TyKind::Never
1673            | TyKind::Tuple(_)
1674            | TyKind::UnsafeBinder(_) => {
1675                let simp =
1676                    fast_reject::simplify_type(self, self_ty, fast_reject::TreatParams::AsRigid)
1677                        .unwrap();
1678                try_visit!(consider_impls_for_simplified_type(simp));
1679            }
1680
1681            // HACK: For integer and float variables we have to manually look at all impls
1682            // which have some integer or float as a self type.
1683            TyKind::Infer(InferTy::IntVar(_)) => {
1684                use IntTy::*;
1685                use UintTy::*;
1686                // This causes a compiler error if any new integer kinds are added.
1687                let (I8 | I16 | I32 | I64 | I128 | Isize): IntTy;
1688                let (U8 | U16 | U32 | U64 | U128 | Usize): UintTy;
1689                let possible_integers = [
1690                    // signed integers
1691                    SimplifiedType::Int(I8),
1692                    SimplifiedType::Int(I16),
1693                    SimplifiedType::Int(I32),
1694                    SimplifiedType::Int(I64),
1695                    SimplifiedType::Int(I128),
1696                    SimplifiedType::Int(Isize),
1697                    // unsigned integers
1698                    SimplifiedType::Uint(U8),
1699                    SimplifiedType::Uint(U16),
1700                    SimplifiedType::Uint(U32),
1701                    SimplifiedType::Uint(U64),
1702                    SimplifiedType::Uint(U128),
1703                    SimplifiedType::Uint(Usize),
1704                ];
1705                for simp in possible_integers {
1706                    try_visit!(consider_impls_for_simplified_type(simp));
1707                }
1708            }
1709
1710            TyKind::Infer(InferTy::FloatVar(_)) => {
1711                // This causes a compiler error if any new float kinds are added.
1712                let (FloatTy::F16 | FloatTy::F32 | FloatTy::F64 | FloatTy::F128);
1713                let possible_floats = [
1714                    SimplifiedType::Float(FloatTy::F16),
1715                    SimplifiedType::Float(FloatTy::F32),
1716                    SimplifiedType::Float(FloatTy::F64),
1717                    SimplifiedType::Float(FloatTy::F128),
1718                ];
1719
1720                for simp in possible_floats {
1721                    try_visit!(consider_impls_for_simplified_type(simp));
1722                }
1723            }
1724
1725            // The only traits applying to aliases and placeholders are blanket impls.
1726            //
1727            // Impls which apply to an alias after normalization are handled by
1728            // `assemble_candidates_after_normalizing_self_ty`.
1729            TyKind::Alias(..) | TyKind::Placeholder(..) | TyKind::Error(_) => (),
1730
1731            // FIXME: These should ideally not exist as a self type. It would be nice for
1732            // the builtin auto trait impls of coroutines to instead directly recurse
1733            // into the witness.
1734            TyKind::CoroutineWitness(..) => (),
1735
1736            // These variants should not exist as a self type.
1737            TyKind::Infer(
1738                InferTy::TyVar(_)
1739                | InferTy::FreshTy(_)
1740                | InferTy::FreshIntTy(_)
1741                | InferTy::FreshFloatTy(_),
1742            )
1743            | TyKind::Param(_)
1744            | TyKind::Bound(_, _) => panic!("unexpected self type: {self_ty:?}"),
1745        }
1746
1747        self.for_each_blanket_impl(trait_def_id, f)
1748    }
1749
1750    fn for_each_blanket_impl<R: VisitorResult>(
1751        self,
1752        trait_def_id: Self::TraitId,
1753        mut f: impl FnMut(Self::ImplId) -> R,
1754    ) -> R {
1755        let Some(krate) = self.krate else {
1756            return R::output();
1757        };
1758        let block = trait_def_id.0.loc(self.db).container.block(self.db);
1759
1760        TraitImpls::for_each_crate_and_block(self.db, krate, block, &mut |impls| {
1761            for &impl_ in impls.blanket_impls(trait_def_id.0) {
1762                try_visit!(f(impl_.into()));
1763            }
1764            R::output()
1765        })
1766    }
1767
1768    fn has_item_definition(self, _def_id: Self::ImplOrTraitAssocTermId) -> bool {
1769        // FIXME(next-solver): should check if the associated item has a value.
1770        true
1771    }
1772
1773    fn impl_is_default(self, impl_def_id: Self::ImplId) -> bool {
1774        match impl_def_id {
1775            AnyImplId::ImplId(impl_id) => ImplSignature::of(self.db, impl_id).is_default(),
1776            AnyImplId::BuiltinDeriveImplId(_) => false,
1777        }
1778    }
1779
1780    #[tracing::instrument(skip(self), ret)]
1781    fn impl_trait_ref(
1782        self,
1783        impl_id: Self::ImplId,
1784    ) -> EarlyBinder<Self, rustc_type_ir::TraitRef<Self>> {
1785        match impl_id {
1786            AnyImplId::ImplId(impl_id) => {
1787                let db = self.db();
1788                db.impl_trait(impl_id)
1789                    // ImplIds for impls where the trait ref can't be resolved should never reach trait solving
1790                    .expect("invalid impl passed to trait solver")
1791            }
1792            AnyImplId::BuiltinDeriveImplId(impl_id) => {
1793                crate::builtin_derive::impl_trait(self, impl_id)
1794            }
1795        }
1796    }
1797
1798    fn impl_polarity(self, impl_id: Self::ImplId) -> rustc_type_ir::ImplPolarity {
1799        let AnyImplId::ImplId(impl_id) = impl_id else {
1800            return ImplPolarity::Positive;
1801        };
1802        let impl_data = ImplSignature::of(self.db(), impl_id);
1803        if impl_data.flags.contains(ImplFlags::NEGATIVE) {
1804            ImplPolarity::Negative
1805        } else {
1806            ImplPolarity::Positive
1807        }
1808    }
1809
1810    fn trait_is_auto(self, trait_: Self::TraitId) -> bool {
1811        let trait_data = TraitSignature::of(self.db(), trait_.0);
1812        trait_data.flags.contains(TraitFlags::AUTO)
1813    }
1814
1815    fn trait_is_alias(self, trait_: Self::TraitId) -> bool {
1816        let trait_data = TraitSignature::of(self.db(), trait_.0);
1817        trait_data.flags.contains(TraitFlags::ALIAS)
1818    }
1819
1820    fn trait_is_dyn_compatible(self, trait_: Self::TraitId) -> bool {
1821        crate::dyn_compatibility::dyn_compatibility(self.db(), trait_.0).is_none()
1822    }
1823
1824    fn trait_is_fundamental(self, trait_: Self::TraitId) -> bool {
1825        let trait_data = TraitSignature::of(self.db(), trait_.0);
1826        trait_data.flags.contains(TraitFlags::FUNDAMENTAL)
1827    }
1828
1829    fn is_impl_trait_in_trait(self, _def_id: Self::DefId) -> bool {
1830        // FIXME(next-solver)
1831        false
1832    }
1833
1834    fn delay_bug(self, _msg: impl ToString) -> Self::ErrorGuaranteed {
1835        ErrorGuaranteed
1836    }
1837
1838    fn is_general_coroutine(self, def_id: Self::CoroutineId) -> bool {
1839        matches!(def_id.0.loc(self.db).kind, HirClosureKind::OldCoroutine(_))
1840    }
1841
1842    fn coroutine_is_async(self, def_id: Self::CoroutineId) -> bool {
1843        matches!(
1844            def_id.0.loc(self.db).kind,
1845            HirClosureKind::Coroutine { kind: HirCoroutineKind::Async, .. }
1846        )
1847    }
1848
1849    fn coroutine_is_gen(self, def_id: Self::CoroutineId) -> bool {
1850        matches!(
1851            def_id.0.loc(self.db).kind,
1852            HirClosureKind::Coroutine { kind: HirCoroutineKind::Gen, .. }
1853        )
1854    }
1855
1856    fn coroutine_is_async_gen(self, def_id: Self::CoroutineId) -> bool {
1857        matches!(
1858            def_id.0.loc(self.db).kind,
1859            HirClosureKind::Coroutine { kind: HirCoroutineKind::AsyncGen, .. }
1860        )
1861    }
1862
1863    fn unsizing_params_for_adt(self, id: Self::AdtId) -> Self::UnsizingParams {
1864        let def = AdtDef::new(id.0, self);
1865        let num_params = self.generics_of(id.into()).count();
1866
1867        let maybe_unsizing_param_idx = |arg: GenericArg<'db>| match arg.kind() {
1868            GenericArgKind::Type(ty) => match ty.kind() {
1869                rustc_type_ir::TyKind::Param(p) => Some(p.index),
1870                _ => None,
1871            },
1872            GenericArgKind::Lifetime(_) => None,
1873            GenericArgKind::Const(ct) => match ct.kind() {
1874                rustc_type_ir::ConstKind::Param(p) => Some(p.index),
1875                _ => None,
1876            },
1877        };
1878
1879        // The last field of the structure has to exist and contain type/const parameters.
1880        let variant = match def.def_id() {
1881            AdtId::StructId(id) => VariantId::from(id),
1882            AdtId::UnionId(id) => id.into(),
1883            AdtId::EnumId(_) => panic!("expected a struct or a union"),
1884        };
1885        let fields = variant.fields(self.db());
1886        let mut prefix_fields = fields.fields().iter();
1887        let Some(tail_field) = prefix_fields.next_back() else {
1888            return UnsizingParams(DenseBitSet::new_empty(num_params));
1889        };
1890
1891        let field_types = self.db().field_types(variant);
1892        let mut unsizing_params = DenseBitSet::new_empty(num_params);
1893        let ty = field_types[tail_field.0].ty();
1894        for arg in ty.instantiate_identity().skip_norm_wip().walk() {
1895            if let Some(i) = maybe_unsizing_param_idx(arg) {
1896                unsizing_params.insert(i);
1897            }
1898        }
1899
1900        // Ensure none of the other fields mention the parameters used
1901        // in unsizing.
1902        for field in prefix_fields {
1903            for arg in field_types[field.0].ty().instantiate_identity().skip_norm_wip().walk() {
1904                if let Some(i) = maybe_unsizing_param_idx(arg) {
1905                    unsizing_params.remove(i);
1906                }
1907            }
1908        }
1909
1910        UnsizingParams(unsizing_params)
1911    }
1912
1913    fn anonymize_bound_vars<T: rustc_type_ir::TypeFoldable<Self>>(
1914        self,
1915        value: rustc_type_ir::Binder<Self, T>,
1916    ) -> rustc_type_ir::Binder<Self, T> {
1917        struct Anonymize<'a, 'db> {
1918            interner: DbInterner<'db>,
1919            map: &'a mut FxIndexMap<BoundVar, BoundVariableKind<'db>>,
1920        }
1921        impl<'db> BoundVarReplacerDelegate<'db> for Anonymize<'_, 'db> {
1922            fn replace_region(&mut self, br: BoundRegion<'db>) -> Region<'db> {
1923                let entry = self.map.entry(br.var);
1924                let index = entry.index();
1925                let var = BoundVar::from_usize(index);
1926                let kind = (*entry
1927                    .or_insert_with(|| BoundVariableKind::Region(BoundRegionKind::Anon)))
1928                .expect_region();
1929                let br = BoundRegion { var, kind };
1930                Region::new_bound(self.interner, DebruijnIndex::ZERO, br)
1931            }
1932            fn replace_ty(&mut self, bt: BoundTy<'db>) -> Ty<'db> {
1933                let entry = self.map.entry(bt.var);
1934                let index = entry.index();
1935                let var = BoundVar::from_usize(index);
1936                let kind = (*entry.or_insert_with(|| BoundVariableKind::Ty(BoundTyKind::Anon)))
1937                    .expect_ty();
1938                Ty::new_bound(self.interner, DebruijnIndex::ZERO, BoundTy { var, kind })
1939            }
1940            fn replace_const(&mut self, bv: BoundConst<'db>) -> Const<'db> {
1941                let entry = self.map.entry(bv.var);
1942                let index = entry.index();
1943                let var = BoundVar::from_usize(index);
1944                let () = (*entry.or_insert_with(|| BoundVariableKind::Const)).expect_const();
1945                Const::new_bound(self.interner, DebruijnIndex::ZERO, BoundConst::new(var))
1946            }
1947        }
1948
1949        let mut map = Default::default();
1950        let delegate = Anonymize { interner: self, map: &mut map };
1951        let inner = self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate);
1952        let bound_vars = BoundVarKinds::new_from_iter(map.into_values());
1953        Binder::bind_with_vars(inner, bound_vars)
1954    }
1955
1956    fn opaque_types_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
1957        let Ok(def_id) = InferBodyId::try_from(def_id) else {
1958            return SolverDefIds::default();
1959        };
1960        let mut result = Vec::new();
1961        crate::opaques::opaque_types_defined_by(self.db, def_id, &mut result);
1962        SolverDefIds::new_from_slice(&result)
1963    }
1964
1965    fn opaque_types_and_coroutines_defined_by(self, def_id: Self::LocalDefId) -> Self::LocalDefIds {
1966        let db = self.db;
1967
1968        let Ok(def_id) = InferBodyId::try_from(def_id) else {
1969            return SolverDefIds::default();
1970        };
1971        let mut result = Vec::new();
1972
1973        crate::opaques::opaque_types_defined_by(db, def_id, &mut result);
1974
1975        // Collect coroutines.
1976        let (store, root_expr) = def_id.store_and_root_expr(db);
1977        // We can't just visit all exprs, since this may end up in unrelated anon consts.
1978        CoroutinesVisitor { db: self.db, owner: def_id, store, coroutines: &mut result }
1979            .on_expr(root_expr);
1980
1981        return SolverDefIds::new_from_slice(&result);
1982
1983        struct CoroutinesVisitor<'a, 'db> {
1984            db: &'db dyn HirDatabase,
1985            owner: InferBodyId<'db>,
1986            store: &'db ExpressionStore,
1987            coroutines: &'a mut Vec<SolverDefId<'db>>,
1988        }
1989
1990        impl<'db> StoreVisitor for CoroutinesVisitor<'_, 'db> {
1991            fn on_expr(&mut self, expr: ExprId) {
1992                if let hir_def::hir::Expr::Closure {
1993                    closure_kind:
1994                        kind @ (hir_def::hir::ClosureKind::Coroutine { .. }
1995                        | hir_def::hir::ClosureKind::OldCoroutine(_)),
1996                    ..
1997                } = self.store[expr]
1998                {
1999                    let coroutine = InternedCoroutineId::new(
2000                        self.db,
2001                        InternedClosure { owner: self.owner, expr, kind },
2002                    );
2003                    self.coroutines.push(coroutine.into());
2004                }
2005
2006                self.store.visit_expr_children(expr, self);
2007            }
2008            fn on_pat(&mut self, pat: PatId) {
2009                self.store.visit_pat_children(pat, self);
2010            }
2011            // Do not visit anon consts, they're separate bodies.
2012            fn on_anon_const_expr(&mut self, _expr: ExprId) {}
2013        }
2014    }
2015
2016    fn alias_has_const_conditions(self, _def_id: Self::DefId) -> bool {
2017        // FIXME(next-solver)
2018        false
2019    }
2020
2021    fn explicit_implied_const_bounds(
2022        self,
2023        _def_id: Self::DefId,
2024    ) -> EarlyBinder<
2025        Self,
2026        impl IntoIterator<Item = rustc_type_ir::Binder<Self, rustc_type_ir::TraitRef<Self>>>,
2027    > {
2028        // FIXME(next-solver)
2029        EarlyBinder::bind([])
2030    }
2031
2032    fn fn_is_const(self, id: Self::FunctionId) -> bool {
2033        let id = match id.0 {
2034            CallableDefId::FunctionId(id) => id,
2035            _ => return false,
2036        };
2037        FunctionSignature::of(self.db(), id).flags.contains(FnFlags::CONST)
2038    }
2039
2040    fn impl_is_const(self, _def_id: Self::ImplId) -> bool {
2041        false
2042    }
2043
2044    fn opt_alias_variances(
2045        self,
2046        _kind: impl Into<AliasTermKind<'db>>,
2047    ) -> Option<Self::VariancesOf> {
2048        None
2049    }
2050
2051    fn type_of_opaque_hir_typeck(
2052        self,
2053        opaque: Self::LocalOpaqueTyId,
2054    ) -> EarlyBinder<Self, Self::Ty> {
2055        let impl_trait_id = opaque.0.loc(self.db);
2056        // The entry is missing when this call cycles back into the still-running inference
2057        // of the defining body, as the cycle fallback is an empty result.
2058        let hidden_type = match impl_trait_id {
2059            crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
2060                crate::opaques::rpit_hidden_types(self.db, func).get(idx)
2061            }
2062            crate::ImplTraitId::TypeAliasImplTrait(type_alias, idx) => {
2063                crate::opaques::tait_hidden_types(self.db, type_alias).get(idx)
2064            }
2065        };
2066        match hidden_type {
2067            Some(hidden_type) => hidden_type.get(),
2068            None => EarlyBinder::bind(Ty::new_error(self, ErrorGuaranteed)),
2069        }
2070    }
2071
2072    fn coroutine_hidden_types(
2073        self,
2074        _def_id: Self::CoroutineId,
2075    ) -> EarlyBinder<Self, Binder<'db, CoroutineWitnessTypes<Self>>> {
2076        // FIXME: Actually implement this.
2077        EarlyBinder::bind(Binder::dummy(CoroutineWitnessTypes {
2078            types: Tys::default(),
2079            assumptions: RegionAssumptions::default(),
2080        }))
2081    }
2082
2083    fn is_default_trait(self, def_id: Self::TraitId) -> bool {
2084        self.as_trait_lang_item(def_id).map_or(false, |l| matches!(l, SolverTraitLangItem::Sized))
2085    }
2086
2087    fn trait_is_coinductive(self, trait_: Self::TraitId) -> bool {
2088        TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::COINDUCTIVE)
2089    }
2090
2091    fn trait_is_unsafe(self, trait_: Self::TraitId) -> bool {
2092        TraitSignature::of(self.db(), trait_.0).flags.contains(TraitFlags::UNSAFE)
2093    }
2094
2095    fn impl_self_is_guaranteed_unsized(self, _def_id: Self::ImplId) -> bool {
2096        false
2097    }
2098
2099    fn impl_specializes(
2100        self,
2101        specializing_impl_def_id: Self::ImplId,
2102        parent_impl_def_id: Self::ImplId,
2103    ) -> bool {
2104        let (AnyImplId::ImplId(specializing_impl_def_id), AnyImplId::ImplId(parent_impl_def_id)) =
2105            (specializing_impl_def_id, parent_impl_def_id)
2106        else {
2107            // No builtin derive allow specialization currently.
2108            return false;
2109        };
2110        crate::specialization::specializes(self.db, specializing_impl_def_id, parent_impl_def_id)
2111    }
2112
2113    fn next_trait_solver_globally(self) -> bool {
2114        true
2115    }
2116
2117    type Probe = rustc_type_ir::solve::inspect::Probe<DbInterner<'db>>;
2118    fn mk_probe(self, probe: rustc_type_ir::solve::inspect::Probe<Self>) -> Self::Probe {
2119        probe
2120    }
2121    fn evaluate_root_goal_for_proof_tree_raw(
2122        self,
2123        canonical_goal: rustc_type_ir::solve::CanonicalInput<Self>,
2124    ) -> (rustc_type_ir::solve::QueryResult<Self>, Self::Probe) {
2125        rustc_next_trait_solver::solve::evaluate_root_goal_for_proof_tree_raw_provider::<
2126            SolverContext<'db>,
2127            Self,
2128        >(self, canonical_goal)
2129    }
2130
2131    fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool {
2132        matches!(
2133            self.as_trait_lang_item(def_id),
2134            Some(SolverTraitLangItem::Sized | SolverTraitLangItem::MetaSized)
2135        )
2136    }
2137
2138    fn const_of_item(self, def_id: Self::DefId) -> rustc_type_ir::EarlyBinder<Self, Self::Const> {
2139        let id = match def_id {
2140            SolverDefId::StaticId(id) => id.into(),
2141            SolverDefId::ConstId(id) => id.into(),
2142            _ => unreachable!(),
2143        };
2144        EarlyBinder::bind(Const::new_unevaluated(
2145            self,
2146            UnevaluatedConst { def: GeneralConstIdWrapper(id), args: GenericArgs::empty() },
2147        ))
2148    }
2149
2150    fn anon_const_kind(self, _def_id: Self::DefId) -> rustc_type_ir::AnonConstKind {
2151        // FIXME
2152        rustc_type_ir::AnonConstKind::GCE
2153    }
2154
2155    fn alias_ty_kind_from_def_id(self, def_id: Self::DefId) -> AliasTyKind<'db> {
2156        match def_id {
2157            SolverDefId::TypeAliasId(type_alias) => match type_alias.loc(self.db).container {
2158                ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
2159                    AliasTyKind::Free { def_id: type_alias.into() }
2160                }
2161                ItemContainerId::ImplId(_) => AliasTyKind::Inherent { def_id: type_alias.into() },
2162                ItemContainerId::TraitId(_) => {
2163                    AliasTyKind::Projection { def_id: type_alias.into() }
2164                }
2165            },
2166            SolverDefId::InternedOpaqueTyId(def_id) => {
2167                AliasTyKind::Opaque { def_id: def_id.into() }
2168            }
2169            _ => unreachable!(),
2170        }
2171    }
2172
2173    fn closure_is_const(self, _def_id: Self::ClosureId) -> bool {
2174        // FIXME
2175        false
2176    }
2177
2178    fn item_name(self, _item_index: Self::DefId) -> Self::Symbol {
2179        Symbol
2180    }
2181}
2182
2183fn is_ty_self(ty: Ty<'_>) -> bool {
2184    match ty.kind() {
2185        TyKind::Param(param) => param.index == 0,
2186        _ => false,
2187    }
2188}
2189fn is_clause_at_ty(p: &Clause<'_>, filter: impl FnOnce(Ty<'_>) -> bool) -> bool {
2190    match p.kind().skip_binder() {
2191        // rustc has the following assertion:
2192        // https://github.com/rust-lang/rust/blob/52618eb338609df44978b0ca4451ab7941fd1c7a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs#L525-L608
2193        ClauseKind::Trait(it) => filter(it.self_ty()),
2194        ClauseKind::TypeOutlives(it) => filter(it.0),
2195        ClauseKind::Projection(it) => filter(it.self_ty()),
2196        ClauseKind::HostEffect(it) => filter(it.self_ty()),
2197        _ => false,
2198    }
2199}
2200
2201impl<'db> DbInterner<'db> {
2202    pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
2203    where
2204        T: rustc_type_ir::TypeFoldable<Self>,
2205    {
2206        let shift_bv = |bv: BoundVar| BoundVar::from_usize(bv.as_usize() + bound_vars);
2207        self.replace_escaping_bound_vars_uncached(
2208            value,
2209            FnMutDelegate {
2210                regions: &mut |r: BoundRegion<'db>| {
2211                    Region::new_bound(
2212                        self,
2213                        DebruijnIndex::ZERO,
2214                        BoundRegion { var: shift_bv(r.var), kind: r.kind },
2215                    )
2216                },
2217                types: &mut |t: BoundTy<'db>| {
2218                    Ty::new_bound(
2219                        self,
2220                        DebruijnIndex::ZERO,
2221                        BoundTy { var: shift_bv(t.var), kind: t.kind },
2222                    )
2223                },
2224                consts: &mut |c| {
2225                    Const::new_bound(self, DebruijnIndex::ZERO, BoundConst::new(shift_bv(c.var)))
2226                },
2227            },
2228        )
2229    }
2230
2231    pub fn replace_escaping_bound_vars_uncached<T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
2232        self,
2233        value: T,
2234        delegate: impl BoundVarReplacerDelegate<'db>,
2235    ) -> T {
2236        if !value.has_escaping_bound_vars() {
2237            value
2238        } else {
2239            let mut replacer = BoundVarReplacer::new(self, delegate);
2240            value.fold_with(&mut replacer)
2241        }
2242    }
2243
2244    pub fn replace_bound_vars_uncached<T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
2245        self,
2246        value: Binder<'db, T>,
2247        delegate: impl BoundVarReplacerDelegate<'db>,
2248    ) -> T {
2249        self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate)
2250    }
2251
2252    // FIXME: add splat support when the experiment is complete
2253    pub fn mk_fn_sig<I>(
2254        self,
2255        inputs: I,
2256        output: Ty<'db>,
2257        c_variadic: bool,
2258        safety: Safety,
2259        abi: ExternAbi,
2260    ) -> FnSig<'db>
2261    where
2262        I: IntoIterator<Item = Ty<'db>>,
2263    {
2264        FnSig {
2265            inputs_and_output: Tys::new_from_iter(
2266                inputs.into_iter().chain(std::iter::once(output)),
2267            ),
2268            fn_sig_kind: FnSigKind::new(abi, safety, c_variadic),
2269        }
2270    }
2271
2272    /// `mk_fn_sig`, but with a safe Rust ABI, and no C-variadic argument.
2273    pub fn mk_fn_sig_safe_rust_abi<I>(self, inputs: I, output: Ty<'db>) -> FnSig<'db>
2274    where
2275        I: IntoIterator<Item = Ty<'db>>,
2276    {
2277        self.mk_fn_sig(inputs, output, false, Safety::Safe, ExternAbi::Rust)
2278    }
2279}
2280
2281fn predicates_of<'db>(
2282    db: &'db dyn HirDatabase,
2283    def_id: SolverDefId<'db>,
2284) -> &'db GenericPredicates {
2285    match def_id {
2286        SolverDefId::BuiltinDeriveImplId(impl_) => crate::builtin_derive::predicates(db, impl_),
2287        SolverDefId::AnonConstId(anon_const) => {
2288            let loc = anon_const.loc(db);
2289            if loc.allow_using_generic_params {
2290                GenericPredicates::query(db, loc.owner.generic_def(db))
2291            } else {
2292                GenericPredicates::empty()
2293            }
2294        }
2295        _ => GenericPredicates::query(db, def_id.try_into().unwrap()),
2296    }
2297}
2298
2299macro_rules! TrivialTypeTraversalImpls {
2300    ($($ty:ty,)+) => {
2301        $(
2302            impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $ty {
2303                fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
2304                    self,
2305                    _: &mut F,
2306                ) -> ::std::result::Result<Self, F::Error> {
2307                    Ok(self)
2308                }
2309
2310                #[inline]
2311                fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
2312                    self,
2313                    _: &mut F,
2314                ) -> Self {
2315                    self
2316                }
2317            }
2318
2319            impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for $ty {
2320                #[inline]
2321                fn visit_with<F: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
2322                    &self,
2323                    _: &mut F)
2324                    -> F::Result
2325                {
2326                    <F::Result as rustc_ast_ir::visit::VisitorResult>::output()
2327                }
2328            }
2329
2330            impl<V> rustc_type_ir::GenericTypeVisitable<V> for $ty {
2331                #[inline]
2332                fn generic_visit_with(&self, _visitor: &mut V) {}
2333            }
2334        )+
2335    };
2336}
2337
2338TrivialTypeTraversalImpls! {
2339    SolverDefId<'_>,
2340    TraitIdWrapper,
2341    TypeAliasIdWrapper,
2342    CallableIdWrapper,
2343    ClosureIdWrapper<'_>,
2344    CoroutineIdWrapper<'_>,
2345    CoroutineClosureIdWrapper<'_>,
2346    AdtIdWrapper,
2347    TraitAssocTyId,
2348    TraitAssocConstId,
2349    TraitAssocTermId,
2350    ImplOrTraitAssocTyId,
2351    ImplOrTraitAssocConstId,
2352    ImplOrTraitAssocTermId,
2353    FreeTyAliasId,
2354    FreeConstAliasId,
2355    FreeTermAliasId,
2356    InherentAssocTyId,
2357    InherentAssocConstId,
2358    InherentAssocTermId,
2359    OpaqueTyIdWrapper<'_>,
2360    AnyImplId,
2361    GeneralConstIdWrapper<'_>,
2362    Safety,
2363    Span,
2364    ParamConst,
2365    ParamTy,
2366    EarlyParamRegion,
2367    AdtDef,
2368    ScalarInt,
2369}
2370
2371mod tls_db {
2372    use std::{cell::Cell, ptr::NonNull};
2373
2374    use crate::db::HirDatabase;
2375
2376    struct Attached {
2377        database: Cell<Option<NonNull<dyn HirDatabase>>>,
2378    }
2379
2380    impl Attached {
2381        #[inline]
2382        fn attach<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2383            struct DbGuard<'s> {
2384                state: Option<&'s Attached>,
2385            }
2386
2387            impl<'s> DbGuard<'s> {
2388                #[inline]
2389                fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
2390                    match attached.database.get() {
2391                        Some(current_db) => {
2392                            let new_db = NonNull::from(db);
2393                            if !std::ptr::addr_eq(current_db.as_ptr(), new_db.as_ptr()) {
2394                                panic!(
2395                                    "Cannot change attached database. This is likely a bug.\n\
2396                                    If this is not a bug, you can use `attach_db_allow_change()`."
2397                                );
2398                            }
2399                            Self { state: None }
2400                        }
2401                        None => {
2402                            // Otherwise, set the database.
2403                            attached.database.set(Some(NonNull::from(db)));
2404                            Self { state: Some(attached) }
2405                        }
2406                    }
2407                }
2408            }
2409
2410            impl Drop for DbGuard<'_> {
2411                #[inline]
2412                fn drop(&mut self) {
2413                    // Reset database to null if we did anything in `DbGuard::new`.
2414                    if let Some(attached) = self.state {
2415                        attached.database.set(None);
2416                    }
2417                }
2418            }
2419
2420            let _guard = DbGuard::new(self, db);
2421            super::tls_cache::reinit_cache(db);
2422            op()
2423        }
2424
2425        #[inline]
2426        fn attach_allow_change<R>(&self, db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2427            struct DbGuard<'s> {
2428                state: &'s Attached,
2429                prev: Option<NonNull<dyn HirDatabase>>,
2430            }
2431
2432            impl<'s> DbGuard<'s> {
2433                #[inline]
2434                fn new(attached: &'s Attached, db: &dyn HirDatabase) -> Self {
2435                    let prev = attached.database.replace(Some(NonNull::from(db)));
2436                    Self { state: attached, prev }
2437                }
2438            }
2439
2440            impl Drop for DbGuard<'_> {
2441                #[inline]
2442                fn drop(&mut self) {
2443                    self.state.database.set(self.prev);
2444                    if let Some(prev) = self.prev {
2445                        super::tls_cache::reinit_cache(unsafe { prev.as_ref() });
2446                    }
2447                }
2448            }
2449
2450            let _guard = DbGuard::new(self, db);
2451            super::tls_cache::reinit_cache(db);
2452            op()
2453        }
2454
2455        #[inline]
2456        fn with<R>(&self, op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
2457            let db = self.database.get().expect("Tried to use attached db, but no db is attached");
2458
2459            // SAFETY: The db is attached, so it must be valid.
2460            op(unsafe { db.as_ref() })
2461        }
2462    }
2463
2464    thread_local! {
2465        static GLOBAL_DB: Attached = const { Attached { database: Cell::new(None) } };
2466    }
2467
2468    #[inline]
2469    pub fn attach_db<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2470        GLOBAL_DB.with(|global_db| global_db.attach(db, op))
2471    }
2472
2473    #[inline]
2474    pub fn attach_db_allow_change<R>(db: &dyn HirDatabase, op: impl FnOnce() -> R) -> R {
2475        GLOBAL_DB.with(|global_db| global_db.attach_allow_change(db, op))
2476    }
2477
2478    #[inline]
2479    pub fn with_attached_db<R>(op: impl FnOnce(&dyn HirDatabase) -> R) -> R {
2480        GLOBAL_DB.with(
2481            #[inline]
2482            |a| a.with(op),
2483        )
2484    }
2485}
2486
2487mod tls_cache {
2488    use crate::db::HirDatabase;
2489
2490    use super::DbInterner;
2491    use base_db::Nonce;
2492    use rustc_type_ir::search_graph::GlobalCache;
2493    use salsa::Revision;
2494    use std::cell::RefCell;
2495
2496    struct Cache {
2497        cache: GlobalCache<DbInterner<'static>>,
2498        revision: Revision,
2499        db_nonce: Nonce,
2500    }
2501
2502    impl Cache {
2503        const fn default() -> Cache {
2504            Cache {
2505                cache: GlobalCache::new(),
2506                revision: Revision::max(),
2507                db_nonce: Nonce::invalid(),
2508            }
2509        }
2510    }
2511
2512    thread_local! {
2513        static GLOBAL_CACHE: RefCell<Cache> = const { RefCell::new(Cache::default()) };
2514    }
2515
2516    pub(super) fn reinit_cache(db: &dyn HirDatabase) {
2517        GLOBAL_CACHE.with_borrow_mut(|handle| {
2518            let (db_nonce, revision) = db.nonce_and_revision();
2519            if handle.revision != revision || db_nonce != handle.db_nonce {
2520                *handle = Cache { cache: GlobalCache::default(), revision, db_nonce };
2521            }
2522        })
2523    }
2524
2525    #[inline]
2526    pub(super) fn borrow_assume_valid<'db, T>(
2527        db: &'db dyn HirDatabase,
2528        f: impl FnOnce(&mut GlobalCache<DbInterner<'db>>) -> T,
2529    ) -> T {
2530        if cfg!(debug_assertions) {
2531            let get_state =
2532                || GLOBAL_CACHE.with_borrow(|handle| (handle.db_nonce, handle.revision));
2533            let old_state = get_state();
2534            reinit_cache(db);
2535            let new_state = get_state();
2536            assert_eq!(old_state, new_state, "you assumed the cache is valid!");
2537        }
2538
2539        GLOBAL_CACHE.with_borrow_mut(|handle| {
2540            // SAFETY: No idea
2541            f(unsafe {
2542                std::mem::transmute::<
2543                    &mut GlobalCache<DbInterner<'static>>,
2544                    &mut GlobalCache<DbInterner<'db>>,
2545                >(&mut handle.cache)
2546            })
2547        })
2548    }
2549
2550    /// Clears the thread-local trait solver cache.
2551    ///
2552    /// Should be called before getting memory usage estimations, as the solver cache
2553    /// is per-revision and usually should be excluded from estimations.
2554    pub fn clear_tls_solver_cache() {
2555        GLOBAL_CACHE.with_borrow_mut(|handle| *handle = Cache::default());
2556    }
2557}
2558
2559impl WorldExposer for intern::GarbageCollector {
2560    fn on_interned<T: intern::Internable>(
2561        &mut self,
2562        interned: InternedRef<'_, T>,
2563    ) -> ControlFlow<()> {
2564        self.mark_interned_alive(interned)
2565    }
2566
2567    fn on_interned_slice<T: intern::SliceInternable>(
2568        &mut self,
2569        interned: InternedSliceRef<'_, T>,
2570    ) -> ControlFlow<()> {
2571        self.mark_interned_slice_alive(interned)
2572    }
2573}
2574
2575/// # Safety
2576///
2577/// This cannot be called if there are some not-yet-recorded type values. Generally, if you have a mutable
2578/// reference to the database, and there are no other database - then you can call this safely, but you
2579/// also need to make sure to maintain the mutable reference while this is running.
2580pub unsafe fn collect_ty_garbage() {
2581    let mut gc = intern::GarbageCollector::default();
2582
2583    gc.add_storage::<super::consts::ConstInterned>();
2584    gc.add_storage::<super::consts::ValTreeInterned>();
2585    gc.add_storage::<super::allocation::AllocationInterned>();
2586    gc.add_storage::<PatternInterned>();
2587    gc.add_storage::<super::opaques::ExternalConstraintsInterned>();
2588    gc.add_storage::<super::predicate::PredicateInterned>();
2589    gc.add_storage::<super::region::RegionInterned>();
2590    gc.add_storage::<super::ty::TyInterned>();
2591
2592    gc.add_slice_storage::<super::consts::ConstsStorage>();
2593    gc.add_slice_storage::<super::predicate::ClausesStorage>();
2594    gc.add_slice_storage::<super::generic_arg::GenericArgsStorage>();
2595    gc.add_slice_storage::<BoundVarKindsStorage>();
2596    gc.add_slice_storage::<VariancesOfStorage>();
2597    gc.add_slice_storage::<CanonicalVarsStorage>();
2598    gc.add_slice_storage::<PatListStorage>();
2599    gc.add_slice_storage::<super::opaques::PredefinedOpaquesStorage>();
2600    gc.add_slice_storage::<super::opaques::SolverDefIdsStorage>();
2601    gc.add_slice_storage::<super::predicate::BoundExistentialPredicatesStorage>();
2602    gc.add_slice_storage::<super::region::RegionAssumptionsStorage>();
2603    gc.add_slice_storage::<super::ty::TysStorage>();
2604    gc.add_slice_storage::<crate::mir::ProjectionStorage>();
2605
2606    // SAFETY:
2607    //  - By our precondition, there are no unrecorded types.
2608    //  - We implement `GcInternedVisit` and `GcInternedSliceVisit` correctly for all types.
2609    //  - We added all storages (FIXME: it's too easy to forget to add a new storage here).
2610    unsafe { gc.collect() };
2611}
2612
2613macro_rules! impl_gc_visit {
2614    ( $($ty:ty),* $(,)? ) => {
2615        $(
2616            impl ::intern::GcInternedVisit for $ty {
2617                #[inline]
2618                fn visit_with(&self, gc: &mut ::intern::GarbageCollector) {
2619                    self.generic_visit_with(gc);
2620                }
2621            }
2622        )*
2623    };
2624}
2625
2626impl_gc_visit!(
2627    super::consts::ConstInterned,
2628    super::consts::ValTreeInterned,
2629    super::allocation::AllocationInterned,
2630    PatternInterned,
2631    super::opaques::ExternalConstraintsInterned,
2632    super::predicate::PredicateInterned,
2633    super::region::RegionInterned,
2634    super::ty::TyInterned,
2635    super::predicate::ClausesCachedTypeInfo,
2636);
2637
2638macro_rules! impl_gc_visit_slice {
2639    ( $($ty:ty),* $(,)? ) => {
2640        $(
2641            impl ::intern::GcInternedSliceVisit for $ty {
2642                #[inline]
2643                fn visit_header(header: &<Self as ::intern::SliceInternable>::Header, gc: &mut ::intern::GarbageCollector) {
2644                    header.generic_visit_with(gc);
2645                }
2646
2647                #[inline]
2648                fn visit_slice(slice: &[<Self as ::intern::SliceInternable>::SliceType], gc: &mut ::intern::GarbageCollector) {
2649                    slice.generic_visit_with(gc);
2650                }
2651            }
2652        )*
2653    };
2654}
2655
2656impl_gc_visit_slice!(
2657    super::predicate::ClausesStorage,
2658    super::generic_arg::GenericArgsStorage,
2659    BoundVarKindsStorage,
2660    VariancesOfStorage,
2661    CanonicalVarsStorage,
2662    PatListStorage,
2663    super::opaques::PredefinedOpaquesStorage,
2664    super::opaques::SolverDefIdsStorage,
2665    super::predicate::BoundExistentialPredicatesStorage,
2666    super::region::RegionAssumptionsStorage,
2667    super::ty::TysStorage,
2668    super::consts::ConstsStorage,
2669    crate::mir::ProjectionStorage,
2670);