hir_ty/next_solver/
interner.rs

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