1use 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 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 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 #[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 pub fn is_trivially_pure_clone_copy(self) -> bool {
212 match self.kind() {
213 TyKind::Bool | TyKind::Char | TyKind::Never => true,
214
215 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 TyKind::FnDef(..) => true,
225
226 TyKind::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(),
227
228 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 TyKind::FnPtr(..) => false,
238
239 TyKind::Ref(_, _, Mutability::Mut) => false,
241
242 TyKind::Ref(_, _, Mutability::Not) | TyKind::RawPtr(..) => true,
245
246 TyKind::Coroutine(..) | TyKind::CoroutineWitness(..) => false,
247
248 TyKind::Adt(..) | TyKind::Closure(..) | TyKind::CoroutineClosure(..) => false,
250
251 TyKind::UnsafeBinder(_) => false,
252
253 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 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 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 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 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}