hir_ty/next_solver/
ty.rs

1//! Things related to tys in the next-trait-solver.
2
3use hir_def::{GenericDefId, TypeOrConstParamId, TypeParamId};
4use intern::{Interned, Symbol, sym};
5use rustc_abi::{Float, Integer, Size};
6use rustc_ast_ir::{Mutability, try_visit, visit::VisitorResult};
7use rustc_type_ir::{
8    BoundVar, ClosureKind, FlagComputation, Flags, FloatTy, FloatVid, InferTy, IntTy, IntVid,
9    TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, UintTy,
10    WithCachedTypeInfo,
11    inherent::{
12        AdtDef, BoundVarLike, GenericArgs as _, IntoKind, ParamLike, PlaceholderLike, SliceLike,
13        Ty as _,
14    },
15    relate::Relate,
16    solve::SizedTraitKind,
17    walk::TypeWalker,
18};
19use salsa::plumbing::{AsId, FromId};
20use smallvec::SmallVec;
21
22use crate::{
23    db::HirDatabase,
24    interner::InternedWrapperNoDebug,
25    next_solver::util::{CoroutineArgsExt, IntegerTypeExt},
26};
27
28use super::{
29    BoundVarKind, DbInterner, GenericArgs, Placeholder, SolverDefId, interned_vec_db,
30    util::{FloatExt, IntegerExt},
31};
32
33pub type TyKind<'db> = rustc_type_ir::TyKind<DbInterner<'db>>;
34pub type FnHeader<'db> = rustc_type_ir::FnHeader<DbInterner<'db>>;
35
36#[salsa::interned(constructor = new_)]
37pub struct Ty<'db> {
38    #[returns(ref)]
39    kind_: InternedWrapperNoDebug<WithCachedTypeInfo<TyKind<'db>>>,
40}
41
42const _: () = {
43    const fn is_copy<T: Copy>() {}
44    is_copy::<Ty<'static>>();
45};
46
47impl<'db> Ty<'db> {
48    pub fn new(interner: DbInterner<'db>, kind: TyKind<'db>) -> Self {
49        let flags = FlagComputation::for_kind(&kind);
50        let cached = WithCachedTypeInfo {
51            internee: kind,
52            flags: flags.flags,
53            outer_exclusive_binder: flags.outer_exclusive_binder,
54        };
55        Ty::new_(interner.db(), InternedWrapperNoDebug(cached))
56    }
57
58    pub fn inner(&self) -> &WithCachedTypeInfo<TyKind<'db>> {
59        salsa::with_attached_database(|db| {
60            let inner = &self.kind_(db).0;
61            // SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will
62            // make sure that our returned value is valid for the lifetime `'db`.
63            unsafe { std::mem::transmute(inner) }
64        })
65        .unwrap()
66    }
67
68    pub fn new_param(interner: DbInterner<'db>, id: TypeParamId, index: u32, name: Symbol) -> Self {
69        Ty::new(interner, TyKind::Param(ParamTy { id, index }))
70    }
71
72    pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderTy) -> Self {
73        Ty::new(interner, TyKind::Placeholder(placeholder))
74    }
75
76    pub fn new_infer(interner: DbInterner<'db>, infer: InferTy) -> Self {
77        Ty::new(interner, TyKind::Infer(infer))
78    }
79
80    pub fn new_int_var(interner: DbInterner<'db>, v: IntVid) -> Self {
81        Ty::new_infer(interner, InferTy::IntVar(v))
82    }
83
84    pub fn new_float_var(interner: DbInterner<'db>, v: FloatVid) -> Self {
85        Ty::new_infer(interner, InferTy::FloatVar(v))
86    }
87
88    pub fn new_int(interner: DbInterner<'db>, i: IntTy) -> Self {
89        Ty::new(interner, TyKind::Int(i))
90    }
91
92    pub fn new_uint(interner: DbInterner<'db>, ui: UintTy) -> Self {
93        Ty::new(interner, TyKind::Uint(ui))
94    }
95
96    pub fn new_float(interner: DbInterner<'db>, f: FloatTy) -> Self {
97        Ty::new(interner, TyKind::Float(f))
98    }
99
100    pub fn new_fresh(interner: DbInterner<'db>, n: u32) -> Self {
101        Ty::new_infer(interner, InferTy::FreshTy(n))
102    }
103
104    pub fn new_fresh_int(interner: DbInterner<'db>, n: u32) -> Self {
105        Ty::new_infer(interner, InferTy::FreshIntTy(n))
106    }
107
108    pub fn new_fresh_float(interner: DbInterner<'db>, n: u32) -> Self {
109        Ty::new_infer(interner, InferTy::FreshFloatTy(n))
110    }
111
112    pub fn new_empty_tuple(interner: DbInterner<'db>) -> Self {
113        Ty::new_tup(interner, &[])
114    }
115
116    /// Returns the `Size` for primitive types (bool, uint, int, char, float).
117    pub fn primitive_size(self, interner: DbInterner<'db>) -> Size {
118        match self.kind() {
119            TyKind::Bool => Size::from_bytes(1),
120            TyKind::Char => Size::from_bytes(4),
121            TyKind::Int(ity) => Integer::from_int_ty(&interner, ity).size(),
122            TyKind::Uint(uty) => Integer::from_uint_ty(&interner, uty).size(),
123            TyKind::Float(fty) => Float::from_float_ty(fty).size(),
124            _ => panic!("non primitive type"),
125        }
126    }
127
128    pub fn int_size_and_signed(self, interner: DbInterner<'db>) -> (Size, bool) {
129        match self.kind() {
130            TyKind::Int(ity) => (Integer::from_int_ty(&interner, ity).size(), true),
131            TyKind::Uint(uty) => (Integer::from_uint_ty(&interner, uty).size(), false),
132            _ => panic!("non integer discriminant"),
133        }
134    }
135
136    pub fn walk(self) -> TypeWalker<DbInterner<'db>> {
137        TypeWalker::new(self.into())
138    }
139
140    /// Fast path helper for testing if a type is `Sized` or `MetaSized`.
141    ///
142    /// Returning true means the type is known to implement the sizedness trait. Returning `false`
143    /// means nothing -- could be sized, might not be.
144    ///
145    /// Note that we could never rely on the fact that a type such as `[_]` is trivially `!Sized`
146    /// because we could be in a type environment with a bound such as `[_]: Copy`. A function with
147    /// such a bound obviously never can be called, but that doesn't mean it shouldn't typecheck.
148    /// This is why this method doesn't return `Option<bool>`.
149    #[tracing::instrument(skip(tcx), level = "debug")]
150    pub fn has_trivial_sizedness(self, tcx: DbInterner<'db>, sizedness: SizedTraitKind) -> bool {
151        match self.kind() {
152            TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_))
153            | TyKind::Uint(_)
154            | TyKind::Int(_)
155            | TyKind::Bool
156            | TyKind::Float(_)
157            | TyKind::FnDef(..)
158            | TyKind::FnPtr(..)
159            | TyKind::UnsafeBinder(_)
160            | TyKind::RawPtr(..)
161            | TyKind::Char
162            | TyKind::Ref(..)
163            | TyKind::Coroutine(..)
164            | TyKind::CoroutineWitness(..)
165            | TyKind::Array(..)
166            | TyKind::Pat(..)
167            | TyKind::Closure(..)
168            | TyKind::CoroutineClosure(..)
169            | TyKind::Never
170            | TyKind::Error(_) => true,
171
172            TyKind::Str | TyKind::Slice(_) | TyKind::Dynamic(_, _, _) => match sizedness {
173                SizedTraitKind::Sized => false,
174                SizedTraitKind::MetaSized => true,
175            },
176
177            TyKind::Foreign(..) => match sizedness {
178                SizedTraitKind::Sized | SizedTraitKind::MetaSized => false,
179            },
180
181            TyKind::Tuple(tys) => {
182                tys.last().is_none_or(|ty| ty.has_trivial_sizedness(tcx, sizedness))
183            }
184
185            TyKind::Adt(def, args) => def
186                .sizedness_constraint(tcx, sizedness)
187                .is_none_or(|ty| ty.instantiate(tcx, args).has_trivial_sizedness(tcx, sizedness)),
188
189            TyKind::Alias(..) | TyKind::Param(_) | TyKind::Placeholder(..) | TyKind::Bound(..) => {
190                false
191            }
192
193            TyKind::Infer(InferTy::TyVar(_)) => false,
194
195            TyKind::Infer(
196                InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_),
197            ) => {
198                panic!("`has_trivial_sizedness` applied to unexpected type: {self:?}")
199            }
200        }
201    }
202
203    /// Fast path helper for primitives which are always `Copy` and which
204    /// have a side-effect-free `Clone` impl.
205    ///
206    /// Returning true means the type is known to be pure and `Copy+Clone`.
207    /// Returning `false` means nothing -- could be `Copy`, might not be.
208    ///
209    /// This is mostly useful for optimizations, as these are the types
210    /// on which we can replace cloning with dereferencing.
211    pub fn is_trivially_pure_clone_copy(self) -> bool {
212        match self.kind() {
213            TyKind::Bool | TyKind::Char | TyKind::Never => true,
214
215            // These aren't even `Clone`
216            TyKind::Str | TyKind::Slice(..) | TyKind::Foreign(..) | TyKind::Dynamic(..) => false,
217
218            TyKind::Infer(InferTy::FloatVar(_) | InferTy::IntVar(_))
219            | TyKind::Int(..)
220            | TyKind::Uint(..)
221            | TyKind::Float(..) => true,
222
223            // ZST which can't be named are fine.
224            TyKind::FnDef(..) => true,
225
226            TyKind::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(),
227
228            // A 100-tuple isn't "trivial", so doing this only for reasonable sizes.
229            TyKind::Tuple(field_tys) => {
230                field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy)
231            }
232
233            TyKind::Pat(ty, _) => ty.is_trivially_pure_clone_copy(),
234
235            // Sometimes traits aren't implemented for every ABI or arity,
236            // because we can't be generic over everything yet.
237            TyKind::FnPtr(..) => false,
238
239            // Definitely absolutely not copy.
240            TyKind::Ref(_, _, Mutability::Mut) => false,
241
242            // The standard library has a blanket Copy impl for shared references and raw pointers,
243            // for all unsized types.
244            TyKind::Ref(_, _, Mutability::Not) | TyKind::RawPtr(..) => true,
245
246            TyKind::Coroutine(..) | TyKind::CoroutineWitness(..) => false,
247
248            // Might be, but not "trivial" so just giving the safe answer.
249            TyKind::Adt(..) | TyKind::Closure(..) | TyKind::CoroutineClosure(..) => false,
250
251            TyKind::UnsafeBinder(_) => false,
252
253            // Needs normalization or revealing to determine, so no is the safe answer.
254            TyKind::Alias(..) => false,
255
256            TyKind::Param(..)
257            | TyKind::Placeholder(..)
258            | TyKind::Bound(..)
259            | TyKind::Infer(..)
260            | TyKind::Error(..) => false,
261        }
262    }
263
264    pub fn is_trivially_wf(self, tcx: DbInterner<'db>) -> bool {
265        match self.kind() {
266            TyKind::Bool
267            | TyKind::Char
268            | TyKind::Int(_)
269            | TyKind::Uint(_)
270            | TyKind::Float(_)
271            | TyKind::Str
272            | TyKind::Never
273            | TyKind::Param(_)
274            | TyKind::Placeholder(_)
275            | TyKind::Bound(..) => true,
276
277            TyKind::Slice(ty) => {
278                ty.is_trivially_wf(tcx) && ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized)
279            }
280            TyKind::RawPtr(ty, _) => ty.is_trivially_wf(tcx),
281
282            TyKind::FnPtr(sig_tys, _) => {
283                sig_tys.skip_binder().inputs_and_output.iter().all(|ty| ty.is_trivially_wf(tcx))
284            }
285            TyKind::Ref(_, ty, _) => ty.is_global() && ty.is_trivially_wf(tcx),
286
287            TyKind::Infer(infer) => match infer {
288                InferTy::TyVar(_) => false,
289                InferTy::IntVar(_) | InferTy::FloatVar(_) => true,
290                InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_) => true,
291            },
292
293            TyKind::Adt(_, _)
294            | TyKind::Tuple(_)
295            | TyKind::Array(..)
296            | TyKind::Foreign(_)
297            | TyKind::Pat(_, _)
298            | TyKind::FnDef(..)
299            | TyKind::UnsafeBinder(..)
300            | TyKind::Dynamic(..)
301            | TyKind::Closure(..)
302            | TyKind::CoroutineClosure(..)
303            | TyKind::Coroutine(..)
304            | TyKind::CoroutineWitness(..)
305            | TyKind::Alias(..)
306            | TyKind::Error(_) => false,
307        }
308    }
309}
310
311impl<'db> std::fmt::Debug for Ty<'db> {
312    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
313        self.inner().internee.fmt(f)
314    }
315}
316
317impl<'db> std::fmt::Debug for InternedWrapperNoDebug<WithCachedTypeInfo<TyKind<'db>>> {
318    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
319        self.0.internee.fmt(f)
320    }
321}
322
323impl<'db> IntoKind for Ty<'db> {
324    type Kind = TyKind<'db>;
325
326    fn kind(self) -> Self::Kind {
327        self.inner().internee
328    }
329}
330
331impl<'db> TypeVisitable<DbInterner<'db>> for Ty<'db> {
332    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
333        &self,
334        visitor: &mut V,
335    ) -> V::Result {
336        visitor.visit_ty(*self)
337    }
338}
339
340impl<'db> TypeSuperVisitable<DbInterner<'db>> for Ty<'db> {
341    fn super_visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
342        &self,
343        visitor: &mut V,
344    ) -> V::Result {
345        match (*self).kind() {
346            TyKind::RawPtr(ty, _mutbl) => ty.visit_with(visitor),
347            TyKind::Array(typ, sz) => {
348                try_visit!(typ.visit_with(visitor));
349                sz.visit_with(visitor)
350            }
351            TyKind::Slice(typ) => typ.visit_with(visitor),
352            TyKind::Adt(_, args) => args.visit_with(visitor),
353            TyKind::Dynamic(ref trait_ty, ref reg, _) => {
354                try_visit!(trait_ty.visit_with(visitor));
355                reg.visit_with(visitor)
356            }
357            TyKind::Tuple(ts) => ts.visit_with(visitor),
358            TyKind::FnDef(_, args) => args.visit_with(visitor),
359            TyKind::FnPtr(ref sig_tys, _) => sig_tys.visit_with(visitor),
360            TyKind::UnsafeBinder(f) => f.visit_with(visitor),
361            TyKind::Ref(r, ty, _) => {
362                try_visit!(r.visit_with(visitor));
363                ty.visit_with(visitor)
364            }
365            TyKind::Coroutine(_did, ref args) => args.visit_with(visitor),
366            TyKind::CoroutineWitness(_did, ref args) => args.visit_with(visitor),
367            TyKind::Closure(_did, ref args) => args.visit_with(visitor),
368            TyKind::CoroutineClosure(_did, ref args) => args.visit_with(visitor),
369            TyKind::Alias(_, ref data) => data.visit_with(visitor),
370
371            TyKind::Pat(ty, pat) => {
372                try_visit!(ty.visit_with(visitor));
373                pat.visit_with(visitor)
374            }
375
376            TyKind::Error(guar) => guar.visit_with(visitor),
377
378            TyKind::Bool
379            | TyKind::Char
380            | TyKind::Str
381            | TyKind::Int(_)
382            | TyKind::Uint(_)
383            | TyKind::Float(_)
384            | TyKind::Infer(_)
385            | TyKind::Bound(..)
386            | TyKind::Placeholder(..)
387            | TyKind::Param(..)
388            | TyKind::Never
389            | TyKind::Foreign(..) => V::Result::output(),
390        }
391    }
392}
393
394impl<'db> TypeFoldable<DbInterner<'db>> for Ty<'db> {
395    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
396        self,
397        folder: &mut F,
398    ) -> Result<Self, F::Error> {
399        folder.try_fold_ty(self)
400    }
401    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
402        folder.fold_ty(self)
403    }
404}
405
406impl<'db> TypeSuperFoldable<DbInterner<'db>> for Ty<'db> {
407    fn try_super_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
408        self,
409        folder: &mut F,
410    ) -> Result<Self, F::Error> {
411        let kind = match self.kind() {
412            TyKind::RawPtr(ty, mutbl) => TyKind::RawPtr(ty.try_fold_with(folder)?, mutbl),
413            TyKind::Array(typ, sz) => {
414                TyKind::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?)
415            }
416            TyKind::Slice(typ) => TyKind::Slice(typ.try_fold_with(folder)?),
417            TyKind::Adt(tid, args) => TyKind::Adt(tid, args.try_fold_with(folder)?),
418            TyKind::Dynamic(trait_ty, region, representation) => TyKind::Dynamic(
419                trait_ty.try_fold_with(folder)?,
420                region.try_fold_with(folder)?,
421                representation,
422            ),
423            TyKind::Tuple(ts) => TyKind::Tuple(ts.try_fold_with(folder)?),
424            TyKind::FnDef(def_id, args) => TyKind::FnDef(def_id, args.try_fold_with(folder)?),
425            TyKind::FnPtr(sig_tys, hdr) => TyKind::FnPtr(sig_tys.try_fold_with(folder)?, hdr),
426            TyKind::UnsafeBinder(f) => TyKind::UnsafeBinder(f.try_fold_with(folder)?),
427            TyKind::Ref(r, ty, mutbl) => {
428                TyKind::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl)
429            }
430            TyKind::Coroutine(did, args) => TyKind::Coroutine(did, args.try_fold_with(folder)?),
431            TyKind::CoroutineWitness(did, args) => {
432                TyKind::CoroutineWitness(did, args.try_fold_with(folder)?)
433            }
434            TyKind::Closure(did, args) => TyKind::Closure(did, args.try_fold_with(folder)?),
435            TyKind::CoroutineClosure(did, args) => {
436                TyKind::CoroutineClosure(did, args.try_fold_with(folder)?)
437            }
438            TyKind::Alias(kind, data) => TyKind::Alias(kind, data.try_fold_with(folder)?),
439            TyKind::Pat(ty, pat) => {
440                TyKind::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?)
441            }
442
443            TyKind::Bool
444            | TyKind::Char
445            | TyKind::Str
446            | TyKind::Int(_)
447            | TyKind::Uint(_)
448            | TyKind::Float(_)
449            | TyKind::Error(_)
450            | TyKind::Infer(_)
451            | TyKind::Param(..)
452            | TyKind::Bound(..)
453            | TyKind::Placeholder(..)
454            | TyKind::Never
455            | TyKind::Foreign(..) => return Ok(self),
456        };
457
458        Ok(if self.kind() == kind { self } else { Ty::new(folder.cx(), kind) })
459    }
460    fn super_fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
461        self,
462        folder: &mut F,
463    ) -> Self {
464        let kind = match self.kind() {
465            TyKind::RawPtr(ty, mutbl) => TyKind::RawPtr(ty.fold_with(folder), mutbl),
466            TyKind::Array(typ, sz) => TyKind::Array(typ.fold_with(folder), sz.fold_with(folder)),
467            TyKind::Slice(typ) => TyKind::Slice(typ.fold_with(folder)),
468            TyKind::Adt(tid, args) => TyKind::Adt(tid, args.fold_with(folder)),
469            TyKind::Dynamic(trait_ty, region, representation) => TyKind::Dynamic(
470                trait_ty.fold_with(folder),
471                region.fold_with(folder),
472                representation,
473            ),
474            TyKind::Tuple(ts) => TyKind::Tuple(ts.fold_with(folder)),
475            TyKind::FnDef(def_id, args) => TyKind::FnDef(def_id, args.fold_with(folder)),
476            TyKind::FnPtr(sig_tys, hdr) => TyKind::FnPtr(sig_tys.fold_with(folder), hdr),
477            TyKind::UnsafeBinder(f) => TyKind::UnsafeBinder(f.fold_with(folder)),
478            TyKind::Ref(r, ty, mutbl) => {
479                TyKind::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl)
480            }
481            TyKind::Coroutine(did, args) => TyKind::Coroutine(did, args.fold_with(folder)),
482            TyKind::CoroutineWitness(did, args) => {
483                TyKind::CoroutineWitness(did, args.fold_with(folder))
484            }
485            TyKind::Closure(did, args) => TyKind::Closure(did, args.fold_with(folder)),
486            TyKind::CoroutineClosure(did, args) => {
487                TyKind::CoroutineClosure(did, args.fold_with(folder))
488            }
489            TyKind::Alias(kind, data) => TyKind::Alias(kind, data.fold_with(folder)),
490            TyKind::Pat(ty, pat) => TyKind::Pat(ty.fold_with(folder), pat.fold_with(folder)),
491
492            TyKind::Bool
493            | TyKind::Char
494            | TyKind::Str
495            | TyKind::Int(_)
496            | TyKind::Uint(_)
497            | TyKind::Float(_)
498            | TyKind::Error(_)
499            | TyKind::Infer(_)
500            | TyKind::Param(..)
501            | TyKind::Bound(..)
502            | TyKind::Placeholder(..)
503            | TyKind::Never
504            | TyKind::Foreign(..) => return self,
505        };
506
507        if self.kind() == kind { self } else { Ty::new(folder.cx(), kind) }
508    }
509}
510
511impl<'db> Relate<DbInterner<'db>> for Ty<'db> {
512    fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
513        relation: &mut R,
514        a: Self,
515        b: Self,
516    ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
517        relation.tys(a, b)
518    }
519}
520
521impl<'db> Flags for Ty<'db> {
522    fn flags(&self) -> rustc_type_ir::TypeFlags {
523        self.inner().flags
524    }
525
526    fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
527        self.inner().outer_exclusive_binder
528    }
529}
530
531impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
532    fn new_unit(interner: DbInterner<'db>) -> Self {
533        Ty::new(interner, TyKind::Tuple(Default::default()))
534    }
535
536    fn new_bool(interner: DbInterner<'db>) -> Self {
537        Ty::new(interner, TyKind::Bool)
538    }
539
540    fn new_u8(interner: DbInterner<'db>) -> Self {
541        Ty::new(interner, TyKind::Uint(rustc_type_ir::UintTy::U8))
542    }
543
544    fn new_usize(interner: DbInterner<'db>) -> Self {
545        Ty::new(interner, TyKind::Uint(rustc_type_ir::UintTy::Usize))
546    }
547
548    fn new_infer(interner: DbInterner<'db>, var: rustc_type_ir::InferTy) -> Self {
549        Ty::new(interner, TyKind::Infer(var))
550    }
551
552    fn new_var(interner: DbInterner<'db>, var: rustc_type_ir::TyVid) -> Self {
553        Ty::new(interner, TyKind::Infer(rustc_type_ir::InferTy::TyVar(var)))
554    }
555
556    fn new_param(interner: DbInterner<'db>, param: ParamTy) -> Self {
557        Ty::new(interner, TyKind::Param(param))
558    }
559
560    fn new_placeholder(interner: DbInterner<'db>, param: PlaceholderTy) -> Self {
561        Ty::new(interner, TyKind::Placeholder(param))
562    }
563
564    fn new_bound(
565        interner: DbInterner<'db>,
566        debruijn: rustc_type_ir::DebruijnIndex,
567        var: BoundTy,
568    ) -> Self {
569        Ty::new(interner, TyKind::Bound(debruijn, var))
570    }
571
572    fn new_anon_bound(
573        interner: DbInterner<'db>,
574        debruijn: rustc_type_ir::DebruijnIndex,
575        var: BoundVar,
576    ) -> Self {
577        Ty::new(interner, TyKind::Bound(debruijn, BoundTy { var, kind: BoundTyKind::Anon }))
578    }
579
580    fn new_alias(
581        interner: DbInterner<'db>,
582        kind: rustc_type_ir::AliasTyKind,
583        alias_ty: rustc_type_ir::AliasTy<DbInterner<'db>>,
584    ) -> Self {
585        Ty::new(interner, TyKind::Alias(kind, alias_ty))
586    }
587
588    fn new_error(interner: DbInterner<'db>, guar: ErrorGuaranteed) -> Self {
589        Ty::new(interner, TyKind::Error(guar))
590    }
591
592    fn new_adt(
593        interner: DbInterner<'db>,
594        adt_def: <DbInterner<'db> as rustc_type_ir::Interner>::AdtDef,
595        args: GenericArgs<'db>,
596    ) -> Self {
597        Ty::new(interner, TyKind::Adt(adt_def, args))
598    }
599
600    fn new_foreign(
601        interner: DbInterner<'db>,
602        def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
603    ) -> Self {
604        Ty::new(interner, TyKind::Foreign(def_id))
605    }
606
607    fn new_dynamic(
608        interner: DbInterner<'db>,
609        preds: <DbInterner<'db> as rustc_type_ir::Interner>::BoundExistentialPredicates,
610        region: <DbInterner<'db> as rustc_type_ir::Interner>::Region,
611        kind: rustc_type_ir::DynKind,
612    ) -> Self {
613        Ty::new(interner, TyKind::Dynamic(preds, region, kind))
614    }
615
616    fn new_coroutine(
617        interner: DbInterner<'db>,
618        def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
619        args: <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs,
620    ) -> Self {
621        Ty::new(interner, TyKind::Coroutine(def_id, args))
622    }
623
624    fn new_coroutine_closure(
625        interner: DbInterner<'db>,
626        def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
627        args: <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs,
628    ) -> Self {
629        Ty::new(interner, TyKind::CoroutineClosure(def_id, args))
630    }
631
632    fn new_closure(
633        interner: DbInterner<'db>,
634        def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
635        args: <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs,
636    ) -> Self {
637        Ty::new(interner, TyKind::Closure(def_id, args))
638    }
639
640    fn new_coroutine_witness(
641        interner: DbInterner<'db>,
642        def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
643        args: <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs,
644    ) -> Self {
645        Ty::new(interner, TyKind::CoroutineWitness(def_id, args))
646    }
647
648    fn new_ptr(interner: DbInterner<'db>, ty: Self, mutbl: rustc_ast_ir::Mutability) -> Self {
649        Ty::new(interner, TyKind::RawPtr(ty, mutbl))
650    }
651
652    fn new_ref(
653        interner: DbInterner<'db>,
654        region: <DbInterner<'db> as rustc_type_ir::Interner>::Region,
655        ty: Self,
656        mutbl: rustc_ast_ir::Mutability,
657    ) -> Self {
658        Ty::new(interner, TyKind::Ref(region, ty, mutbl))
659    }
660
661    fn new_array_with_const_len(
662        interner: DbInterner<'db>,
663        ty: Self,
664        len: <DbInterner<'db> as rustc_type_ir::Interner>::Const,
665    ) -> Self {
666        Ty::new(interner, TyKind::Array(ty, len))
667    }
668
669    fn new_slice(interner: DbInterner<'db>, ty: Self) -> Self {
670        Ty::new(interner, TyKind::Slice(ty))
671    }
672
673    fn new_tup(
674        interner: DbInterner<'db>,
675        tys: &[<DbInterner<'db> as rustc_type_ir::Interner>::Ty],
676    ) -> Self {
677        Ty::new(interner, TyKind::Tuple(Tys::new_from_iter(interner, tys.iter().cloned())))
678    }
679
680    fn new_tup_from_iter<It, T>(interner: DbInterner<'db>, iter: It) -> T::Output
681    where
682        It: Iterator<Item = T>,
683        T: rustc_type_ir::CollectAndApply<Self, Self>,
684    {
685        T::collect_and_apply(iter, |ts| Ty::new_tup(interner, ts))
686    }
687
688    fn new_fn_def(
689        interner: DbInterner<'db>,
690        def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
691        args: <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs,
692    ) -> Self {
693        Ty::new(interner, TyKind::FnDef(def_id, args))
694    }
695
696    fn new_fn_ptr(
697        interner: DbInterner<'db>,
698        sig: rustc_type_ir::Binder<DbInterner<'db>, rustc_type_ir::FnSig<DbInterner<'db>>>,
699    ) -> Self {
700        let (sig_tys, header) = sig.split();
701        Ty::new(interner, TyKind::FnPtr(sig_tys, header))
702    }
703
704    fn new_pat(
705        interner: DbInterner<'db>,
706        ty: Self,
707        pat: <DbInterner<'db> as rustc_type_ir::Interner>::Pat,
708    ) -> Self {
709        Ty::new(interner, TyKind::Pat(ty, pat))
710    }
711
712    fn tuple_fields(self) -> <DbInterner<'db> as rustc_type_ir::Interner>::Tys {
713        match self.kind() {
714            TyKind::Tuple(args) => args,
715            _ => panic!("tuple_fields called on non-tuple: {self:?}"),
716        }
717    }
718
719    fn to_opt_closure_kind(self) -> Option<rustc_type_ir::ClosureKind> {
720        match self.kind() {
721            TyKind::Int(int_ty) => match int_ty {
722                IntTy::I8 => Some(ClosureKind::Fn),
723                IntTy::I16 => Some(ClosureKind::FnMut),
724                IntTy::I32 => Some(ClosureKind::FnOnce),
725                _ => unreachable!("cannot convert type `{:?}` to a closure kind", self),
726            },
727
728            // "Bound" types appear in canonical queries when the
729            // closure type is not yet known, and `Placeholder` and `Param`
730            // may be encountered in generic `AsyncFnKindHelper` goals.
731            TyKind::Bound(..) | TyKind::Placeholder(_) | TyKind::Param(_) | TyKind::Infer(_) => {
732                None
733            }
734
735            TyKind::Error(_) => Some(ClosureKind::Fn),
736
737            _ => unreachable!("cannot convert type `{:?}` to a closure kind", self),
738        }
739    }
740
741    fn from_closure_kind(interner: DbInterner<'db>, kind: rustc_type_ir::ClosureKind) -> Self {
742        match kind {
743            ClosureKind::Fn => Ty::new(interner, TyKind::Int(IntTy::I8)),
744            ClosureKind::FnMut => Ty::new(interner, TyKind::Int(IntTy::I16)),
745            ClosureKind::FnOnce => Ty::new(interner, TyKind::Int(IntTy::I32)),
746        }
747    }
748
749    fn from_coroutine_closure_kind(
750        interner: DbInterner<'db>,
751        kind: rustc_type_ir::ClosureKind,
752    ) -> Self {
753        match kind {
754            ClosureKind::Fn | ClosureKind::FnMut => Ty::new(interner, TyKind::Int(IntTy::I16)),
755            ClosureKind::FnOnce => Ty::new(interner, TyKind::Int(IntTy::I32)),
756        }
757    }
758
759    fn discriminant_ty(
760        self,
761        interner: DbInterner<'db>,
762    ) -> <DbInterner<'db> as rustc_type_ir::Interner>::Ty {
763        match self.kind() {
764            TyKind::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(interner),
765            TyKind::Coroutine(_, args) => args.as_coroutine().discr_ty(interner),
766
767            TyKind::Param(_) | TyKind::Alias(..) | TyKind::Infer(InferTy::TyVar(_)) => {
768                /*
769                let assoc_items = tcx.associated_item_def_ids(
770                    tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
771                );
772                TyKind::new_projection_from_args(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
773                */
774                unimplemented!()
775            }
776
777            TyKind::Pat(ty, _) => ty.discriminant_ty(interner),
778
779            TyKind::Bool
780            | TyKind::Char
781            | TyKind::Int(_)
782            | TyKind::Uint(_)
783            | TyKind::Float(_)
784            | TyKind::Adt(..)
785            | TyKind::Foreign(_)
786            | TyKind::Str
787            | TyKind::Array(..)
788            | TyKind::Slice(_)
789            | TyKind::RawPtr(_, _)
790            | TyKind::Ref(..)
791            | TyKind::FnDef(..)
792            | TyKind::FnPtr(..)
793            | TyKind::Dynamic(..)
794            | TyKind::Closure(..)
795            | TyKind::CoroutineClosure(..)
796            | TyKind::CoroutineWitness(..)
797            | TyKind::Never
798            | TyKind::Tuple(_)
799            | TyKind::Error(_)
800            | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) => {
801                Ty::new(interner, TyKind::Uint(UintTy::U8))
802            }
803
804            TyKind::Bound(..)
805            | TyKind::Placeholder(_)
806            | TyKind::Infer(
807                InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_),
808            ) => {
809                panic!(
810                    "`dself.iter().map(|v| v.try_fold_with(folder)).collect::<Result<_, _>>()?iscriminant_ty` applied to unexpected type: {self:?}"
811                )
812            }
813            TyKind::UnsafeBinder(..) => unimplemented!(),
814        }
815    }
816
817    fn new_unsafe_binder(
818        interner: DbInterner<'db>,
819        ty: rustc_type_ir::Binder<
820            DbInterner<'db>,
821            <DbInterner<'db> as rustc_type_ir::Interner>::Ty,
822        >,
823    ) -> Self {
824        Ty::new(interner, TyKind::UnsafeBinder(ty.into()))
825    }
826
827    fn has_unsafe_fields(self) -> bool {
828        false
829    }
830}
831
832interned_vec_db!(Tys, Ty);
833
834impl<'db> rustc_type_ir::inherent::Tys<DbInterner<'db>> for Tys<'db> {
835    fn inputs(self) -> <DbInterner<'db> as rustc_type_ir::Interner>::FnInputTys {
836        Tys::new_from_iter(
837            DbInterner::conjure(),
838            self.as_slice().split_last().unwrap().1.iter().cloned(),
839        )
840    }
841
842    fn output(self) -> <DbInterner<'db> as rustc_type_ir::Interner>::Ty {
843        *self.as_slice().split_last().unwrap().0
844    }
845}
846
847pub type PlaceholderTy = Placeholder<BoundTy>;
848
849#[derive(Copy, Clone, PartialEq, Eq, Hash)]
850pub struct ParamTy {
851    // FIXME: I'm not pleased with this. Ideally a `Param` should only know its index - the defining item
852    // is known from the `EarlyBinder`. This should also be beneficial for memory usage. But code currently
853    // assumes it can get the definition from `Param` alone - so that's what we got.
854    pub id: TypeParamId,
855    pub index: u32,
856}
857
858impl ParamTy {
859    pub fn to_ty<'db>(self, interner: DbInterner<'db>) -> Ty<'db> {
860        Ty::new_param(interner, self.id, self.index, sym::MISSING_NAME.clone())
861    }
862}
863
864impl std::fmt::Debug for ParamTy {
865    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
866        write!(f, "#{}", self.index)
867    }
868}
869
870#[derive(Copy, Clone, PartialEq, Eq, Hash)]
871pub struct BoundTy {
872    pub var: BoundVar,
873    // FIXME: This is for diagnostics in rustc, do we really need it?
874    pub kind: BoundTyKind,
875}
876
877impl std::fmt::Debug for BoundTy {
878    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
879        match self.kind {
880            BoundTyKind::Anon => write!(f, "{:?}", self.var),
881            BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"),
882        }
883    }
884}
885
886#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
887pub enum BoundTyKind {
888    Anon,
889    Param(SolverDefId),
890}
891
892#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
893pub struct ErrorGuaranteed;
894
895impl<'db> TypeVisitable<DbInterner<'db>> for ErrorGuaranteed {
896    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
897        &self,
898        visitor: &mut V,
899    ) -> V::Result {
900        visitor.visit_error(*self)
901    }
902}
903
904impl<'db> TypeFoldable<DbInterner<'db>> for ErrorGuaranteed {
905    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
906        self,
907        folder: &mut F,
908    ) -> Result<Self, F::Error> {
909        Ok(self)
910    }
911    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
912        self
913    }
914}
915
916impl ParamLike for ParamTy {
917    fn index(self) -> u32 {
918        self.index
919    }
920}
921
922impl<'db> BoundVarLike<DbInterner<'db>> for BoundTy {
923    fn var(self) -> BoundVar {
924        self.var
925    }
926
927    fn assert_eq(self, var: BoundVarKind) {
928        assert_eq!(self.kind, var.expect_ty())
929    }
930}
931
932impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderTy {
933    type Bound = BoundTy;
934
935    fn universe(self) -> rustc_type_ir::UniverseIndex {
936        self.universe
937    }
938
939    fn var(self) -> BoundVar {
940        self.bound.var
941    }
942
943    fn with_updated_universe(self, ui: rustc_type_ir::UniverseIndex) -> Self {
944        Placeholder { universe: ui, bound: self.bound }
945    }
946
947    fn new(ui: rustc_type_ir::UniverseIndex, bound: BoundTy) -> Self {
948        Placeholder { universe: ui, bound }
949    }
950
951    fn new_anon(ui: rustc_type_ir::UniverseIndex, var: rustc_type_ir::BoundVar) -> Self {
952        Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
953    }
954}