1use std::{hint::unreachable_unchecked, marker::PhantomData, ptr::NonNull};
10
11use arrayvec::ArrayVec;
12use hir_def::{GenericDefId, GenericParamId, hir::generics::LifetimeParamData};
13use intern::InternedRef;
14use rustc_type_ir::{
15 ClosureArgs, ConstVid, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder,
16 GenericTypeVisitable, Interner, TyVid, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
17 Variance,
18 inherent::{GenericArg as _, GenericsOf, IntoKind, SliceLike, Term as _, Ty as _},
19 relate::{Relate, VarianceDiagInfo},
20 walk::TypeWalker,
21};
22
23use crate::next_solver::{
24 ConstInterned, RegionInterned, TyInterned, impl_foldable_for_interned_slice, interned_slice,
25};
26
27use super::{
28 Const, DbInterner, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, SolverDefId, Ty,
29 generics::Generics,
30};
31
32pub type GenericArgKind<'db> = rustc_type_ir::GenericArgKind<DbInterner<'db>>;
33pub type TermKind<'db> = rustc_type_ir::TermKind<DbInterner<'db>>;
34
35#[derive(Clone, Copy, PartialEq, Eq, Hash)]
36struct GenericArgImpl<'db> {
37 ptr: NonNull<()>,
41 _marker: PhantomData<(Ty<'db>, Const<'db>, Region<'db>)>,
42}
43
44unsafe impl Send for GenericArgImpl<'_> {}
46unsafe impl Sync for GenericArgImpl<'_> {}
47
48impl<'db> GenericArgImpl<'db> {
49 const KIND_MASK: usize = 0b11;
50 const PTR_MASK: usize = !Self::KIND_MASK;
51 const TY_TAG: usize = 0b00;
52 const CONST_TAG: usize = 0b01;
53 const REGION_TAG: usize = 0b10;
54
55 #[inline]
56 fn new_ty(ty: Ty<'db>) -> Self {
57 Self {
58 ptr: unsafe {
60 NonNull::new_unchecked(
61 ty.interned
62 .as_raw()
63 .cast::<()>()
64 .cast_mut()
65 .map_addr(|addr| addr | Self::TY_TAG),
66 )
67 },
68 _marker: PhantomData,
69 }
70 }
71
72 #[inline]
73 fn new_const(ty: Const<'db>) -> Self {
74 Self {
75 ptr: unsafe {
77 NonNull::new_unchecked(
78 ty.interned
79 .as_raw()
80 .cast::<()>()
81 .cast_mut()
82 .map_addr(|addr| addr | Self::CONST_TAG),
83 )
84 },
85 _marker: PhantomData,
86 }
87 }
88
89 #[inline]
90 fn new_region(ty: Region<'db>) -> Self {
91 Self {
92 ptr: unsafe {
94 NonNull::new_unchecked(
95 ty.interned
96 .as_raw()
97 .cast::<()>()
98 .cast_mut()
99 .map_addr(|addr| addr | Self::REGION_TAG),
100 )
101 },
102 _marker: PhantomData,
103 }
104 }
105
106 #[inline]
107 fn kind(self) -> GenericArgKind<'db> {
108 let ptr = self.ptr.as_ptr().map_addr(|addr| addr & Self::PTR_MASK);
109 unsafe {
111 match self.ptr.addr().get() & Self::KIND_MASK {
112 Self::TY_TAG => GenericArgKind::Type(Ty {
113 interned: InternedRef::from_raw(ptr.cast::<TyInterned>()),
114 }),
115 Self::CONST_TAG => GenericArgKind::Const(Const {
116 interned: InternedRef::from_raw(ptr.cast::<ConstInterned>()),
117 }),
118 Self::REGION_TAG => GenericArgKind::Lifetime(Region {
119 interned: InternedRef::from_raw(ptr.cast::<RegionInterned>()),
120 }),
121 _ => unreachable_unchecked(),
122 }
123 }
124 }
125
126 #[inline]
127 fn term_kind(self) -> TermKind<'db> {
128 let ptr = self.ptr.as_ptr().map_addr(|addr| addr & Self::PTR_MASK);
129 unsafe {
133 match self.ptr.addr().get() & Self::KIND_MASK {
134 Self::TY_TAG => {
135 TermKind::Ty(Ty { interned: InternedRef::from_raw(ptr.cast::<TyInterned>()) })
136 }
137 Self::CONST_TAG => TermKind::Const(Const {
138 interned: InternedRef::from_raw(ptr.cast::<ConstInterned>()),
139 }),
140 _ => unreachable_unchecked(),
141 }
142 }
143 }
144}
145
146#[derive(PartialEq, Eq, Hash)]
147pub struct StoredGenericArg {
148 ptr: GenericArgImpl<'static>,
149}
150
151impl Clone for StoredGenericArg {
152 #[inline]
153 fn clone(&self) -> Self {
154 match self.ptr.kind() {
155 GenericArgKind::Lifetime(it) => std::mem::forget(it.interned.to_owned()),
156 GenericArgKind::Type(it) => std::mem::forget(it.interned.to_owned()),
157 GenericArgKind::Const(it) => std::mem::forget(it.interned.to_owned()),
158 }
159 Self { ptr: self.ptr }
160 }
161}
162
163impl Drop for StoredGenericArg {
164 #[inline]
165 fn drop(&mut self) {
166 unsafe {
167 match self.ptr.kind() {
168 GenericArgKind::Lifetime(it) => it.interned.decrement_refcount(),
169 GenericArgKind::Type(it) => it.interned.decrement_refcount(),
170 GenericArgKind::Const(it) => it.interned.decrement_refcount(),
171 }
172 }
173 }
174}
175
176impl StoredGenericArg {
177 #[inline]
178 fn new(value: GenericArg<'_>) -> Self {
179 let result = Self { ptr: GenericArgImpl { ptr: value.ptr.ptr, _marker: PhantomData } };
180 std::mem::forget(result.clone());
182 result
183 }
184
185 #[inline]
186 pub fn as_ref<'db>(&self) -> GenericArg<'db> {
187 GenericArg { ptr: self.ptr }
188 }
189}
190
191impl std::fmt::Debug for StoredGenericArg {
192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193 self.as_ref().fmt(f)
194 }
195}
196
197impl<'db> TypeVisitable<DbInterner<'db>> for StoredGenericArg {
198 fn visit_with<V: TypeVisitor<DbInterner<'db>>>(&self, visitor: &mut V) -> V::Result {
199 self.as_ref().visit_with(visitor)
200 }
201}
202
203impl<'db> TypeFoldable<DbInterner<'db>> for StoredGenericArg {
204 fn try_fold_with<F: FallibleTypeFolder<DbInterner<'db>>>(
205 self,
206 folder: &mut F,
207 ) -> Result<Self, F::Error> {
208 Ok(self.as_ref().try_fold_with(folder)?.store())
209 }
210
211 fn fold_with<F: TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
212 self.as_ref().fold_with(folder).store()
213 }
214}
215
216#[derive(Copy, Clone, PartialEq, Eq, Hash)]
217pub struct GenericArg<'db> {
218 ptr: GenericArgImpl<'db>,
219}
220
221impl<'db> std::fmt::Debug for GenericArg<'db> {
222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223 match self.kind() {
224 GenericArgKind::Type(t) => std::fmt::Debug::fmt(&t, f),
225 GenericArgKind::Lifetime(r) => std::fmt::Debug::fmt(&r, f),
226 GenericArgKind::Const(c) => std::fmt::Debug::fmt(&c, f),
227 }
228 }
229}
230
231impl<'db> GenericArg<'db> {
232 #[inline]
233 pub fn store(self) -> StoredGenericArg {
234 StoredGenericArg::new(self)
235 }
236
237 #[inline]
238 pub fn kind(self) -> GenericArgKind<'db> {
239 self.ptr.kind()
240 }
241
242 pub fn ty(self) -> Option<Ty<'db>> {
243 match self.kind() {
244 GenericArgKind::Type(ty) => Some(ty),
245 _ => None,
246 }
247 }
248
249 pub fn expect_ty(self) -> Ty<'db> {
250 match self.kind() {
251 GenericArgKind::Type(ty) => ty,
252 _ => panic!("Expected ty, got {self:?}"),
253 }
254 }
255
256 pub fn konst(self) -> Option<Const<'db>> {
257 match self.kind() {
258 GenericArgKind::Const(konst) => Some(konst),
259 _ => None,
260 }
261 }
262
263 pub fn region(self) -> Option<Region<'db>> {
264 match self.kind() {
265 GenericArgKind::Lifetime(r) => Some(r),
266 _ => None,
267 }
268 }
269
270 #[inline]
271 pub(crate) fn expect_region(self) -> Region<'db> {
272 match self.kind() {
273 GenericArgKind::Lifetime(region) => region,
274 _ => panic!("expected a region, got {self:?}"),
275 }
276 }
277
278 pub fn error_from_id(interner: DbInterner<'db>, id: GenericParamId) -> GenericArg<'db> {
279 match id {
280 GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(),
281 GenericParamId::ConstParamId(_) => Const::error(interner).into(),
282 GenericParamId::LifetimeParamId(_) => Region::error(interner).into(),
283 }
284 }
285
286 #[inline]
287 pub fn walk(self) -> TypeWalker<DbInterner<'db>> {
288 TypeWalker::new(self)
289 }
290}
291
292impl<'db> From<Term<'db>> for GenericArg<'db> {
293 #[inline]
294 fn from(value: Term<'db>) -> Self {
295 GenericArg { ptr: value.ptr }
296 }
297}
298
299#[derive(Copy, Clone, PartialEq, Eq, Hash)]
300pub struct Term<'db> {
301 ptr: GenericArgImpl<'db>,
302}
303
304impl<'db> std::fmt::Debug for Term<'db> {
305 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
306 match self.kind() {
307 TermKind::Ty(t) => std::fmt::Debug::fmt(&t, f),
308 TermKind::Const(c) => std::fmt::Debug::fmt(&c, f),
309 }
310 }
311}
312
313impl<'db> Term<'db> {
314 #[inline]
315 pub fn kind(self) -> TermKind<'db> {
316 self.ptr.term_kind()
317 }
318
319 pub fn expect_type(&self) -> Ty<'db> {
320 self.as_type().expect("expected a type, but found a const")
321 }
322
323 pub fn is_trivially_wf(&self, tcx: DbInterner<'db>) -> bool {
324 match self.kind() {
325 TermKind::Ty(ty) => ty.is_trivially_wf(tcx),
326 TermKind::Const(ct) => ct.is_trivially_wf(),
327 }
328 }
329}
330
331impl<'db> From<Ty<'db>> for GenericArg<'db> {
332 #[inline]
333 fn from(value: Ty<'db>) -> Self {
334 GenericArg { ptr: GenericArgImpl::new_ty(value) }
335 }
336}
337
338impl<'db> From<Region<'db>> for GenericArg<'db> {
339 #[inline]
340 fn from(value: Region<'db>) -> Self {
341 GenericArg { ptr: GenericArgImpl::new_region(value) }
342 }
343}
344
345impl<'db> From<Const<'db>> for GenericArg<'db> {
346 #[inline]
347 fn from(value: Const<'db>) -> Self {
348 GenericArg { ptr: GenericArgImpl::new_const(value) }
349 }
350}
351
352impl<'db> IntoKind for GenericArg<'db> {
353 type Kind = GenericArgKind<'db>;
354
355 #[inline]
356 fn kind(self) -> Self::Kind {
357 self.ptr.kind()
358 }
359}
360
361impl<'db, V> GenericTypeVisitable<V> for GenericArg<'db>
362where
363 GenericArgKind<'db>: GenericTypeVisitable<V>,
364{
365 fn generic_visit_with(&self, visitor: &mut V) {
366 self.kind().generic_visit_with(visitor);
367 }
368}
369
370impl<'db, V> GenericTypeVisitable<V> for Term<'db>
371where
372 TermKind<'db>: GenericTypeVisitable<V>,
373{
374 fn generic_visit_with(&self, visitor: &mut V) {
375 self.kind().generic_visit_with(visitor);
376 }
377}
378
379impl<'db> TypeVisitable<DbInterner<'db>> for GenericArg<'db> {
380 fn visit_with<V: TypeVisitor<DbInterner<'db>>>(&self, visitor: &mut V) -> V::Result {
381 match self.kind() {
382 GenericArgKind::Lifetime(it) => it.visit_with(visitor),
383 GenericArgKind::Type(it) => it.visit_with(visitor),
384 GenericArgKind::Const(it) => it.visit_with(visitor),
385 }
386 }
387}
388
389impl<'db> TypeVisitable<DbInterner<'db>> for Term<'db> {
390 fn visit_with<V: TypeVisitor<DbInterner<'db>>>(&self, visitor: &mut V) -> V::Result {
391 match self.kind() {
392 TermKind::Ty(it) => it.visit_with(visitor),
393 TermKind::Const(it) => it.visit_with(visitor),
394 }
395 }
396}
397
398impl<'db> TypeFoldable<DbInterner<'db>> for GenericArg<'db> {
399 fn try_fold_with<F: FallibleTypeFolder<DbInterner<'db>>>(
400 self,
401 folder: &mut F,
402 ) -> Result<Self, F::Error> {
403 Ok(match self.kind() {
404 GenericArgKind::Lifetime(it) => it.try_fold_with(folder)?.into(),
405 GenericArgKind::Type(it) => it.try_fold_with(folder)?.into(),
406 GenericArgKind::Const(it) => it.try_fold_with(folder)?.into(),
407 })
408 }
409
410 fn fold_with<F: TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
411 match self.kind() {
412 GenericArgKind::Lifetime(it) => it.fold_with(folder).into(),
413 GenericArgKind::Type(it) => it.fold_with(folder).into(),
414 GenericArgKind::Const(it) => it.fold_with(folder).into(),
415 }
416 }
417}
418
419impl<'db> TypeFoldable<DbInterner<'db>> for Term<'db> {
420 fn try_fold_with<F: FallibleTypeFolder<DbInterner<'db>>>(
421 self,
422 folder: &mut F,
423 ) -> Result<Self, F::Error> {
424 Ok(match self.kind() {
425 TermKind::Ty(it) => it.try_fold_with(folder)?.into(),
426 TermKind::Const(it) => it.try_fold_with(folder)?.into(),
427 })
428 }
429
430 fn fold_with<F: TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
431 match self.kind() {
432 TermKind::Ty(it) => it.fold_with(folder).into(),
433 TermKind::Const(it) => it.fold_with(folder).into(),
434 }
435 }
436}
437
438impl<'db> Relate<DbInterner<'db>> for GenericArg<'db> {
439 fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
440 relation: &mut R,
441 a: Self,
442 b: Self,
443 ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
444 match (a.kind(), b.kind()) {
445 (GenericArgKind::Lifetime(a_lt), GenericArgKind::Lifetime(b_lt)) => {
446 Ok(relation.relate(a_lt, b_lt)?.into())
447 }
448 (GenericArgKind::Type(a_ty), GenericArgKind::Type(b_ty)) => {
449 Ok(relation.relate(a_ty, b_ty)?.into())
450 }
451 (GenericArgKind::Const(a_ct), GenericArgKind::Const(b_ct)) => {
452 Ok(relation.relate(a_ct, b_ct)?.into())
453 }
454 (GenericArgKind::Lifetime(unpacked), x) => {
455 unreachable!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
456 }
457 (GenericArgKind::Type(unpacked), x) => {
458 unreachable!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
459 }
460 (GenericArgKind::Const(unpacked), x) => {
461 unreachable!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
462 }
463 }
464 }
465}
466
467interned_slice!(
468 GenericArgsStorage,
469 GenericArgs,
470 StoredGenericArgs,
471 generic_args,
472 GenericArg<'db>,
473 GenericArg<'static>,
474);
475impl_foldable_for_interned_slice!(GenericArgs);
476
477impl<'db> rustc_type_ir::inherent::GenericArg<DbInterner<'db>> for GenericArg<'db> {}
478
479impl<'db> TypeVisitable<DbInterner<'db>> for StoredGenericArgs {
480 fn visit_with<V: TypeVisitor<DbInterner<'db>>>(&self, visitor: &mut V) -> V::Result {
481 self.as_ref().visit_with(visitor)
482 }
483}
484
485impl<'db> TypeFoldable<DbInterner<'db>> for StoredGenericArgs {
486 fn try_fold_with<F: FallibleTypeFolder<DbInterner<'db>>>(
487 self,
488 folder: &mut F,
489 ) -> Result<Self, F::Error> {
490 Ok(self.as_ref().try_fold_with(folder)?.store())
491 }
492
493 fn fold_with<F: TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
494 self.as_ref().fold_with(folder).store()
495 }
496}
497
498trait GenericArgsBuilder<'db>: AsRef<[GenericArg<'db>]> {
499 fn push(&mut self, arg: GenericArg<'db>);
500}
501
502impl<'db, const N: usize> GenericArgsBuilder<'db> for ArrayVec<GenericArg<'db>, N> {
503 fn push(&mut self, arg: GenericArg<'db>) {
504 self.push(arg);
505 }
506}
507
508impl<'db> GenericArgsBuilder<'db> for Vec<GenericArg<'db>> {
509 fn push(&mut self, arg: GenericArg<'db>) {
510 self.push(arg);
511 }
512}
513
514impl<'db> GenericArgs<'db> {
515 #[inline(always)]
516 fn fill_builder<F>(
517 args: &mut impl GenericArgsBuilder<'db>,
518 defs: &Generics<'db>,
519 mut mk_kind: F,
520 ) where
521 F: FnMut(
522 u32,
523 GenericParamId,
524 Option<&LifetimeParamData>,
525 &[GenericArg<'db>],
526 ) -> GenericArg<'db>,
527 {
528 defs.iter().enumerate().for_each(|(idx, (param, lt_data))| {
529 let new_arg = mk_kind(idx as u32, param, lt_data, args.as_ref());
530 args.push(new_arg);
531 });
532 }
533
534 #[cold]
535 fn fill_vec_builder<F>(defs: &Generics<'db>, count: usize, mk_kind: F) -> GenericArgs<'db>
536 where
537 F: FnMut(
538 u32,
539 GenericParamId,
540 Option<&LifetimeParamData>,
541 &[GenericArg<'db>],
542 ) -> GenericArg<'db>,
543 {
544 let mut args = Vec::with_capacity(count);
545 Self::fill_builder(&mut args, defs, mk_kind);
546 GenericArgs::new_from_slice(&args)
547 }
548
549 pub fn for_item<F>(
555 interner: DbInterner<'db>,
556 def_id: SolverDefId<'db>,
557 mk_kind: F,
558 ) -> GenericArgs<'db>
559 where
560 F: FnMut(
561 u32,
562 GenericParamId,
563 Option<&LifetimeParamData>,
564 &[GenericArg<'db>],
565 ) -> GenericArg<'db>,
566 {
567 let defs = interner.generics_of(def_id);
568 let count = defs.count();
569
570 if count == 0 {
571 GenericArgs::default()
572 } else if count <= 10 {
573 let mut args = ArrayVec::<_, 10>::new();
574 Self::fill_builder(&mut args, &defs, mk_kind);
575 GenericArgs::new_from_slice(&args)
576 } else {
577 Self::fill_vec_builder(&defs, count, mk_kind)
578 }
579 }
580
581 pub fn error_for_item(interner: DbInterner<'db>, def_id: SolverDefId<'db>) -> GenericArgs<'db> {
583 GenericArgs::for_item(interner, def_id, |_, id, _, _| {
584 GenericArg::error_from_id(interner, id)
585 })
586 }
587
588 pub fn for_item_with_defaults<F>(
590 interner: DbInterner<'db>,
591 def_id: GenericDefId,
592 mut fallback: F,
593 ) -> GenericArgs<'db>
594 where
595 F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
596 {
597 let defaults = interner.db.generic_defaults(def_id);
598 Self::for_item(interner, def_id.into(), |idx, id, _, prev| {
599 match defaults.get(idx as usize) {
600 Some(default) => default.instantiate(interner, prev).skip_norm_wip(),
601 None => fallback(idx, id, prev),
602 }
603 })
604 }
605
606 pub fn fill_rest<F>(
608 interner: DbInterner<'db>,
609 def_id: SolverDefId<'db>,
610 first: impl IntoIterator<Item = GenericArg<'db>>,
611 mut fallback: F,
612 ) -> GenericArgs<'db>
613 where
614 F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
615 {
616 let mut iter = first.into_iter();
617 Self::for_item(interner, def_id, |idx, id, _, prev| {
618 iter.next().unwrap_or_else(|| fallback(idx, id, prev))
619 })
620 }
621
622 pub fn fill_with_defaults<F>(
624 interner: DbInterner<'db>,
625 def_id: GenericDefId,
626 first: impl IntoIterator<Item = GenericArg<'db>>,
627 mut fallback: F,
628 ) -> GenericArgs<'db>
629 where
630 F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
631 {
632 let defaults = interner.db.generic_defaults(def_id);
633 Self::fill_rest(interner, def_id.into(), first, |idx, id, prev| {
634 defaults
635 .get(idx as usize)
636 .map(|default| default.instantiate(interner, prev).skip_norm_wip())
637 .unwrap_or_else(|| fallback(idx, id, prev))
638 })
639 }
640
641 pub fn types(self) -> impl Iterator<Item = Ty<'db>> {
642 self.iter().filter_map(|it| it.as_type())
643 }
644
645 pub fn consts(self) -> impl Iterator<Item = Const<'db>> {
646 self.iter().filter_map(|it| it.as_const())
647 }
648
649 pub fn regions(self) -> impl Iterator<Item = Region<'db>> {
650 self.iter().filter_map(|it| it.as_region())
651 }
652}
653
654impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for GenericArgs<'db> {
655 fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
656 relation: &mut R,
657 a: Self,
658 b: Self,
659 ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
660 GenericArgs::new_from_iter(
661 relation.cx(),
662 std::iter::zip(a.iter(), b.iter()).map(|(a, b)| {
663 relation.relate_with_variance(
664 Variance::Invariant,
665 VarianceDiagInfo::default(),
666 a,
667 b,
668 )
669 }),
670 )
671 }
672}
673
674impl<'db> rustc_type_ir::inherent::GenericArgs<DbInterner<'db>> for GenericArgs<'db> {
675 fn as_closure(self) -> ClosureArgs<DbInterner<'db>> {
676 ClosureArgs { args: self }
677 }
678 fn as_coroutine(self) -> CoroutineArgs<DbInterner<'db>> {
679 CoroutineArgs { args: self }
680 }
681 fn as_coroutine_closure(self) -> CoroutineClosureArgs<DbInterner<'db>> {
682 CoroutineClosureArgs { args: self }
683 }
684 fn rebase_onto(
685 self,
686 interner: DbInterner<'db>,
687 source_def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
688 target: <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs,
689 ) -> <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs {
690 let defs = interner.generics_of(source_def_id);
691 interner.mk_args_from_iter(target.iter().chain(self.iter().skip(defs.count())))
692 }
693
694 fn identity_for_item(
695 interner: DbInterner<'db>,
696 def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
697 ) -> <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs {
698 Self::for_item(interner, def_id, |index, kind, _, _| mk_param(interner, index, kind))
699 }
700
701 fn extend_with_error(
702 interner: DbInterner<'db>,
703 def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
704 original_args: &[<DbInterner<'db> as rustc_type_ir::Interner>::GenericArg],
705 ) -> <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs {
706 Self::for_item(interner, def_id, |index, kind, _, _| {
707 if let Some(arg) = original_args.get(index as usize) {
708 *arg
709 } else {
710 error_for_param_kind(kind, interner)
711 }
712 })
713 }
714 fn type_at(self, i: usize) -> <DbInterner<'db> as rustc_type_ir::Interner>::Ty {
715 self.get(i)
716 .and_then(|g| g.as_type())
717 .unwrap_or_else(|| Ty::new_error(DbInterner::conjure(), ErrorGuaranteed))
718 }
719
720 fn region_at(self, i: usize) -> <DbInterner<'db> as rustc_type_ir::Interner>::Region {
721 self.get(i)
722 .and_then(|g| g.as_region())
723 .unwrap_or_else(|| Region::error(DbInterner::conjure()))
724 }
725
726 fn const_at(self, i: usize) -> <DbInterner<'db> as rustc_type_ir::Interner>::Const {
727 self.get(i)
728 .and_then(|g| g.as_const())
729 .unwrap_or_else(|| Const::error(DbInterner::conjure()))
730 }
731
732 fn split_closure_args(self) -> rustc_type_ir::ClosureArgsParts<DbInterner<'db>> {
733 match self.as_slice() {
735 [parent_args @ .., closure_kind_ty, sig_ty, tupled_upvars_ty] => {
736 rustc_type_ir::ClosureArgsParts {
737 parent_args,
738 closure_sig_as_fn_ptr_ty: sig_ty.expect_ty(),
739 closure_kind_ty: closure_kind_ty.expect_ty(),
740 tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
741 }
742 }
743 _ => {
744 unreachable!("unexpected closure sig");
745 }
746 }
747 }
748
749 fn split_coroutine_closure_args(
750 self,
751 ) -> rustc_type_ir::CoroutineClosureArgsParts<DbInterner<'db>> {
752 match self.as_slice() {
753 [
754 parent_args @ ..,
755 closure_kind_ty,
756 signature_parts_ty,
757 tupled_upvars_ty,
758 coroutine_captures_by_ref_ty,
759 ] => rustc_type_ir::CoroutineClosureArgsParts {
760 parent_args,
761 closure_kind_ty: closure_kind_ty.expect_ty(),
762 signature_parts_ty: signature_parts_ty.expect_ty(),
763 tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
764 coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(),
765 },
766 _ => panic!("GenericArgs were likely not for a CoroutineClosure."),
767 }
768 }
769
770 fn split_coroutine_args(self) -> rustc_type_ir::CoroutineArgsParts<DbInterner<'db>> {
771 match self.as_slice() {
772 [parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => {
773 rustc_type_ir::CoroutineArgsParts {
774 parent_args,
775 kind_ty: kind_ty.expect_ty(),
776 resume_ty: resume_ty.expect_ty(),
777 yield_ty: yield_ty.expect_ty(),
778 return_ty: return_ty.expect_ty(),
779 tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
780 }
781 }
782 _ => panic!("GenericArgs were likely not for a Coroutine."),
783 }
784 }
785}
786
787pub fn mk_param<'db>(interner: DbInterner<'db>, index: u32, id: GenericParamId) -> GenericArg<'db> {
788 match id {
789 GenericParamId::LifetimeParamId(id) => {
790 Region::new_early_param(interner, EarlyParamRegion { index, id }).into()
791 }
792 GenericParamId::TypeParamId(id) => Ty::new_param(interner, id, index).into(),
793 GenericParamId::ConstParamId(id) => {
794 Const::new_param(interner, ParamConst { index, id }).into()
795 }
796 }
797}
798
799pub fn error_for_param_kind<'db>(id: GenericParamId, interner: DbInterner<'db>) -> GenericArg<'db> {
800 match id {
801 GenericParamId::LifetimeParamId(_) => Region::error(interner).into(),
802 GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(),
803 GenericParamId::ConstParamId(_) => Const::error(interner).into(),
804 }
805}
806
807impl<'db> IntoKind for Term<'db> {
808 type Kind = TermKind<'db>;
809
810 #[inline]
811 fn kind(self) -> Self::Kind {
812 self.ptr.term_kind()
813 }
814}
815
816impl<'db> From<Ty<'db>> for Term<'db> {
817 #[inline]
818 fn from(value: Ty<'db>) -> Self {
819 Term { ptr: GenericArgImpl::new_ty(value) }
820 }
821}
822
823impl<'db> From<Const<'db>> for Term<'db> {
824 #[inline]
825 fn from(value: Const<'db>) -> Self {
826 Term { ptr: GenericArgImpl::new_const(value) }
827 }
828}
829
830impl<'db> Relate<DbInterner<'db>> for Term<'db> {
831 fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
832 relation: &mut R,
833 a: Self,
834 b: Self,
835 ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
836 match (a.kind(), b.kind()) {
837 (TermKind::Ty(a_ty), TermKind::Ty(b_ty)) => Ok(relation.relate(a_ty, b_ty)?.into()),
838 (TermKind::Const(a_ct), TermKind::Const(b_ct)) => {
839 Ok(relation.relate(a_ct, b_ct)?.into())
840 }
841 (TermKind::Ty(unpacked), x) => {
842 unreachable!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
843 }
844 (TermKind::Const(unpacked), x) => {
845 unreachable!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
846 }
847 }
848 }
849}
850
851impl<'db> rustc_type_ir::inherent::Term<DbInterner<'db>> for Term<'db> {}
852
853#[derive(Clone, Eq, PartialEq, Debug)]
854pub enum TermVid {
855 Ty(TyVid),
856 Const(ConstVid),
857}
858
859impl From<TyVid> for TermVid {
860 fn from(value: TyVid) -> Self {
861 TermVid::Ty(value)
862 }
863}
864
865impl From<ConstVid> for TermVid {
866 fn from(value: ConstVid) -> Self {
867 TermVid::Const(value)
868 }
869}
870
871impl<'db> DbInterner<'db> {
872 pub(super) fn mk_args(self, args: &[GenericArg<'db>]) -> GenericArgs<'db> {
873 GenericArgs::new_from_slice(args)
874 }
875
876 pub(super) fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output
877 where
878 I: Iterator<Item = T>,
879 T: rustc_type_ir::CollectAndApply<GenericArg<'db>, GenericArgs<'db>>,
880 {
881 T::collect_and_apply(iter, |xs| self.mk_args(xs))
882 }
883}