hir_ty/next_solver/
ty.rs

1//! Things related to tys in the next-trait-solver.
2
3use std::ops::ControlFlow;
4
5use hir_def::{
6    AdtId, HasModule, TypeParamId,
7    hir::generics::{TypeOrConstParamData, TypeParamProvenance},
8};
9use hir_def::{TraitId, type_ref::Rawness};
10use rustc_abi::{Float, Integer, Size};
11use rustc_ast_ir::{Mutability, try_visit, visit::VisitorResult};
12use rustc_type_ir::{
13    AliasTyKind, BoundVar, BoundVarIndexKind, ClosureKind, CoroutineArgs, CoroutineArgsParts,
14    DebruijnIndex, FlagComputation, Flags, FloatTy, FloatVid, InferTy, IntTy, IntVid, Interner,
15    TyVid, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
16    TypeVisitor, UintTy, Upcast, WithCachedTypeInfo,
17    inherent::{
18        AdtDef as _, BoundExistentialPredicates, BoundVarLike, Const as _, GenericArgs as _,
19        IntoKind, ParamLike, PlaceholderLike, Safety as _, SliceLike, Ty as _,
20    },
21    relate::Relate,
22    solve::SizedTraitKind,
23    walk::TypeWalker,
24};
25
26use crate::{
27    db::{HirDatabase, InternedCoroutine},
28    lower::GenericPredicates,
29    next_solver::{
30        AdtDef, AliasTy, Binder, CallableIdWrapper, Clause, ClauseKind, ClosureIdWrapper, Const,
31        CoroutineIdWrapper, FnSig, GenericArg, PolyFnSig, Region, TraitRef, TypeAliasIdWrapper,
32        abi::Safety,
33        interner::InternedWrapperNoDebug,
34        util::{CoroutineArgsExt, IntegerTypeExt},
35    },
36};
37
38use super::{
39    BoundVarKind, DbInterner, GenericArgs, Placeholder, SolverDefId, interned_vec_db,
40    util::{FloatExt, IntegerExt},
41};
42
43pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType<SolverDefId>;
44pub type TyKind<'db> = rustc_type_ir::TyKind<DbInterner<'db>>;
45pub type FnHeader<'db> = rustc_type_ir::FnHeader<DbInterner<'db>>;
46
47#[salsa::interned(constructor = new_)]
48pub struct Ty<'db> {
49    #[returns(ref)]
50    kind_: InternedWrapperNoDebug<WithCachedTypeInfo<TyKind<'db>>>,
51}
52
53const _: () = {
54    const fn is_copy<T: Copy>() {}
55    is_copy::<Ty<'static>>();
56};
57
58impl<'db> Ty<'db> {
59    pub fn new(interner: DbInterner<'db>, kind: TyKind<'db>) -> Self {
60        let flags = FlagComputation::for_kind(&kind);
61        let cached = WithCachedTypeInfo {
62            internee: kind,
63            flags: flags.flags,
64            outer_exclusive_binder: flags.outer_exclusive_binder,
65        };
66        Ty::new_(interner.db(), InternedWrapperNoDebug(cached))
67    }
68
69    pub fn inner(&self) -> &WithCachedTypeInfo<TyKind<'db>> {
70        crate::with_attached_db(|db| {
71            let inner = &self.kind_(db).0;
72            // SAFETY: The caller already has access to a `Ty<'db>`, so borrowchecking will
73            // make sure that our returned value is valid for the lifetime `'db`.
74            unsafe { std::mem::transmute(inner) }
75        })
76    }
77
78    pub fn new_adt(interner: DbInterner<'db>, adt_id: AdtId, args: GenericArgs<'db>) -> Self {
79        Ty::new(interner, TyKind::Adt(AdtDef::new(adt_id, interner), args))
80    }
81
82    pub fn new_param(interner: DbInterner<'db>, id: TypeParamId, index: u32) -> Self {
83        Ty::new(interner, TyKind::Param(ParamTy { id, index }))
84    }
85
86    pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderTy) -> Self {
87        Ty::new(interner, TyKind::Placeholder(placeholder))
88    }
89
90    pub fn new_infer(interner: DbInterner<'db>, infer: InferTy) -> Self {
91        Ty::new(interner, TyKind::Infer(infer))
92    }
93
94    pub fn new_int_var(interner: DbInterner<'db>, v: IntVid) -> Self {
95        Ty::new_infer(interner, InferTy::IntVar(v))
96    }
97
98    pub fn new_float_var(interner: DbInterner<'db>, v: FloatVid) -> Self {
99        Ty::new_infer(interner, InferTy::FloatVar(v))
100    }
101
102    pub fn new_int(interner: DbInterner<'db>, i: IntTy) -> Self {
103        Ty::new(interner, TyKind::Int(i))
104    }
105
106    pub fn new_uint(interner: DbInterner<'db>, ui: UintTy) -> Self {
107        Ty::new(interner, TyKind::Uint(ui))
108    }
109
110    pub fn new_float(interner: DbInterner<'db>, f: FloatTy) -> Self {
111        Ty::new(interner, TyKind::Float(f))
112    }
113
114    pub fn new_fresh(interner: DbInterner<'db>, n: u32) -> Self {
115        Ty::new_infer(interner, InferTy::FreshTy(n))
116    }
117
118    pub fn new_fresh_int(interner: DbInterner<'db>, n: u32) -> Self {
119        Ty::new_infer(interner, InferTy::FreshIntTy(n))
120    }
121
122    pub fn new_fresh_float(interner: DbInterner<'db>, n: u32) -> Self {
123        Ty::new_infer(interner, InferTy::FreshFloatTy(n))
124    }
125
126    pub fn new_empty_tuple(interner: DbInterner<'db>) -> Self {
127        Ty::new_tup(interner, &[])
128    }
129
130    pub fn new_imm_ptr(interner: DbInterner<'db>, ty: Ty<'db>) -> Self {
131        Ty::new_ptr(interner, ty, Mutability::Not)
132    }
133
134    pub fn new_imm_ref(interner: DbInterner<'db>, region: Region<'db>, ty: Ty<'db>) -> Self {
135        Ty::new_ref(interner, region, ty, Mutability::Not)
136    }
137
138    pub fn new_opaque(
139        interner: DbInterner<'db>,
140        def_id: SolverDefId,
141        args: GenericArgs<'db>,
142    ) -> Self {
143        Ty::new_alias(interner, AliasTyKind::Opaque, AliasTy::new_from_args(interner, def_id, args))
144    }
145
146    /// Returns the `Size` for primitive types (bool, uint, int, char, float).
147    pub fn primitive_size(self, interner: DbInterner<'db>) -> Size {
148        match self.kind() {
149            TyKind::Bool => Size::from_bytes(1),
150            TyKind::Char => Size::from_bytes(4),
151            TyKind::Int(ity) => Integer::from_int_ty(&interner, ity).size(),
152            TyKind::Uint(uty) => Integer::from_uint_ty(&interner, uty).size(),
153            TyKind::Float(fty) => Float::from_float_ty(fty).size(),
154            _ => panic!("non primitive type"),
155        }
156    }
157
158    pub fn int_size_and_signed(self, interner: DbInterner<'db>) -> (Size, bool) {
159        match self.kind() {
160            TyKind::Int(ity) => (Integer::from_int_ty(&interner, ity).size(), true),
161            TyKind::Uint(uty) => (Integer::from_uint_ty(&interner, uty).size(), false),
162            _ => panic!("non integer discriminant"),
163        }
164    }
165
166    pub fn walk(self) -> TypeWalker<DbInterner<'db>> {
167        TypeWalker::new(self.into())
168    }
169
170    /// Fast path helper for testing if a type is `Sized` or `MetaSized`.
171    ///
172    /// Returning true means the type is known to implement the sizedness trait. Returning `false`
173    /// means nothing -- could be sized, might not be.
174    ///
175    /// Note that we could never rely on the fact that a type such as `[_]` is trivially `!Sized`
176    /// because we could be in a type environment with a bound such as `[_]: Copy`. A function with
177    /// such a bound obviously never can be called, but that doesn't mean it shouldn't typecheck.
178    /// This is why this method doesn't return `Option<bool>`.
179    #[tracing::instrument(skip(tcx), level = "debug")]
180    pub fn has_trivial_sizedness(self, tcx: DbInterner<'db>, sizedness: SizedTraitKind) -> bool {
181        match self.kind() {
182            TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_))
183            | TyKind::Uint(_)
184            | TyKind::Int(_)
185            | TyKind::Bool
186            | TyKind::Float(_)
187            | TyKind::FnDef(..)
188            | TyKind::FnPtr(..)
189            | TyKind::UnsafeBinder(_)
190            | TyKind::RawPtr(..)
191            | TyKind::Char
192            | TyKind::Ref(..)
193            | TyKind::Coroutine(..)
194            | TyKind::CoroutineWitness(..)
195            | TyKind::Array(..)
196            | TyKind::Pat(..)
197            | TyKind::Closure(..)
198            | TyKind::CoroutineClosure(..)
199            | TyKind::Never
200            | TyKind::Error(_) => true,
201
202            TyKind::Str | TyKind::Slice(_) | TyKind::Dynamic(_, _) => match sizedness {
203                SizedTraitKind::Sized => false,
204                SizedTraitKind::MetaSized => true,
205            },
206
207            TyKind::Foreign(..) => match sizedness {
208                SizedTraitKind::Sized | SizedTraitKind::MetaSized => false,
209            },
210
211            TyKind::Tuple(tys) => {
212                tys.last().is_none_or(|ty| ty.has_trivial_sizedness(tcx, sizedness))
213            }
214
215            TyKind::Adt(def, args) => def
216                .sizedness_constraint(tcx, sizedness)
217                .is_none_or(|ty| ty.instantiate(tcx, args).has_trivial_sizedness(tcx, sizedness)),
218
219            TyKind::Alias(..) | TyKind::Param(_) | TyKind::Placeholder(..) | TyKind::Bound(..) => {
220                false
221            }
222
223            TyKind::Infer(InferTy::TyVar(_)) => false,
224
225            TyKind::Infer(
226                InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_),
227            ) => {
228                panic!("`has_trivial_sizedness` applied to unexpected type: {self:?}")
229            }
230        }
231    }
232
233    /// Fast path helper for primitives which are always `Copy` and which
234    /// have a side-effect-free `Clone` impl.
235    ///
236    /// Returning true means the type is known to be pure and `Copy+Clone`.
237    /// Returning `false` means nothing -- could be `Copy`, might not be.
238    ///
239    /// This is mostly useful for optimizations, as these are the types
240    /// on which we can replace cloning with dereferencing.
241    pub fn is_trivially_pure_clone_copy(self) -> bool {
242        match self.kind() {
243            TyKind::Bool | TyKind::Char | TyKind::Never => true,
244
245            // These aren't even `Clone`
246            TyKind::Str | TyKind::Slice(..) | TyKind::Foreign(..) | TyKind::Dynamic(..) => false,
247
248            TyKind::Infer(InferTy::FloatVar(_) | InferTy::IntVar(_))
249            | TyKind::Int(..)
250            | TyKind::Uint(..)
251            | TyKind::Float(..) => true,
252
253            // ZST which can't be named are fine.
254            TyKind::FnDef(..) => true,
255
256            TyKind::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(),
257
258            // A 100-tuple isn't "trivial", so doing this only for reasonable sizes.
259            TyKind::Tuple(field_tys) => {
260                field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy)
261            }
262
263            TyKind::Pat(ty, _) => ty.is_trivially_pure_clone_copy(),
264
265            // Sometimes traits aren't implemented for every ABI or arity,
266            // because we can't be generic over everything yet.
267            TyKind::FnPtr(..) => false,
268
269            // Definitely absolutely not copy.
270            TyKind::Ref(_, _, Mutability::Mut) => false,
271
272            // The standard library has a blanket Copy impl for shared references and raw pointers,
273            // for all unsized types.
274            TyKind::Ref(_, _, Mutability::Not) | TyKind::RawPtr(..) => true,
275
276            TyKind::Coroutine(..) | TyKind::CoroutineWitness(..) => false,
277
278            // Might be, but not "trivial" so just giving the safe answer.
279            TyKind::Adt(..) | TyKind::Closure(..) | TyKind::CoroutineClosure(..) => false,
280
281            TyKind::UnsafeBinder(_) => false,
282
283            // Needs normalization or revealing to determine, so no is the safe answer.
284            TyKind::Alias(..) => false,
285
286            TyKind::Param(..)
287            | TyKind::Placeholder(..)
288            | TyKind::Bound(..)
289            | TyKind::Infer(..)
290            | TyKind::Error(..) => false,
291        }
292    }
293
294    pub fn is_trivially_wf(self, tcx: DbInterner<'db>) -> bool {
295        match self.kind() {
296            TyKind::Bool
297            | TyKind::Char
298            | TyKind::Int(_)
299            | TyKind::Uint(_)
300            | TyKind::Float(_)
301            | TyKind::Str
302            | TyKind::Never
303            | TyKind::Param(_)
304            | TyKind::Placeholder(_)
305            | TyKind::Bound(..) => true,
306
307            TyKind::Slice(ty) => {
308                ty.is_trivially_wf(tcx) && ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized)
309            }
310            TyKind::RawPtr(ty, _) => ty.is_trivially_wf(tcx),
311
312            TyKind::FnPtr(sig_tys, _) => {
313                sig_tys.skip_binder().inputs_and_output.iter().all(|ty| ty.is_trivially_wf(tcx))
314            }
315            TyKind::Ref(_, ty, _) => ty.is_global() && ty.is_trivially_wf(tcx),
316
317            TyKind::Infer(infer) => match infer {
318                InferTy::TyVar(_) => false,
319                InferTy::IntVar(_) | InferTy::FloatVar(_) => true,
320                InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_) => true,
321            },
322
323            TyKind::Adt(_, _)
324            | TyKind::Tuple(_)
325            | TyKind::Array(..)
326            | TyKind::Foreign(_)
327            | TyKind::Pat(_, _)
328            | TyKind::FnDef(..)
329            | TyKind::UnsafeBinder(..)
330            | TyKind::Dynamic(..)
331            | TyKind::Closure(..)
332            | TyKind::CoroutineClosure(..)
333            | TyKind::Coroutine(..)
334            | TyKind::CoroutineWitness(..)
335            | TyKind::Alias(..)
336            | TyKind::Error(_) => false,
337        }
338    }
339
340    #[inline]
341    pub fn is_never(self) -> bool {
342        matches!(self.kind(), TyKind::Never)
343    }
344
345    #[inline]
346    pub fn is_bool(self) -> bool {
347        matches!(self.kind(), TyKind::Bool)
348    }
349
350    /// A scalar type is one that denotes an atomic datum, with no sub-components.
351    /// (A RawPtr is scalar because it represents a non-managed pointer, so its
352    /// contents are abstract to rustc.)
353    #[inline]
354    pub fn is_scalar(self) -> bool {
355        matches!(
356            self.kind(),
357            TyKind::Bool
358                | TyKind::Char
359                | TyKind::Int(_)
360                | TyKind::Float(_)
361                | TyKind::Uint(_)
362                | TyKind::FnDef(..)
363                | TyKind::FnPtr(..)
364                | TyKind::RawPtr(_, _)
365                | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_))
366        )
367    }
368
369    #[inline]
370    pub fn is_infer(self) -> bool {
371        matches!(self.kind(), TyKind::Infer(..))
372    }
373
374    #[inline]
375    pub fn is_numeric(self) -> bool {
376        self.is_integral() || self.is_floating_point()
377    }
378
379    #[inline]
380    pub fn is_str(self) -> bool {
381        matches!(self.kind(), TyKind::Str)
382    }
383
384    #[inline]
385    pub fn is_unit(self) -> bool {
386        matches!(self.kind(), TyKind::Tuple(tys) if tys.inner().is_empty())
387    }
388
389    #[inline]
390    pub fn is_raw_ptr(self) -> bool {
391        matches!(self.kind(), TyKind::RawPtr(..))
392    }
393
394    #[inline]
395    pub fn is_array(self) -> bool {
396        matches!(self.kind(), TyKind::Array(..))
397    }
398
399    #[inline]
400    pub fn is_slice(self) -> bool {
401        matches!(self.kind(), TyKind::Slice(..))
402    }
403
404    pub fn is_union(self) -> bool {
405        self.as_adt().is_some_and(|(adt, _)| matches!(adt, AdtId::UnionId(_)))
406    }
407
408    pub fn boxed_ty(self) -> Option<Ty<'db>> {
409        match self.kind() {
410            TyKind::Adt(adt_def, args) if adt_def.is_box() => Some(args.type_at(0)),
411            _ => None,
412        }
413    }
414
415    #[inline]
416    pub fn as_adt(self) -> Option<(AdtId, GenericArgs<'db>)> {
417        match self.kind() {
418            TyKind::Adt(adt_def, args) => Some((adt_def.def_id().0, args)),
419            _ => None,
420        }
421    }
422
423    #[inline]
424    pub fn ty_vid(self) -> Option<TyVid> {
425        match self.kind() {
426            TyKind::Infer(rustc_type_ir::TyVar(vid)) => Some(vid),
427            _ => None,
428        }
429    }
430
431    /// Given a `fn` type, returns an equivalent `unsafe fn` type;
432    /// that is, a `fn` type that is equivalent in every way for being
433    /// unsafe.
434    pub fn safe_to_unsafe_fn_ty(interner: DbInterner<'db>, sig: PolyFnSig<'db>) -> Ty<'db> {
435        assert!(sig.safety().is_safe());
436        Ty::new_fn_ptr(interner, sig.map_bound(|sig| FnSig { safety: Safety::Unsafe, ..sig }))
437    }
438
439    /// Returns the type of `*ty`.
440    ///
441    /// The parameter `explicit` indicates if this is an *explicit* dereference.
442    /// Some types -- notably raw ptrs -- can only be dereferenced explicitly.
443    pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'db>> {
444        match self.kind() {
445            TyKind::Adt(adt, substs) if adt.is_box() => Some(substs.as_slice()[0].expect_ty()),
446            TyKind::Ref(_, ty, _) => Some(ty),
447            TyKind::RawPtr(ty, _) if explicit => Some(ty),
448            _ => None,
449        }
450    }
451
452    /// Whether the type contains some non-lifetime, aka. type or const, error type.
453    pub fn references_non_lt_error(self) -> bool {
454        references_non_lt_error(&self)
455    }
456
457    pub fn callable_sig(self, interner: DbInterner<'db>) -> Option<Binder<'db, FnSig<'db>>> {
458        match self.kind() {
459            TyKind::FnDef(callable, args) => {
460                Some(interner.fn_sig(callable).instantiate(interner, args))
461            }
462            TyKind::FnPtr(sig, hdr) => Some(sig.with(hdr)),
463            TyKind::Closure(_, closure_args) => closure_args
464                .split_closure_args_untupled()
465                .closure_sig_as_fn_ptr_ty
466                .callable_sig(interner),
467            TyKind::CoroutineClosure(coroutine_id, args) => {
468                Some(args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
469                    let unit_ty = Ty::new_unit(interner);
470                    let return_ty = Ty::new_coroutine(
471                        interner,
472                        coroutine_id,
473                        CoroutineArgs::new(
474                            interner,
475                            CoroutineArgsParts {
476                                parent_args: args.as_coroutine_closure().parent_args(),
477                                kind_ty: unit_ty,
478                                resume_ty: unit_ty,
479                                yield_ty: unit_ty,
480                                return_ty: sig.return_ty,
481                                // FIXME: Deduce this from the coroutine closure's upvars.
482                                tupled_upvars_ty: unit_ty,
483                            },
484                        )
485                        .args,
486                    );
487                    FnSig {
488                        inputs_and_output: Tys::new_from_iter(
489                            interner,
490                            sig.tupled_inputs_ty
491                                .tuple_fields()
492                                .iter()
493                                .chain(std::iter::once(return_ty)),
494                        ),
495                        c_variadic: sig.c_variadic,
496                        safety: sig.safety,
497                        abi: sig.abi,
498                    }
499                }))
500            }
501            _ => None,
502        }
503    }
504
505    pub fn as_reference(self) -> Option<(Ty<'db>, Region<'db>, Mutability)> {
506        match self.kind() {
507            TyKind::Ref(region, ty, mutability) => Some((ty, region, mutability)),
508            _ => None,
509        }
510    }
511
512    pub fn as_reference_or_ptr(self) -> Option<(Ty<'db>, Rawness, Mutability)> {
513        match self.kind() {
514            TyKind::Ref(_, ty, mutability) => Some((ty, Rawness::Ref, mutability)),
515            TyKind::RawPtr(ty, mutability) => Some((ty, Rawness::RawPtr, mutability)),
516            _ => None,
517        }
518    }
519
520    pub fn as_tuple(self) -> Option<Tys<'db>> {
521        match self.kind() {
522            TyKind::Tuple(tys) => Some(tys),
523            _ => None,
524        }
525    }
526
527    pub fn dyn_trait(self) -> Option<TraitId> {
528        let TyKind::Dynamic(bounds, _) = self.kind() else { return None };
529        Some(bounds.principal_def_id()?.0)
530    }
531
532    pub fn strip_references(self) -> Ty<'db> {
533        let mut t = self;
534        while let TyKind::Ref(_lifetime, ty, _mutability) = t.kind() {
535            t = ty;
536        }
537        t
538    }
539
540    pub fn strip_reference(self) -> Ty<'db> {
541        self.as_reference().map_or(self, |(ty, _, _)| ty)
542    }
543
544    /// Replace infer vars with errors.
545    ///
546    /// This needs to be called for every type that may contain infer vars and is yielded to outside inference,
547    /// as things other than inference do not expect to see infer vars.
548    pub fn replace_infer_with_error(self, interner: DbInterner<'db>) -> Ty<'db> {
549        self.fold_with(&mut crate::next_solver::infer::resolve::ReplaceInferWithError::new(
550            interner,
551        ))
552    }
553
554    pub fn from_builtin_type(
555        interner: DbInterner<'db>,
556        ty: hir_def::builtin_type::BuiltinType,
557    ) -> Ty<'db> {
558        let kind = match ty {
559            hir_def::builtin_type::BuiltinType::Char => TyKind::Char,
560            hir_def::builtin_type::BuiltinType::Bool => TyKind::Bool,
561            hir_def::builtin_type::BuiltinType::Str => TyKind::Str,
562            hir_def::builtin_type::BuiltinType::Int(int) => TyKind::Int(match int {
563                hir_def::builtin_type::BuiltinInt::Isize => rustc_type_ir::IntTy::Isize,
564                hir_def::builtin_type::BuiltinInt::I8 => rustc_type_ir::IntTy::I8,
565                hir_def::builtin_type::BuiltinInt::I16 => rustc_type_ir::IntTy::I16,
566                hir_def::builtin_type::BuiltinInt::I32 => rustc_type_ir::IntTy::I32,
567                hir_def::builtin_type::BuiltinInt::I64 => rustc_type_ir::IntTy::I64,
568                hir_def::builtin_type::BuiltinInt::I128 => rustc_type_ir::IntTy::I128,
569            }),
570            hir_def::builtin_type::BuiltinType::Uint(uint) => TyKind::Uint(match uint {
571                hir_def::builtin_type::BuiltinUint::Usize => rustc_type_ir::UintTy::Usize,
572                hir_def::builtin_type::BuiltinUint::U8 => rustc_type_ir::UintTy::U8,
573                hir_def::builtin_type::BuiltinUint::U16 => rustc_type_ir::UintTy::U16,
574                hir_def::builtin_type::BuiltinUint::U32 => rustc_type_ir::UintTy::U32,
575                hir_def::builtin_type::BuiltinUint::U64 => rustc_type_ir::UintTy::U64,
576                hir_def::builtin_type::BuiltinUint::U128 => rustc_type_ir::UintTy::U128,
577            }),
578            hir_def::builtin_type::BuiltinType::Float(float) => TyKind::Float(match float {
579                hir_def::builtin_type::BuiltinFloat::F16 => rustc_type_ir::FloatTy::F16,
580                hir_def::builtin_type::BuiltinFloat::F32 => rustc_type_ir::FloatTy::F32,
581                hir_def::builtin_type::BuiltinFloat::F64 => rustc_type_ir::FloatTy::F64,
582                hir_def::builtin_type::BuiltinFloat::F128 => rustc_type_ir::FloatTy::F128,
583            }),
584        };
585        Ty::new(interner, kind)
586    }
587
588    pub fn as_builtin(self) -> Option<hir_def::builtin_type::BuiltinType> {
589        let builtin = match self.kind() {
590            TyKind::Char => hir_def::builtin_type::BuiltinType::Char,
591            TyKind::Bool => hir_def::builtin_type::BuiltinType::Bool,
592            TyKind::Str => hir_def::builtin_type::BuiltinType::Str,
593            TyKind::Int(int) => hir_def::builtin_type::BuiltinType::Int(match int {
594                rustc_type_ir::IntTy::Isize => hir_def::builtin_type::BuiltinInt::Isize,
595                rustc_type_ir::IntTy::I8 => hir_def::builtin_type::BuiltinInt::I8,
596                rustc_type_ir::IntTy::I16 => hir_def::builtin_type::BuiltinInt::I16,
597                rustc_type_ir::IntTy::I32 => hir_def::builtin_type::BuiltinInt::I32,
598                rustc_type_ir::IntTy::I64 => hir_def::builtin_type::BuiltinInt::I64,
599                rustc_type_ir::IntTy::I128 => hir_def::builtin_type::BuiltinInt::I128,
600            }),
601            TyKind::Uint(uint) => hir_def::builtin_type::BuiltinType::Uint(match uint {
602                rustc_type_ir::UintTy::Usize => hir_def::builtin_type::BuiltinUint::Usize,
603                rustc_type_ir::UintTy::U8 => hir_def::builtin_type::BuiltinUint::U8,
604                rustc_type_ir::UintTy::U16 => hir_def::builtin_type::BuiltinUint::U16,
605                rustc_type_ir::UintTy::U32 => hir_def::builtin_type::BuiltinUint::U32,
606                rustc_type_ir::UintTy::U64 => hir_def::builtin_type::BuiltinUint::U64,
607                rustc_type_ir::UintTy::U128 => hir_def::builtin_type::BuiltinUint::U128,
608            }),
609            TyKind::Float(float) => hir_def::builtin_type::BuiltinType::Float(match float {
610                rustc_type_ir::FloatTy::F16 => hir_def::builtin_type::BuiltinFloat::F16,
611                rustc_type_ir::FloatTy::F32 => hir_def::builtin_type::BuiltinFloat::F32,
612                rustc_type_ir::FloatTy::F64 => hir_def::builtin_type::BuiltinFloat::F64,
613                rustc_type_ir::FloatTy::F128 => hir_def::builtin_type::BuiltinFloat::F128,
614            }),
615            _ => return None,
616        };
617        Some(builtin)
618    }
619
620    // FIXME: Should this be here?
621    pub fn impl_trait_bounds(self, db: &'db dyn HirDatabase) -> Option<Vec<Clause<'db>>> {
622        let interner = DbInterner::new_no_crate(db);
623
624        match self.kind() {
625            TyKind::Alias(AliasTyKind::Opaque, opaque_ty) => Some(
626                opaque_ty
627                    .def_id
628                    .expect_opaque_ty()
629                    .predicates(db)
630                    .iter_instantiated_copied(interner, opaque_ty.args.as_slice())
631                    .collect(),
632            ),
633            TyKind::Param(param) => {
634                // FIXME: We shouldn't use `param.id` here.
635                let generic_params = db.generic_params(param.id.parent());
636                let param_data = &generic_params[param.id.local_id()];
637                match param_data {
638                    TypeOrConstParamData::TypeParamData(p) => match p.provenance {
639                        TypeParamProvenance::ArgumentImplTrait => {
640                            let predicates = GenericPredicates::query_all(db, param.id.parent())
641                                .iter_identity_copied()
642                                .filter(|wc| match wc.kind().skip_binder() {
643                                    ClauseKind::Trait(tr) => tr.self_ty() == self,
644                                    ClauseKind::Projection(pred) => pred.self_ty() == self,
645                                    ClauseKind::TypeOutlives(pred) => pred.0 == self,
646                                    _ => false,
647                                })
648                                .collect::<Vec<_>>();
649
650                            Some(predicates)
651                        }
652                        _ => None,
653                    },
654                    _ => None,
655                }
656            }
657            TyKind::Coroutine(coroutine_id, _args) => {
658                let InternedCoroutine(owner, _) = coroutine_id.0.loc(db);
659                let krate = owner.module(db).krate(db);
660                if let Some(future_trait) = hir_def::lang_item::lang_items(db, krate).Future {
661                    // This is only used by type walking.
662                    // Parameters will be walked outside, and projection predicate is not used.
663                    // So just provide the Future trait.
664                    let impl_bound = TraitRef::new(
665                        interner,
666                        future_trait.into(),
667                        GenericArgs::new_from_iter(interner, []),
668                    )
669                    .upcast(interner);
670                    Some(vec![impl_bound])
671                } else {
672                    None
673                }
674            }
675            _ => None,
676        }
677    }
678
679    /// FIXME: Get rid of this, it's not a good abstraction
680    pub fn equals_ctor(self, other: Ty<'db>) -> bool {
681        match (self.kind(), other.kind()) {
682            (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt.def_id() == adt2.def_id(),
683            (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => {
684                true
685            }
686            (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
687            (TyKind::Alias(_, alias, ..), TyKind::Alias(_, alias2)) => {
688                alias.def_id == alias2.def_id
689            }
690            (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2,
691            (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
692            (TyKind::Ref(.., mutability), TyKind::Ref(.., mutability2))
693            | (TyKind::RawPtr(.., mutability), TyKind::RawPtr(.., mutability2)) => {
694                mutability == mutability2
695            }
696            (TyKind::FnPtr(sig, hdr), TyKind::FnPtr(sig2, hdr2)) => sig == sig2 && hdr == hdr2,
697            (TyKind::Tuple(tys), TyKind::Tuple(tys2)) => tys.len() == tys2.len(),
698            (TyKind::Str, TyKind::Str)
699            | (TyKind::Never, TyKind::Never)
700            | (TyKind::Char, TyKind::Char)
701            | (TyKind::Bool, TyKind::Bool) => true,
702            (TyKind::Int(int), TyKind::Int(int2)) => int == int2,
703            (TyKind::Float(float), TyKind::Float(float2)) => float == float2,
704            _ => false,
705        }
706    }
707}
708
709pub fn references_non_lt_error<'db, T: TypeVisitableExt<DbInterner<'db>>>(t: &T) -> bool {
710    t.references_error() && t.visit_with(&mut ReferencesNonLifetimeError).is_break()
711}
712
713struct ReferencesNonLifetimeError;
714
715impl<'db> TypeVisitor<DbInterner<'db>> for ReferencesNonLifetimeError {
716    type Result = ControlFlow<()>;
717
718    fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
719        if ty.is_ty_error() { ControlFlow::Break(()) } else { ty.super_visit_with(self) }
720    }
721
722    fn visit_const(&mut self, c: Const<'db>) -> Self::Result {
723        if c.is_ct_error() { ControlFlow::Break(()) } else { c.super_visit_with(self) }
724    }
725}
726
727impl<'db> std::fmt::Debug for Ty<'db> {
728    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
729        self.inner().internee.fmt(f)
730    }
731}
732
733impl<'db> std::fmt::Debug for InternedWrapperNoDebug<WithCachedTypeInfo<TyKind<'db>>> {
734    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
735        self.0.internee.fmt(f)
736    }
737}
738
739impl<'db> IntoKind for Ty<'db> {
740    type Kind = TyKind<'db>;
741
742    fn kind(self) -> Self::Kind {
743        self.inner().internee
744    }
745}
746
747impl<'db> TypeVisitable<DbInterner<'db>> for Ty<'db> {
748    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
749        &self,
750        visitor: &mut V,
751    ) -> V::Result {
752        visitor.visit_ty(*self)
753    }
754}
755
756impl<'db> TypeSuperVisitable<DbInterner<'db>> for Ty<'db> {
757    fn super_visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
758        &self,
759        visitor: &mut V,
760    ) -> V::Result {
761        match (*self).kind() {
762            TyKind::RawPtr(ty, _mutbl) => ty.visit_with(visitor),
763            TyKind::Array(typ, sz) => {
764                try_visit!(typ.visit_with(visitor));
765                sz.visit_with(visitor)
766            }
767            TyKind::Slice(typ) => typ.visit_with(visitor),
768            TyKind::Adt(_, args) => args.visit_with(visitor),
769            TyKind::Dynamic(ref trait_ty, ref reg) => {
770                try_visit!(trait_ty.visit_with(visitor));
771                reg.visit_with(visitor)
772            }
773            TyKind::Tuple(ts) => ts.visit_with(visitor),
774            TyKind::FnDef(_, args) => args.visit_with(visitor),
775            TyKind::FnPtr(ref sig_tys, _) => sig_tys.visit_with(visitor),
776            TyKind::UnsafeBinder(f) => f.visit_with(visitor),
777            TyKind::Ref(r, ty, _) => {
778                try_visit!(r.visit_with(visitor));
779                ty.visit_with(visitor)
780            }
781            TyKind::Coroutine(_did, ref args) => args.visit_with(visitor),
782            TyKind::CoroutineWitness(_did, ref args) => args.visit_with(visitor),
783            TyKind::Closure(_did, ref args) => args.visit_with(visitor),
784            TyKind::CoroutineClosure(_did, ref args) => args.visit_with(visitor),
785            TyKind::Alias(_, ref data) => data.visit_with(visitor),
786
787            TyKind::Pat(ty, pat) => {
788                try_visit!(ty.visit_with(visitor));
789                pat.visit_with(visitor)
790            }
791
792            TyKind::Error(guar) => guar.visit_with(visitor),
793
794            TyKind::Bool
795            | TyKind::Char
796            | TyKind::Str
797            | TyKind::Int(_)
798            | TyKind::Uint(_)
799            | TyKind::Float(_)
800            | TyKind::Infer(_)
801            | TyKind::Bound(..)
802            | TyKind::Placeholder(..)
803            | TyKind::Param(..)
804            | TyKind::Never
805            | TyKind::Foreign(..) => V::Result::output(),
806        }
807    }
808}
809
810impl<'db> TypeFoldable<DbInterner<'db>> for Ty<'db> {
811    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
812        self,
813        folder: &mut F,
814    ) -> Result<Self, F::Error> {
815        folder.try_fold_ty(self)
816    }
817    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
818        folder.fold_ty(self)
819    }
820}
821
822impl<'db> TypeSuperFoldable<DbInterner<'db>> for Ty<'db> {
823    fn try_super_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
824        self,
825        folder: &mut F,
826    ) -> Result<Self, F::Error> {
827        let kind = match self.kind() {
828            TyKind::RawPtr(ty, mutbl) => TyKind::RawPtr(ty.try_fold_with(folder)?, mutbl),
829            TyKind::Array(typ, sz) => {
830                TyKind::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?)
831            }
832            TyKind::Slice(typ) => TyKind::Slice(typ.try_fold_with(folder)?),
833            TyKind::Adt(tid, args) => TyKind::Adt(tid, args.try_fold_with(folder)?),
834            TyKind::Dynamic(trait_ty, region) => {
835                TyKind::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?)
836            }
837            TyKind::Tuple(ts) => TyKind::Tuple(ts.try_fold_with(folder)?),
838            TyKind::FnDef(def_id, args) => TyKind::FnDef(def_id, args.try_fold_with(folder)?),
839            TyKind::FnPtr(sig_tys, hdr) => TyKind::FnPtr(sig_tys.try_fold_with(folder)?, hdr),
840            TyKind::UnsafeBinder(f) => TyKind::UnsafeBinder(f.try_fold_with(folder)?),
841            TyKind::Ref(r, ty, mutbl) => {
842                TyKind::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl)
843            }
844            TyKind::Coroutine(did, args) => TyKind::Coroutine(did, args.try_fold_with(folder)?),
845            TyKind::CoroutineWitness(did, args) => {
846                TyKind::CoroutineWitness(did, args.try_fold_with(folder)?)
847            }
848            TyKind::Closure(did, args) => TyKind::Closure(did, args.try_fold_with(folder)?),
849            TyKind::CoroutineClosure(did, args) => {
850                TyKind::CoroutineClosure(did, args.try_fold_with(folder)?)
851            }
852            TyKind::Alias(kind, data) => TyKind::Alias(kind, data.try_fold_with(folder)?),
853            TyKind::Pat(ty, pat) => {
854                TyKind::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?)
855            }
856
857            TyKind::Bool
858            | TyKind::Char
859            | TyKind::Str
860            | TyKind::Int(_)
861            | TyKind::Uint(_)
862            | TyKind::Float(_)
863            | TyKind::Error(_)
864            | TyKind::Infer(_)
865            | TyKind::Param(..)
866            | TyKind::Bound(..)
867            | TyKind::Placeholder(..)
868            | TyKind::Never
869            | TyKind::Foreign(..) => return Ok(self),
870        };
871
872        Ok(if self.kind() == kind { self } else { Ty::new(folder.cx(), kind) })
873    }
874    fn super_fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
875        self,
876        folder: &mut F,
877    ) -> Self {
878        let kind = match self.kind() {
879            TyKind::RawPtr(ty, mutbl) => TyKind::RawPtr(ty.fold_with(folder), mutbl),
880            TyKind::Array(typ, sz) => TyKind::Array(typ.fold_with(folder), sz.fold_with(folder)),
881            TyKind::Slice(typ) => TyKind::Slice(typ.fold_with(folder)),
882            TyKind::Adt(tid, args) => TyKind::Adt(tid, args.fold_with(folder)),
883            TyKind::Dynamic(trait_ty, region) => {
884                TyKind::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder))
885            }
886            TyKind::Tuple(ts) => TyKind::Tuple(ts.fold_with(folder)),
887            TyKind::FnDef(def_id, args) => TyKind::FnDef(def_id, args.fold_with(folder)),
888            TyKind::FnPtr(sig_tys, hdr) => TyKind::FnPtr(sig_tys.fold_with(folder), hdr),
889            TyKind::UnsafeBinder(f) => TyKind::UnsafeBinder(f.fold_with(folder)),
890            TyKind::Ref(r, ty, mutbl) => {
891                TyKind::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl)
892            }
893            TyKind::Coroutine(did, args) => TyKind::Coroutine(did, args.fold_with(folder)),
894            TyKind::CoroutineWitness(did, args) => {
895                TyKind::CoroutineWitness(did, args.fold_with(folder))
896            }
897            TyKind::Closure(did, args) => TyKind::Closure(did, args.fold_with(folder)),
898            TyKind::CoroutineClosure(did, args) => {
899                TyKind::CoroutineClosure(did, args.fold_with(folder))
900            }
901            TyKind::Alias(kind, data) => TyKind::Alias(kind, data.fold_with(folder)),
902            TyKind::Pat(ty, pat) => TyKind::Pat(ty.fold_with(folder), pat.fold_with(folder)),
903
904            TyKind::Bool
905            | TyKind::Char
906            | TyKind::Str
907            | TyKind::Int(_)
908            | TyKind::Uint(_)
909            | TyKind::Float(_)
910            | TyKind::Error(_)
911            | TyKind::Infer(_)
912            | TyKind::Param(..)
913            | TyKind::Bound(..)
914            | TyKind::Placeholder(..)
915            | TyKind::Never
916            | TyKind::Foreign(..) => return self,
917        };
918
919        if self.kind() == kind { self } else { Ty::new(folder.cx(), kind) }
920    }
921}
922
923impl<'db> Relate<DbInterner<'db>> for Ty<'db> {
924    fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
925        relation: &mut R,
926        a: Self,
927        b: Self,
928    ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
929        relation.tys(a, b)
930    }
931}
932
933impl<'db> Flags for Ty<'db> {
934    fn flags(&self) -> rustc_type_ir::TypeFlags {
935        self.inner().flags
936    }
937
938    fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
939        self.inner().outer_exclusive_binder
940    }
941}
942
943impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> {
944    fn new_unit(interner: DbInterner<'db>) -> Self {
945        Ty::new(interner, TyKind::Tuple(Default::default()))
946    }
947
948    fn new_bool(interner: DbInterner<'db>) -> Self {
949        Ty::new(interner, TyKind::Bool)
950    }
951
952    fn new_u8(interner: DbInterner<'db>) -> Self {
953        Ty::new(interner, TyKind::Uint(rustc_type_ir::UintTy::U8))
954    }
955
956    fn new_usize(interner: DbInterner<'db>) -> Self {
957        Ty::new(interner, TyKind::Uint(rustc_type_ir::UintTy::Usize))
958    }
959
960    fn new_infer(interner: DbInterner<'db>, var: rustc_type_ir::InferTy) -> Self {
961        Ty::new(interner, TyKind::Infer(var))
962    }
963
964    fn new_var(interner: DbInterner<'db>, var: rustc_type_ir::TyVid) -> Self {
965        Ty::new(interner, TyKind::Infer(rustc_type_ir::InferTy::TyVar(var)))
966    }
967
968    fn new_param(interner: DbInterner<'db>, param: ParamTy) -> Self {
969        Ty::new(interner, TyKind::Param(param))
970    }
971
972    fn new_placeholder(interner: DbInterner<'db>, param: PlaceholderTy) -> Self {
973        Ty::new(interner, TyKind::Placeholder(param))
974    }
975
976    fn new_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundTy) -> Self {
977        Ty::new(interner, TyKind::Bound(BoundVarIndexKind::Bound(debruijn), var))
978    }
979
980    fn new_anon_bound(interner: DbInterner<'db>, debruijn: DebruijnIndex, var: BoundVar) -> Self {
981        Ty::new(
982            interner,
983            TyKind::Bound(
984                BoundVarIndexKind::Bound(debruijn),
985                BoundTy { var, kind: BoundTyKind::Anon },
986            ),
987        )
988    }
989
990    fn new_canonical_bound(interner: DbInterner<'db>, var: BoundVar) -> Self {
991        Ty::new(
992            interner,
993            TyKind::Bound(BoundVarIndexKind::Canonical, BoundTy { var, kind: BoundTyKind::Anon }),
994        )
995    }
996
997    fn new_alias(interner: DbInterner<'db>, kind: AliasTyKind, alias_ty: AliasTy<'db>) -> Self {
998        Ty::new(interner, TyKind::Alias(kind, alias_ty))
999    }
1000
1001    fn new_error(interner: DbInterner<'db>, guar: ErrorGuaranteed) -> Self {
1002        Ty::new(interner, TyKind::Error(guar))
1003    }
1004
1005    fn new_adt(
1006        interner: DbInterner<'db>,
1007        adt_def: <DbInterner<'db> as Interner>::AdtDef,
1008        args: GenericArgs<'db>,
1009    ) -> Self {
1010        Ty::new(interner, TyKind::Adt(adt_def, args))
1011    }
1012
1013    fn new_foreign(interner: DbInterner<'db>, def_id: TypeAliasIdWrapper) -> Self {
1014        Ty::new(interner, TyKind::Foreign(def_id))
1015    }
1016
1017    fn new_dynamic(
1018        interner: DbInterner<'db>,
1019        preds: <DbInterner<'db> as Interner>::BoundExistentialPredicates,
1020        region: <DbInterner<'db> as Interner>::Region,
1021    ) -> Self {
1022        Ty::new(interner, TyKind::Dynamic(preds, region))
1023    }
1024
1025    fn new_coroutine(
1026        interner: DbInterner<'db>,
1027        def_id: CoroutineIdWrapper,
1028        args: <DbInterner<'db> as Interner>::GenericArgs,
1029    ) -> Self {
1030        Ty::new(interner, TyKind::Coroutine(def_id, args))
1031    }
1032
1033    fn new_coroutine_closure(
1034        interner: DbInterner<'db>,
1035        def_id: CoroutineIdWrapper,
1036        args: <DbInterner<'db> as Interner>::GenericArgs,
1037    ) -> Self {
1038        Ty::new(interner, TyKind::CoroutineClosure(def_id, args))
1039    }
1040
1041    fn new_closure(
1042        interner: DbInterner<'db>,
1043        def_id: ClosureIdWrapper,
1044        args: <DbInterner<'db> as Interner>::GenericArgs,
1045    ) -> Self {
1046        Ty::new(interner, TyKind::Closure(def_id, args))
1047    }
1048
1049    fn new_coroutine_witness(
1050        interner: DbInterner<'db>,
1051        def_id: CoroutineIdWrapper,
1052        args: <DbInterner<'db> as Interner>::GenericArgs,
1053    ) -> Self {
1054        Ty::new(interner, TyKind::CoroutineWitness(def_id, args))
1055    }
1056
1057    fn new_coroutine_witness_for_coroutine(
1058        interner: DbInterner<'db>,
1059        def_id: CoroutineIdWrapper,
1060        coroutine_args: <DbInterner<'db> as Interner>::GenericArgs,
1061    ) -> Self {
1062        // HACK: Coroutine witness types are lifetime erased, so they
1063        // never reference any lifetime args from the coroutine. We erase
1064        // the regions here since we may get into situations where a
1065        // coroutine is recursively contained within itself, leading to
1066        // witness types that differ by region args. This means that
1067        // cycle detection in fulfillment will not kick in, which leads
1068        // to unnecessary overflows in async code. See the issue:
1069        // <https://github.com/rust-lang/rust/issues/145151>.
1070        let coroutine_args = interner.mk_args_from_iter(coroutine_args.iter().map(|arg| {
1071            match arg {
1072                GenericArg::Ty(_) | GenericArg::Const(_) => arg,
1073                GenericArg::Lifetime(_) => {
1074                    crate::next_solver::Region::new(interner, rustc_type_ir::RegionKind::ReErased)
1075                        .into()
1076                }
1077            }
1078        }));
1079        Ty::new_coroutine_witness(interner, def_id, coroutine_args)
1080    }
1081
1082    fn new_ptr(interner: DbInterner<'db>, ty: Self, mutbl: rustc_ast_ir::Mutability) -> Self {
1083        Ty::new(interner, TyKind::RawPtr(ty, mutbl))
1084    }
1085
1086    fn new_ref(
1087        interner: DbInterner<'db>,
1088        region: <DbInterner<'db> as Interner>::Region,
1089        ty: Self,
1090        mutbl: rustc_ast_ir::Mutability,
1091    ) -> Self {
1092        Ty::new(interner, TyKind::Ref(region, ty, mutbl))
1093    }
1094
1095    fn new_array_with_const_len(
1096        interner: DbInterner<'db>,
1097        ty: Self,
1098        len: <DbInterner<'db> as Interner>::Const,
1099    ) -> Self {
1100        Ty::new(interner, TyKind::Array(ty, len))
1101    }
1102
1103    fn new_slice(interner: DbInterner<'db>, ty: Self) -> Self {
1104        Ty::new(interner, TyKind::Slice(ty))
1105    }
1106
1107    fn new_tup(interner: DbInterner<'db>, tys: &[<DbInterner<'db> as Interner>::Ty]) -> Self {
1108        Ty::new(interner, TyKind::Tuple(Tys::new_from_iter(interner, tys.iter().cloned())))
1109    }
1110
1111    fn new_tup_from_iter<It, T>(interner: DbInterner<'db>, iter: It) -> T::Output
1112    where
1113        It: Iterator<Item = T>,
1114        T: rustc_type_ir::CollectAndApply<Self, Self>,
1115    {
1116        T::collect_and_apply(iter, |ts| Ty::new_tup(interner, ts))
1117    }
1118
1119    fn new_fn_def(
1120        interner: DbInterner<'db>,
1121        def_id: CallableIdWrapper,
1122        args: <DbInterner<'db> as Interner>::GenericArgs,
1123    ) -> Self {
1124        Ty::new(interner, TyKind::FnDef(def_id, args))
1125    }
1126
1127    fn new_fn_ptr(
1128        interner: DbInterner<'db>,
1129        sig: rustc_type_ir::Binder<DbInterner<'db>, rustc_type_ir::FnSig<DbInterner<'db>>>,
1130    ) -> Self {
1131        let (sig_tys, header) = sig.split();
1132        Ty::new(interner, TyKind::FnPtr(sig_tys, header))
1133    }
1134
1135    fn new_pat(
1136        interner: DbInterner<'db>,
1137        ty: Self,
1138        pat: <DbInterner<'db> as Interner>::Pat,
1139    ) -> Self {
1140        Ty::new(interner, TyKind::Pat(ty, pat))
1141    }
1142
1143    fn new_unsafe_binder(
1144        interner: DbInterner<'db>,
1145        ty: rustc_type_ir::Binder<DbInterner<'db>, <DbInterner<'db> as Interner>::Ty>,
1146    ) -> Self {
1147        Ty::new(interner, TyKind::UnsafeBinder(ty.into()))
1148    }
1149
1150    fn tuple_fields(self) -> <DbInterner<'db> as Interner>::Tys {
1151        match self.kind() {
1152            TyKind::Tuple(args) => args,
1153            _ => panic!("tuple_fields called on non-tuple: {self:?}"),
1154        }
1155    }
1156
1157    fn to_opt_closure_kind(self) -> Option<rustc_type_ir::ClosureKind> {
1158        match self.kind() {
1159            TyKind::Int(int_ty) => match int_ty {
1160                IntTy::I8 => Some(ClosureKind::Fn),
1161                IntTy::I16 => Some(ClosureKind::FnMut),
1162                IntTy::I32 => Some(ClosureKind::FnOnce),
1163                _ => unreachable!("cannot convert type `{:?}` to a closure kind", self),
1164            },
1165
1166            // "Bound" types appear in canonical queries when the
1167            // closure type is not yet known, and `Placeholder` and `Param`
1168            // may be encountered in generic `AsyncFnKindHelper` goals.
1169            TyKind::Bound(..) | TyKind::Placeholder(_) | TyKind::Param(_) | TyKind::Infer(_) => {
1170                None
1171            }
1172
1173            TyKind::Error(_) => Some(ClosureKind::Fn),
1174
1175            _ => unreachable!("cannot convert type `{:?}` to a closure kind", self),
1176        }
1177    }
1178
1179    fn from_closure_kind(interner: DbInterner<'db>, kind: rustc_type_ir::ClosureKind) -> Self {
1180        match kind {
1181            ClosureKind::Fn => Ty::new(interner, TyKind::Int(IntTy::I8)),
1182            ClosureKind::FnMut => Ty::new(interner, TyKind::Int(IntTy::I16)),
1183            ClosureKind::FnOnce => Ty::new(interner, TyKind::Int(IntTy::I32)),
1184        }
1185    }
1186
1187    fn from_coroutine_closure_kind(
1188        interner: DbInterner<'db>,
1189        kind: rustc_type_ir::ClosureKind,
1190    ) -> Self {
1191        match kind {
1192            ClosureKind::Fn | ClosureKind::FnMut => Ty::new(interner, TyKind::Int(IntTy::I16)),
1193            ClosureKind::FnOnce => Ty::new(interner, TyKind::Int(IntTy::I32)),
1194        }
1195    }
1196
1197    fn has_unsafe_fields(self) -> bool {
1198        false
1199    }
1200
1201    fn discriminant_ty(self, interner: DbInterner<'db>) -> <DbInterner<'db> as Interner>::Ty {
1202        match self.kind() {
1203            TyKind::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(interner),
1204            TyKind::Coroutine(_, args) => args.as_coroutine().discr_ty(interner),
1205
1206            TyKind::Param(_) | TyKind::Alias(..) | TyKind::Infer(InferTy::TyVar(_)) => {
1207                /*
1208                let assoc_items = tcx.associated_item_def_ids(
1209                    tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
1210                );
1211                TyKind::new_projection_from_args(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
1212                */
1213                unimplemented!()
1214            }
1215
1216            TyKind::Pat(ty, _) => ty.discriminant_ty(interner),
1217
1218            TyKind::Bool
1219            | TyKind::Char
1220            | TyKind::Int(_)
1221            | TyKind::Uint(_)
1222            | TyKind::Float(_)
1223            | TyKind::Adt(..)
1224            | TyKind::Foreign(_)
1225            | TyKind::Str
1226            | TyKind::Array(..)
1227            | TyKind::Slice(_)
1228            | TyKind::RawPtr(_, _)
1229            | TyKind::Ref(..)
1230            | TyKind::FnDef(..)
1231            | TyKind::FnPtr(..)
1232            | TyKind::Dynamic(..)
1233            | TyKind::Closure(..)
1234            | TyKind::CoroutineClosure(..)
1235            | TyKind::CoroutineWitness(..)
1236            | TyKind::Never
1237            | TyKind::Tuple(_)
1238            | TyKind::Error(_)
1239            | TyKind::Infer(InferTy::IntVar(_) | InferTy::FloatVar(_)) => {
1240                Ty::new(interner, TyKind::Uint(UintTy::U8))
1241            }
1242
1243            TyKind::Bound(..)
1244            | TyKind::Placeholder(_)
1245            | TyKind::Infer(
1246                InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_),
1247            ) => {
1248                panic!(
1249                    "`dself.iter().map(|v| v.try_fold_with(folder)).collect::<Result<_, _>>()?iscriminant_ty` applied to unexpected type: {self:?}"
1250                )
1251            }
1252            TyKind::UnsafeBinder(..) => unimplemented!(),
1253        }
1254    }
1255}
1256
1257interned_vec_db!(Tys, Ty);
1258
1259impl<'db> Tys<'db> {
1260    pub fn inputs(&self) -> &[Ty<'db>] {
1261        self.as_slice().split_last().unwrap().1
1262    }
1263}
1264
1265impl<'db> rustc_type_ir::inherent::Tys<DbInterner<'db>> for Tys<'db> {
1266    fn inputs(self) -> <DbInterner<'db> as Interner>::FnInputTys {
1267        Tys::new_from_iter(
1268            DbInterner::conjure(),
1269            self.as_slice().split_last().unwrap().1.iter().copied(),
1270        )
1271    }
1272
1273    fn output(self) -> <DbInterner<'db> as Interner>::Ty {
1274        *self.as_slice().split_last().unwrap().0
1275    }
1276}
1277
1278pub type PlaceholderTy = Placeholder<BoundTy>;
1279
1280#[derive(Copy, Clone, PartialEq, Eq, Hash)]
1281pub struct ParamTy {
1282    // FIXME: I'm not pleased with this. Ideally a `Param` should only know its index - the defining item
1283    // is known from the `EarlyBinder`. This should also be beneficial for memory usage. But code currently
1284    // assumes it can get the definition from `Param` alone - so that's what we got.
1285    pub id: TypeParamId,
1286    pub index: u32,
1287}
1288
1289impl ParamTy {
1290    pub fn to_ty<'db>(self, interner: DbInterner<'db>) -> Ty<'db> {
1291        Ty::new_param(interner, self.id, self.index)
1292    }
1293}
1294
1295impl std::fmt::Debug for ParamTy {
1296    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1297        write!(f, "#{}", self.index)
1298    }
1299}
1300
1301#[derive(Copy, Clone, PartialEq, Eq, Hash)]
1302pub struct BoundTy {
1303    pub var: BoundVar,
1304    // FIXME: This is for diagnostics in rustc, do we really need it?
1305    pub kind: BoundTyKind,
1306}
1307
1308impl std::fmt::Debug for BoundTy {
1309    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1310        match self.kind {
1311            BoundTyKind::Anon => write!(f, "{:?}", self.var),
1312            BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"),
1313        }
1314    }
1315}
1316
1317#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
1318pub enum BoundTyKind {
1319    Anon,
1320    Param(SolverDefId),
1321}
1322
1323#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
1324pub struct ErrorGuaranteed;
1325
1326impl<'db> TypeVisitable<DbInterner<'db>> for ErrorGuaranteed {
1327    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
1328        &self,
1329        visitor: &mut V,
1330    ) -> V::Result {
1331        visitor.visit_error(*self)
1332    }
1333}
1334
1335impl<'db> TypeFoldable<DbInterner<'db>> for ErrorGuaranteed {
1336    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
1337        self,
1338        _folder: &mut F,
1339    ) -> Result<Self, F::Error> {
1340        Ok(self)
1341    }
1342    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, _folder: &mut F) -> Self {
1343        self
1344    }
1345}
1346
1347impl ParamLike for ParamTy {
1348    fn index(self) -> u32 {
1349        self.index
1350    }
1351}
1352
1353impl<'db> BoundVarLike<DbInterner<'db>> for BoundTy {
1354    fn var(self) -> BoundVar {
1355        self.var
1356    }
1357
1358    fn assert_eq(self, var: BoundVarKind) {
1359        assert_eq!(self.kind, var.expect_ty())
1360    }
1361}
1362
1363impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderTy {
1364    type Bound = BoundTy;
1365
1366    fn universe(self) -> rustc_type_ir::UniverseIndex {
1367        self.universe
1368    }
1369
1370    fn var(self) -> BoundVar {
1371        self.bound.var
1372    }
1373
1374    fn with_updated_universe(self, ui: rustc_type_ir::UniverseIndex) -> Self {
1375        Placeholder { universe: ui, bound: self.bound }
1376    }
1377
1378    fn new(ui: rustc_type_ir::UniverseIndex, bound: BoundTy) -> Self {
1379        Placeholder { universe: ui, bound }
1380    }
1381
1382    fn new_anon(ui: rustc_type_ir::UniverseIndex, var: rustc_type_ir::BoundVar) -> Self {
1383        Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
1384    }
1385}