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