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