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(
627 relation.cx(),
628 std::iter::zip(a.iter(), b.iter()).map(|(a, b)| {
629 relation.relate_with_variance(
630 Variance::Invariant,
631 VarianceDiagInfo::default(),
632 a,
633 b,
634 )
635 }),
636 )
637 }
638}
639
640impl<'db> rustc_type_ir::inherent::GenericArgs<DbInterner<'db>> for GenericArgs<'db> {
641 fn as_closure(self) -> ClosureArgs<DbInterner<'db>> {
642 ClosureArgs { args: self }
643 }
644 fn as_coroutine(self) -> CoroutineArgs<DbInterner<'db>> {
645 CoroutineArgs { args: self }
646 }
647 fn as_coroutine_closure(self) -> CoroutineClosureArgs<DbInterner<'db>> {
648 CoroutineClosureArgs { args: self }
649 }
650 fn rebase_onto(
651 self,
652 interner: DbInterner<'db>,
653 source_def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
654 target: <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs,
655 ) -> <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs {
656 let defs = interner.generics_of(source_def_id);
657 interner.mk_args_from_iter(target.iter().chain(self.iter().skip(defs.count())))
658 }
659
660 fn identity_for_item(
661 interner: DbInterner<'db>,
662 def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
663 ) -> <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs {
664 Self::for_item(interner, def_id, |index, kind, _, _| mk_param(interner, index, kind))
665 }
666
667 fn extend_with_error(
668 interner: DbInterner<'db>,
669 def_id: <DbInterner<'db> as rustc_type_ir::Interner>::DefId,
670 original_args: &[<DbInterner<'db> as rustc_type_ir::Interner>::GenericArg],
671 ) -> <DbInterner<'db> as rustc_type_ir::Interner>::GenericArgs {
672 Self::for_item(interner, def_id, |index, kind, _, _| {
673 if let Some(arg) = original_args.get(index as usize) {
674 *arg
675 } else {
676 error_for_param_kind(kind, interner)
677 }
678 })
679 }
680 fn type_at(self, i: usize) -> <DbInterner<'db> as rustc_type_ir::Interner>::Ty {
681 self.get(i)
682 .and_then(|g| g.as_type())
683 .unwrap_or_else(|| Ty::new_error(DbInterner::conjure(), ErrorGuaranteed))
684 }
685
686 fn region_at(self, i: usize) -> <DbInterner<'db> as rustc_type_ir::Interner>::Region {
687 self.get(i)
688 .and_then(|g| g.as_region())
689 .unwrap_or_else(|| Region::error(DbInterner::conjure()))
690 }
691
692 fn const_at(self, i: usize) -> <DbInterner<'db> as rustc_type_ir::Interner>::Const {
693 self.get(i)
694 .and_then(|g| g.as_const())
695 .unwrap_or_else(|| Const::error(DbInterner::conjure()))
696 }
697
698 fn split_closure_args(self) -> rustc_type_ir::ClosureArgsParts<DbInterner<'db>> {
699 match self.as_slice() {
701 [parent_args @ .., closure_kind_ty, sig_ty, tupled_upvars_ty] => {
702 rustc_type_ir::ClosureArgsParts {
703 parent_args,
704 closure_sig_as_fn_ptr_ty: sig_ty.expect_ty(),
705 closure_kind_ty: closure_kind_ty.expect_ty(),
706 tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
707 }
708 }
709 _ => {
710 unreachable!("unexpected closure sig");
711 }
712 }
713 }
714
715 fn split_coroutine_closure_args(
716 self,
717 ) -> rustc_type_ir::CoroutineClosureArgsParts<DbInterner<'db>> {
718 match self.as_slice() {
719 [
720 parent_args @ ..,
721 closure_kind_ty,
722 signature_parts_ty,
723 tupled_upvars_ty,
724 coroutine_captures_by_ref_ty,
725 ] => rustc_type_ir::CoroutineClosureArgsParts {
726 parent_args,
727 closure_kind_ty: closure_kind_ty.expect_ty(),
728 signature_parts_ty: signature_parts_ty.expect_ty(),
729 tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
730 coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(),
731 },
732 _ => panic!("GenericArgs were likely not for a CoroutineClosure."),
733 }
734 }
735
736 fn split_coroutine_args(self) -> rustc_type_ir::CoroutineArgsParts<DbInterner<'db>> {
737 match self.as_slice() {
738 [parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => {
739 rustc_type_ir::CoroutineArgsParts {
740 parent_args,
741 kind_ty: kind_ty.expect_ty(),
742 resume_ty: resume_ty.expect_ty(),
743 yield_ty: yield_ty.expect_ty(),
744 return_ty: return_ty.expect_ty(),
745 tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
746 }
747 }
748 _ => panic!("GenericArgs were likely not for a Coroutine."),
749 }
750 }
751}
752
753pub fn mk_param<'db>(interner: DbInterner<'db>, index: u32, id: GenericParamId) -> GenericArg<'db> {
754 match id {
755 GenericParamId::LifetimeParamId(id) => {
756 Region::new_early_param(interner, EarlyParamRegion { index, id }).into()
757 }
758 GenericParamId::TypeParamId(id) => Ty::new_param(interner, id, index).into(),
759 GenericParamId::ConstParamId(id) => {
760 Const::new_param(interner, ParamConst { index, id }).into()
761 }
762 }
763}
764
765pub fn error_for_param_kind<'db>(id: GenericParamId, interner: DbInterner<'db>) -> GenericArg<'db> {
766 match id {
767 GenericParamId::LifetimeParamId(_) => Region::error(interner).into(),
768 GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(),
769 GenericParamId::ConstParamId(_) => Const::error(interner).into(),
770 }
771}
772
773impl<'db> IntoKind for Term<'db> {
774 type Kind = TermKind<'db>;
775
776 #[inline]
777 fn kind(self) -> Self::Kind {
778 self.ptr.term_kind()
779 }
780}
781
782impl<'db> From<Ty<'db>> for Term<'db> {
783 #[inline]
784 fn from(value: Ty<'db>) -> Self {
785 Term { ptr: GenericArgImpl::new_ty(value) }
786 }
787}
788
789impl<'db> From<Const<'db>> for Term<'db> {
790 #[inline]
791 fn from(value: Const<'db>) -> Self {
792 Term { ptr: GenericArgImpl::new_const(value) }
793 }
794}
795
796impl<'db> Relate<DbInterner<'db>> for Term<'db> {
797 fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
798 relation: &mut R,
799 a: Self,
800 b: Self,
801 ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
802 match (a.kind(), b.kind()) {
803 (TermKind::Ty(a_ty), TermKind::Ty(b_ty)) => Ok(relation.relate(a_ty, b_ty)?.into()),
804 (TermKind::Const(a_ct), TermKind::Const(b_ct)) => {
805 Ok(relation.relate(a_ct, b_ct)?.into())
806 }
807 (TermKind::Ty(unpacked), x) => {
808 unreachable!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
809 }
810 (TermKind::Const(unpacked), x) => {
811 unreachable!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
812 }
813 }
814 }
815}
816
817impl<'db> rustc_type_ir::inherent::Term<DbInterner<'db>> for Term<'db> {}
818
819#[derive(Clone, Eq, PartialEq, Debug)]
820pub enum TermVid {
821 Ty(TyVid),
822 Const(ConstVid),
823}
824
825impl From<TyVid> for TermVid {
826 fn from(value: TyVid) -> Self {
827 TermVid::Ty(value)
828 }
829}
830
831impl From<ConstVid> for TermVid {
832 fn from(value: ConstVid) -> Self {
833 TermVid::Const(value)
834 }
835}
836
837impl<'db> DbInterner<'db> {
838 pub(super) fn mk_args(self, args: &[GenericArg<'db>]) -> GenericArgs<'db> {
839 GenericArgs::new_from_slice(args)
840 }
841
842 pub(super) fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output
843 where
844 I: Iterator<Item = T>,
845 T: rustc_type_ir::CollectAndApply<GenericArg<'db>, GenericArgs<'db>>,
846 {
847 T::collect_and_apply(iter, |xs| self.mk_args(xs))
848 }
849}