1mod subst;
4
5use std::fmt;
6
7pub use flux_arc_interner::List;
8use flux_arc_interner::{Interned, impl_internable, impl_slice_internable};
9use flux_common::{bug, tracked_span_assert_eq, tracked_span_bug};
10use itertools::Itertools;
11use rustc_abi;
12pub use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
13use rustc_hir::{Safety, def_id::DefId};
14use rustc_index::{IndexSlice, IndexVec};
15use rustc_macros::{TyDecodable, TyEncodable, extension};
16pub use rustc_middle::{
17 mir::Mutability,
18 ty::{
19 BoundRegionKind, BoundVar, ConstVid, DebruijnIndex, EarlyParamRegion, FloatTy, IntTy,
20 LateParamRegion, LateParamRegionKind, ParamTy, RegionVid, ScalarInt, UintTy,
21 },
22};
23use rustc_middle::{
24 mir::Promoted,
25 ty::{self as rustc_ty, AdtFlags, ParamConst, TyCtxt},
26};
27use rustc_span::Symbol;
28pub use rustc_type_ir::InferConst;
29
30use self::subst::Subst;
31use super::ToRustc;
32use crate::def_id_to_string;
33
34#[derive(Debug, Clone)]
35pub struct Generics<'tcx> {
36 pub params: List<GenericParamDef>,
37 pub orig: &'tcx rustc_middle::ty::Generics,
38}
39
40#[derive(Clone)]
41pub struct EarlyBinder<T>(pub T);
42
43#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
44pub struct Binder<T>(T, List<BoundVariableKind>);
45
46#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
47pub enum BoundVariableKind {
48 Region(BoundRegionKind),
49}
50
51impl BoundVariableKind {
52 fn to_rustc<'tcx>(
55 vars: &[Self],
56 tcx: TyCtxt<'tcx>,
57 ) -> &'tcx rustc_middle::ty::List<rustc_middle::ty::BoundVariableKind> {
58 tcx.mk_bound_variable_kinds_from_iter(vars.iter().flat_map(|kind| {
59 match kind {
60 BoundVariableKind::Region(brk) => {
61 Some(rustc_middle::ty::BoundVariableKind::Region(*brk))
62 }
63 }
64 }))
65 }
66}
67
68#[derive(Debug, Hash, Eq, PartialEq, TyEncodable, TyDecodable)]
69pub struct GenericParamDef {
70 pub def_id: DefId,
71 pub index: u32,
72 pub name: Symbol,
73 pub kind: GenericParamDefKind,
74}
75
76#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy, TyEncodable, TyDecodable)]
77pub enum GenericParamDefKind {
78 Type { has_default: bool },
79 Lifetime,
80 Const { has_default: bool },
81}
82
83#[derive(Clone, Debug)]
84pub struct GenericPredicates {
85 pub parent: Option<DefId>,
86 pub predicates: List<Clause>,
87}
88
89#[derive(PartialEq, Eq, Hash, Debug)]
90pub struct Clause {
91 pub kind: Binder<ClauseKind>,
92}
93
94#[derive(PartialEq, Eq, Hash, Debug)]
95pub enum ClauseKind {
96 Trait(TraitPredicate),
97 Projection(ProjectionPredicate),
98 RegionOutlives(RegionOutlivesPredicate),
99 TypeOutlives(TypeOutlivesPredicate),
100 ConstArgHasType(Const, Ty),
101 UnstableFeature(Symbol),
102}
103
104#[derive(Eq, PartialEq, Hash, Clone, Debug, TyEncodable, TyDecodable)]
105pub struct OutlivesPredicate<T>(pub T, pub Region);
106
107pub type TypeOutlivesPredicate = OutlivesPredicate<Ty>;
108pub type RegionOutlivesPredicate = OutlivesPredicate<Region>;
109
110#[derive(PartialEq, Eq, Hash, Debug)]
111pub struct TraitPredicate {
112 pub trait_ref: TraitRef,
113}
114
115#[derive(PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
116pub struct TraitRef {
117 pub def_id: DefId,
118 pub args: GenericArgs,
119}
120
121impl TraitRef {
122 pub fn self_ty(&self) -> &Ty {
123 self.args[0].expect_type()
124 }
125}
126
127pub type PolyTraitRef = Binder<TraitRef>;
128
129#[derive(PartialEq, Eq, Hash, Debug)]
130pub struct ProjectionPredicate {
131 pub projection_ty: AliasTy,
132 pub term: Ty,
133}
134#[derive(Clone, Hash, PartialEq, Eq, TyEncodable, TyDecodable)]
135pub struct FnSig {
136 pub safety: Safety,
137 pub abi: rustc_abi::ExternAbi,
138 pub(crate) inputs_and_output: List<Ty>,
139}
140
141pub type PolyFnSig = Binder<FnSig>;
142
143impl PolyFnSig {
144 pub fn unpack_closure_sig(&self) -> Self {
145 let vars = self.vars().clone();
146 let fn_sig = self.skip_binder_ref();
147 let [input] = &fn_sig.inputs() else {
148 bug!("closure signature should have at least two values");
149 };
150 let fn_sig = FnSig {
151 safety: fn_sig.safety,
152 abi: fn_sig.abi,
153 inputs_and_output: input
154 .tuple_fields()
155 .iter()
156 .cloned()
157 .chain([fn_sig.output().clone()])
158 .collect(),
159 };
160 Binder::bind_with_vars(fn_sig, vars)
161 }
162}
163
164#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
165pub struct Ty(Interned<TyS>);
166
167#[derive(Debug, Eq, PartialEq, Hash, Clone, TyEncodable, TyDecodable)]
168pub struct AdtDef(Interned<AdtDefData>);
169
170#[derive(Debug, TyEncodable, TyDecodable)]
171pub struct AdtDefData {
172 pub did: DefId,
173 variants: IndexVec<VariantIdx, VariantDef>,
174 discrs: IndexVec<VariantIdx, u128>,
175 flags: AdtFlags,
176}
177
178impl std::hash::Hash for AdtDefData {
181 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
182 self.did.hash(state);
183 }
184}
185
186impl PartialEq for AdtDefData {
189 fn eq(&self, other: &Self) -> bool {
190 self.did == other.did
191 }
192}
193
194impl Eq for AdtDefData {}
195
196#[derive(Debug, TyEncodable, TyDecodable)]
197pub struct VariantDef {
198 pub def_id: DefId,
199 pub name: Symbol,
200 pub fields: IndexVec<FieldIdx, FieldDef>,
201}
202
203#[derive(Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
204pub struct FieldDef {
205 pub did: DefId,
206 pub name: Symbol,
207}
208
209#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
210struct TyS {
211 kind: TyKind,
212}
213
214#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
215pub enum TyKind {
216 Adt(AdtDef, GenericArgs),
217 Array(Ty, Const),
218 Bool,
219 Str,
220 Char,
221 Float(FloatTy),
222 Int(IntTy),
223 Never,
224 Param(ParamTy),
225 Ref(Region, Ty, Mutability),
226 Tuple(List<Ty>),
227 Uint(UintTy),
228 Slice(Ty),
229 FnPtr(PolyFnSig),
230 FnDef(DefId, GenericArgs),
231 Closure(DefId, GenericArgs),
232 Coroutine(DefId, GenericArgs),
233 CoroutineWitness(DefId, GenericArgs),
234 Alias(AliasKind, AliasTy),
235 RawPtr(Ty, Mutability),
236 Dynamic(List<Binder<ExistentialPredicate>>, Region),
237 Foreign(DefId),
238 Pat,
239}
240
241#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
242pub enum ExistentialPredicate {
243 Trait(ExistentialTraitRef),
244 Projection(ExistentialProjection),
245 AutoTrait(DefId),
246}
247
248pub type PolyExistentialPredicate = Binder<ExistentialPredicate>;
249
250#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
251pub struct ExistentialTraitRef {
252 pub def_id: DefId,
253 pub args: GenericArgs,
254}
255
256#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
257pub struct ExistentialProjection {
258 pub def_id: DefId,
259 pub args: GenericArgs,
260 pub term: Ty,
261}
262
263#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
264pub struct AliasTy {
265 pub args: GenericArgs,
266 pub def_id: DefId,
267}
268
269#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
270pub enum AliasKind {
271 Projection,
272 Opaque,
273 Free,
274}
275
276impl<'tcx> ToRustc<'tcx> for AliasKind {
277 type T = rustc_middle::ty::AliasTyKind;
278
279 fn to_rustc(&self, _tcx: TyCtxt<'tcx>) -> Self::T {
280 use rustc_middle::ty;
281 match self {
282 AliasKind::Opaque => ty::AliasTyKind::Opaque,
283 AliasKind::Projection => ty::AliasTyKind::Projection,
284 AliasKind::Free => ty::AliasTyKind::Free,
285 }
286 }
287}
288
289#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
290pub struct Const {
291 pub kind: ConstKind,
292}
293
294impl<'tcx> ToRustc<'tcx> for UnevaluatedConst {
295 type T = rustc_middle::ty::UnevaluatedConst<'tcx>;
296
297 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
298 let args = tcx.mk_args_from_iter(self.args.iter().map(|arg| arg.to_rustc(tcx)));
299 rustc_ty::UnevaluatedConst::new(self.def, args)
300 }
301}
302
303impl Const {
304 pub fn from_usize(tcx: TyCtxt, v: usize) -> Self {
305 Self {
306 kind: ConstKind::Value(
307 Ty::mk_uint(UintTy::Usize),
308 ValTree::Leaf(ScalarInt::try_from_target_usize(v as u128, tcx).unwrap()),
309 ),
310 }
311 }
312}
313
314impl<'tcx> ToRustc<'tcx> for ValTree {
315 type T = rustc_middle::ty::ValTree<'tcx>;
316
317 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
318 match self {
319 ValTree::Leaf(scalar) => rustc_middle::ty::ValTree::from_scalar_int(tcx, *scalar),
320 ValTree::Branch(trees) => {
321 let trees = trees.iter().map(|tree| tree.to_rustc(tcx));
322 rustc_middle::ty::ValTree::from_branches(tcx, trees)
323 }
324 }
325 }
326}
327
328impl<'tcx> ToRustc<'tcx> for Const {
329 type T = rustc_ty::Const<'tcx>;
330
331 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
332 let kind = match &self.kind {
333 ConstKind::Param(param_const) => rustc_ty::ConstKind::Param(*param_const),
334 ConstKind::Value(ty, val) => {
335 let val = rustc_ty::Value { ty: ty.to_rustc(tcx), valtree: val.to_rustc(tcx) };
336 rustc_ty::ConstKind::Value(val)
337 }
338 ConstKind::Infer(infer_const) => rustc_ty::ConstKind::Infer(*infer_const),
339 ConstKind::Unevaluated(uneval_const) => {
340 rustc_ty::ConstKind::Unevaluated(uneval_const.to_rustc(tcx))
341 }
342 };
343 rustc_ty::Const::new(tcx, kind)
344 }
345}
346
347#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
348pub struct UnevaluatedConst {
349 pub def: DefId,
350 pub args: GenericArgs,
351 pub promoted: Option<Promoted>,
352}
353
354#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
355pub enum ValTree {
356 Leaf(ScalarInt),
357 Branch(List<ValTree>),
358}
359
360#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
361pub enum ConstKind {
362 Param(ParamConst),
363 Value(Ty, ValTree),
364 Infer(InferConst),
365 Unevaluated(UnevaluatedConst),
366}
367
368#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
369pub enum GenericArg {
370 Ty(Ty),
371 Lifetime(Region),
372 Const(Const),
373}
374
375pub type GenericArgs = List<GenericArg>;
376
377#[extension(pub trait GenericArgsExt)]
378impl GenericArgs {
379 fn box_args(&self) -> (&Ty, &Ty) {
380 if let [GenericArg::Ty(deref), GenericArg::Ty(alloc)] = &self[..] {
381 (deref, alloc)
382 } else {
383 bug!("invalid generic arguments for box");
384 }
385 }
386
387 fn as_closure(&self) -> ClosureArgs {
388 ClosureArgs { args: self.clone() }
389 }
390
391 fn as_coroutine(&self) -> CoroutineArgs {
392 CoroutineArgs { args: self.clone() }
393 }
394}
395
396pub struct CoroutineArgs {
397 pub args: GenericArgs,
398}
399
400pub struct ClosureArgs {
401 pub args: GenericArgs,
402}
403
404#[expect(unused, reason = "keeping this in case we use it")]
405pub struct ClosureArgsParts<'a, T> {
406 parent_args: &'a [T],
407 closure_kind_ty: &'a T,
408 closure_sig_as_fn_ptr_ty: &'a T,
409 tupled_upvars_ty: &'a T,
410}
411
412#[derive(Debug)]
413pub struct CoroutineArgsParts<'a> {
414 pub parent_args: &'a [GenericArg],
415 pub kind_ty: &'a Ty,
416 pub resume_ty: &'a Ty,
417 pub yield_ty: &'a Ty,
418 pub return_ty: &'a Ty,
419 pub tupled_upvars_ty: &'a Ty,
420}
421
422#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
423pub enum Region {
424 ReBound(DebruijnIndex, BoundRegion),
425 ReEarlyParam(EarlyParamRegion),
426 ReStatic,
427 ReVar(RegionVid),
428 ReLateParam(LateParamRegion),
429 ReErased,
430}
431
432impl<'tcx> ToRustc<'tcx> for Region {
433 type T = rustc_middle::ty::Region<'tcx>;
434
435 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
436 match *self {
437 Region::ReBound(debruijn, bound_region) => {
438 rustc_middle::ty::Region::new_bound(tcx, debruijn, bound_region.to_rustc(tcx))
439 }
440 Region::ReEarlyParam(epr) => rustc_middle::ty::Region::new_early_param(tcx, epr),
441 Region::ReStatic => tcx.lifetimes.re_static,
442 Region::ReVar(rvid) => rustc_middle::ty::Region::new_var(tcx, rvid),
443 Region::ReLateParam(LateParamRegion { scope, kind }) => {
444 rustc_middle::ty::Region::new_late_param(tcx, scope, kind)
445 }
446 Region::ReErased => tcx.lifetimes.re_erased,
447 }
448 }
449}
450
451#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
452pub struct BoundRegion {
453 pub var: BoundVar,
454 pub kind: BoundRegionKind,
455}
456
457impl<'tcx> ToRustc<'tcx> for BoundRegion {
458 type T = rustc_middle::ty::BoundRegion;
459
460 fn to_rustc(&self, _tcx: TyCtxt<'tcx>) -> Self::T {
461 rustc_middle::ty::BoundRegion { var: self.var, kind: self.kind }
462 }
463}
464
465impl Generics<'_> {
466 pub fn parent(&self) -> Option<DefId> {
467 self.orig.parent
468 }
469
470 pub fn parent_count(&self) -> usize {
471 self.orig.parent_count
472 }
473}
474
475impl Clause {
476 pub(crate) fn new(kind: Binder<ClauseKind>) -> Clause {
477 Clause { kind }
478 }
479}
480
481impl<T> EarlyBinder<T> {
482 pub fn skip_binder(self) -> T {
483 self.0
484 }
485
486 pub fn instantiate_identity(self) -> T {
487 self.0
488 }
489}
490
491impl EarlyBinder<Ty> {
492 pub fn subst(&self, args: &[GenericArg]) -> Ty {
493 self.0.subst(args)
494 }
495}
496
497impl<T> Binder<T> {
498 pub fn dummy(value: T) -> Binder<T> {
499 Binder(value, List::empty())
500 }
501
502 pub fn bind_with_vars(value: T, vars: impl Into<List<BoundVariableKind>>) -> Binder<T> {
503 Binder(value, vars.into())
504 }
505
506 pub fn skip_binder(self) -> T {
507 self.0
508 }
509
510 pub fn skip_binder_ref(&self) -> &T {
511 self.as_ref().skip_binder()
512 }
513
514 pub fn as_ref(&self) -> Binder<&T> {
515 Binder(&self.0, self.1.clone())
516 }
517
518 pub fn vars(&self) -> &List<BoundVariableKind> {
519 &self.1
520 }
521}
522
523impl FnSig {
524 pub fn inputs(&self) -> &[Ty] {
525 &self.inputs_and_output[..self.inputs_and_output.len() - 1]
526 }
527
528 pub fn output(&self) -> &Ty {
529 &self.inputs_and_output[self.inputs_and_output.len() - 1]
530 }
531}
532
533impl GenericArg {
534 pub fn expect_type(&self) -> &Ty {
535 if let GenericArg::Ty(ty) = self {
536 ty
537 } else {
538 bug!("expected `GenericArg::Ty`, found {:?}", self)
539 }
540 }
541
542 fn expect_lifetime(&self) -> Region {
543 if let GenericArg::Lifetime(re) = self {
544 *re
545 } else {
546 bug!("expected `GenericArg::Lifetime`, found {:?}", self)
547 }
548 }
549
550 fn expect_const(&self) -> &Const {
551 if let GenericArg::Const(c) = self {
552 c
553 } else {
554 bug!("expected `GenericArg::Const`, found {:?}", self)
555 }
556 }
557}
558
559impl<'tcx> ToRustc<'tcx> for GenericArgs {
560 type T = rustc_middle::ty::GenericArgsRef<'tcx>;
561
562 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
563 tcx.mk_args_from_iter(self.iter().map(|arg| arg.to_rustc(tcx)))
564 }
565}
566
567impl<'tcx> ToRustc<'tcx> for GenericArg {
568 type T = rustc_middle::ty::GenericArg<'tcx>;
569
570 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
571 use rustc_middle::ty;
572 match self {
573 GenericArg::Ty(ty) => ty::GenericArg::from(ty.to_rustc(tcx)),
574 GenericArg::Lifetime(re) => ty::GenericArg::from(re.to_rustc(tcx)),
575 GenericArg::Const(c) => ty::GenericArg::from(c.to_rustc(tcx)),
576 }
577 }
578}
579
580impl CoroutineArgs {
581 pub fn tupled_upvars_ty(&self) -> &Ty {
582 self.split().tupled_upvars_ty
583 }
584
585 pub fn upvar_tys(&self) -> impl Iterator<Item = &Ty> {
586 self.tupled_upvars_ty().tuple_fields().iter()
587 }
588
589 pub fn resume_ty(&self) -> &Ty {
590 self.split().resume_ty
591 }
592
593 fn split(&self) -> CoroutineArgsParts<'_> {
594 match &self.args[..] {
595 [parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => {
596 CoroutineArgsParts {
597 parent_args,
598 kind_ty: kind_ty.expect_type(),
599 resume_ty: resume_ty.expect_type(),
600 yield_ty: yield_ty.expect_type(),
601 return_ty: return_ty.expect_type(),
602 tupled_upvars_ty: tupled_upvars_ty.expect_type(),
603 }
604 }
605 _ => bug!("generator args missing synthetics"),
606 }
607 }
608}
609
610impl ClosureArgs {
611 pub fn tupled_upvars_ty(&self) -> &Ty {
612 self.split().tupled_upvars_ty.expect_type()
613 }
614
615 pub fn upvar_tys(&self) -> &List<Ty> {
616 self.tupled_upvars_ty().tuple_fields()
617 }
618
619 pub fn split(&self) -> ClosureArgsParts<'_, GenericArg> {
620 match &self.args[..] {
621 [parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
622 ClosureArgsParts {
623 parent_args,
624 closure_kind_ty,
625 closure_sig_as_fn_ptr_ty,
626 tupled_upvars_ty,
627 }
628 }
629 _ => bug!("closure args missing synthetics"),
630 }
631 }
632
633 pub fn sig_as_fn_ptr_ty(&self) -> &Ty {
634 self.split().closure_sig_as_fn_ptr_ty.expect_type()
635 }
636
637 pub fn kind_ty(&self) -> &Ty {
638 self.split().closure_kind_ty.expect_type()
639 }
640}
641
642impl AdtDef {
643 pub(crate) fn new(data: AdtDefData) -> Self {
644 Self(Interned::new(data))
645 }
646
647 pub fn did(&self) -> DefId {
648 self.0.did
649 }
650
651 pub fn flags(&self) -> AdtFlags {
652 self.0.flags
653 }
654
655 pub fn is_struct(&self) -> bool {
656 self.flags().contains(AdtFlags::IS_STRUCT)
657 }
658
659 pub fn is_union(&self) -> bool {
660 self.flags().contains(AdtFlags::IS_UNION)
661 }
662
663 pub fn is_enum(&self) -> bool {
664 self.flags().contains(AdtFlags::IS_ENUM)
665 }
666
667 pub fn is_box(&self) -> bool {
668 self.flags().contains(AdtFlags::IS_BOX)
669 }
670
671 pub fn variant(&self, idx: VariantIdx) -> &VariantDef {
672 &self.0.variants[idx]
673 }
674
675 pub fn variants(&self) -> &IndexSlice<VariantIdx, VariantDef> {
676 &self.0.variants
677 }
678
679 pub fn discriminants(&self) -> impl Iterator<Item = (VariantIdx, u128)> + '_ {
680 self.0
681 .discrs
682 .iter_enumerated()
683 .map(|(idx, discr)| (idx, *discr))
684 }
685
686 pub fn non_enum_variant(&self) -> &VariantDef {
687 assert!(self.is_struct() || self.is_union());
688 self.variant(FIRST_VARIANT)
689 }
690}
691
692impl<'tcx> ToRustc<'tcx> for AdtDef {
693 type T = rustc_middle::ty::AdtDef<'tcx>;
694
695 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
696 tcx.adt_def(self.did())
697 }
698}
699
700impl AdtDefData {
701 pub(crate) fn new<'tcx>(
702 tcx: TyCtxt<'tcx>,
703 adt_def: rustc_middle::ty::AdtDef<'tcx>,
704 variants: IndexVec<VariantIdx, VariantDef>,
705 ) -> Self {
706 let discrs: IndexVec<VariantIdx, u128> = if adt_def.is_enum() {
707 adt_def
708 .discriminants(tcx)
709 .map(|(_, discr)| discr.val)
710 .collect()
711 } else {
712 IndexVec::from_raw(vec![0])
713 };
714 tracked_span_assert_eq!(discrs.len(), variants.len());
715 Self { did: adt_def.did(), variants, flags: adt_def.flags(), discrs }
716 }
717}
718
719impl AliasTy {
720 pub fn self_ty(&self) -> &Ty {
722 self.args[0].expect_type()
723 }
724}
725
726impl TyKind {
727 fn intern(self) -> Ty {
728 Ty(Interned::new(TyS { kind: self }))
729 }
730}
731
732impl Ty {
733 pub fn mk_adt(adt_def: AdtDef, args: impl Into<GenericArgs>) -> Ty {
734 let args = args.into();
735 TyKind::Adt(adt_def, args).intern()
736 }
737
738 pub fn mk_closure(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
739 TyKind::Closure(def_id, args.into()).intern()
740 }
741
742 pub fn mk_fn_def(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
743 TyKind::FnDef(def_id, args.into()).intern()
744 }
745
746 pub fn mk_coroutine(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
747 TyKind::Coroutine(def_id, args.into()).intern()
748 }
749
750 pub fn mk_generator_witness(def_id: DefId, args: GenericArgs) -> Ty {
751 TyKind::CoroutineWitness(def_id, args).intern()
752 }
753
754 pub fn mk_alias(kind: AliasKind, def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
755 let alias_ty = AliasTy { args: args.into(), def_id };
756 TyKind::Alias(kind, alias_ty).intern()
757 }
758
759 pub fn mk_array(ty: Ty, c: Const) -> Ty {
760 TyKind::Array(ty, c).intern()
761 }
762
763 pub fn mk_slice(ty: Ty) -> Ty {
764 TyKind::Slice(ty).intern()
765 }
766
767 pub fn mk_fn_ptr(fn_sig: PolyFnSig) -> Ty {
768 TyKind::FnPtr(fn_sig).intern()
769 }
770
771 pub fn mk_raw_ptr(ty: Ty, mutbl: Mutability) -> Ty {
772 TyKind::RawPtr(ty, mutbl).intern()
773 }
774
775 pub fn mk_bool() -> Ty {
776 TyKind::Bool.intern()
777 }
778
779 pub fn mk_float(float_ty: FloatTy) -> Ty {
780 TyKind::Float(float_ty).intern()
781 }
782
783 pub fn mk_int(int_ty: IntTy) -> Ty {
784 TyKind::Int(int_ty).intern()
785 }
786
787 pub fn mk_never() -> Ty {
788 TyKind::Never.intern()
789 }
790
791 pub fn mk_param(param: ParamTy) -> Ty {
792 TyKind::Param(param).intern()
793 }
794
795 pub fn mk_dynamic(exi_preds: impl Into<List<Binder<ExistentialPredicate>>>, r: Region) -> Ty {
796 TyKind::Dynamic(exi_preds.into(), r).intern()
797 }
798
799 pub fn mk_ref(region: Region, ty: Ty, mutability: Mutability) -> Ty {
800 TyKind::Ref(region, ty, mutability).intern()
801 }
802
803 pub fn mk_tuple(tys: impl Into<List<Ty>>) -> Ty {
804 TyKind::Tuple(tys.into()).intern()
805 }
806
807 pub fn mk_uint(uint_ty: UintTy) -> Ty {
808 TyKind::Uint(uint_ty).intern()
809 }
810
811 pub fn mk_str() -> Ty {
812 TyKind::Str.intern()
813 }
814
815 pub fn mk_char() -> Ty {
816 TyKind::Char.intern()
817 }
818
819 pub fn mk_foreign(def_id: DefId) -> Ty {
820 TyKind::Foreign(def_id).intern()
821 }
822
823 pub fn mk_pat() -> Ty {
824 TyKind::Pat.intern()
825 }
826
827 pub fn deref(&self) -> Ty {
828 match self.kind() {
829 TyKind::Adt(adt_def, args) if adt_def.is_box() => args[0].expect_type().clone(),
830 TyKind::Ref(_, ty, _) | TyKind::RawPtr(ty, _) => ty.clone(),
831 _ => tracked_span_bug!("deref projection of non-dereferenceable ty `{self:?}`"),
832 }
833 }
834
835 pub fn kind(&self) -> &TyKind {
836 &self.0.kind
837 }
838
839 pub fn tuple_fields(&self) -> &List<Ty> {
840 match self.kind() {
841 TyKind::Tuple(tys) => tys,
842 _ => bug!("tuple_fields called on non-tuple"),
843 }
844 }
845
846 pub fn expect_adt(&self) -> (&AdtDef, &GenericArgs) {
847 match self.kind() {
848 TyKind::Adt(adt_def, args) => (adt_def, args),
849 _ => bug!("expect_adt called on non-adt"),
850 }
851 }
852
853 pub fn is_mut_ref(&self) -> bool {
854 matches!(self.kind(), TyKind::Ref(.., Mutability::Mut))
855 }
856
857 pub fn is_box(&self) -> bool {
858 matches!(self.kind(), TyKind::Adt(adt, ..) if adt.is_box())
859 }
860}
861
862impl<'tcx, V> ToRustc<'tcx> for Binder<V>
863where
864 V: ToRustc<'tcx, T: rustc_middle::ty::TypeVisitable<TyCtxt<'tcx>>>,
865{
866 type T = rustc_middle::ty::Binder<'tcx, V::T>;
867
868 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
869 let vars = BoundVariableKind::to_rustc(self.vars(), tcx);
870 let value = self.skip_binder_ref().to_rustc(tcx);
871 rustc_middle::ty::Binder::bind_with_vars(value, vars)
872 }
873}
874
875impl<'tcx> ToRustc<'tcx> for FnSig {
876 type T = rustc_middle::ty::FnSig<'tcx>;
877
878 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
879 tcx.mk_fn_sig(
880 self.inputs().iter().map(|ty| ty.to_rustc(tcx)),
881 self.output().to_rustc(tcx),
882 false,
883 self.safety,
884 self.abi,
885 )
886 }
887}
888
889impl<'tcx> ToRustc<'tcx> for AliasTy {
890 type T = rustc_middle::ty::AliasTy<'tcx>;
891
892 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
893 rustc_middle::ty::AliasTy::new(tcx, self.def_id, self.args.to_rustc(tcx))
894 }
895}
896
897impl<'tcx> ToRustc<'tcx> for ExistentialPredicate {
898 type T = rustc_middle::ty::ExistentialPredicate<'tcx>;
899
900 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
901 match self {
902 ExistentialPredicate::Trait(trait_ref) => {
903 let trait_ref = rustc_middle::ty::ExistentialTraitRef::new_from_args(
904 tcx,
905 trait_ref.def_id,
906 trait_ref.args.to_rustc(tcx),
907 );
908 rustc_middle::ty::ExistentialPredicate::Trait(trait_ref)
909 }
910 ExistentialPredicate::Projection(projection) => {
911 rustc_middle::ty::ExistentialPredicate::Projection(
912 rustc_middle::ty::ExistentialProjection::new_from_args(
913 tcx,
914 projection.def_id,
915 projection.args.to_rustc(tcx),
916 projection.term.to_rustc(tcx).into(),
917 ),
918 )
919 }
920 ExistentialPredicate::AutoTrait(def_id) => {
921 rustc_middle::ty::ExistentialPredicate::AutoTrait(*def_id)
922 }
923 }
924 }
925}
926
927impl<'tcx> ToRustc<'tcx> for Ty {
928 type T = rustc_middle::ty::Ty<'tcx>;
929
930 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::Ty<'tcx> {
931 match self.kind() {
932 TyKind::Bool => tcx.types.bool,
933 TyKind::Str => tcx.types.str_,
934 TyKind::Char => tcx.types.char,
935 TyKind::Never => tcx.types.never,
936 TyKind::Foreign(def_id) => rustc_ty::Ty::new_foreign(tcx, *def_id),
937 TyKind::Float(float_ty) => rustc_ty::Ty::new_float(tcx, *float_ty),
938 TyKind::Int(int_ty) => rustc_ty::Ty::new_int(tcx, *int_ty),
939 TyKind::Uint(uint_ty) => rustc_ty::Ty::new_uint(tcx, *uint_ty),
940 TyKind::Adt(adt_def, args) => {
941 let adt_def = adt_def.to_rustc(tcx);
942 let args = tcx.mk_args_from_iter(args.iter().map(|arg| arg.to_rustc(tcx)));
943 rustc_ty::Ty::new_adt(tcx, adt_def, args)
944 }
945 TyKind::FnDef(def_id, args) => {
946 let args = tcx.mk_args_from_iter(args.iter().map(|arg| arg.to_rustc(tcx)));
947 rustc_ty::Ty::new_fn_def(tcx, *def_id, args)
948 }
949 TyKind::Array(ty, len) => {
950 let ty = ty.to_rustc(tcx);
951 let len = len.to_rustc(tcx);
952 rustc_ty::Ty::new_array_with_const_len(tcx, ty, len)
953 }
954 TyKind::Param(pty) => rustc_ty::Ty::new_param(tcx, pty.index, pty.name),
955 TyKind::Ref(re, ty, mutbl) => {
956 rustc_ty::Ty::new_ref(tcx, re.to_rustc(tcx), ty.to_rustc(tcx), *mutbl)
957 }
958 TyKind::Tuple(tys) => {
959 let ts = tys.iter().map(|ty| ty.to_rustc(tcx)).collect_vec();
960 rustc_ty::Ty::new_tup(tcx, tcx.mk_type_list(&ts))
961 }
962 TyKind::Slice(ty) => rustc_ty::Ty::new_slice(tcx, ty.to_rustc(tcx)),
963 TyKind::RawPtr(ty, mutbl) => rustc_ty::Ty::new_ptr(tcx, ty.to_rustc(tcx), *mutbl),
964 TyKind::Closure(did, args) => rustc_ty::Ty::new_closure(tcx, *did, args.to_rustc(tcx)),
965 TyKind::FnPtr(poly_sig) => rustc_ty::Ty::new_fn_ptr(tcx, poly_sig.to_rustc(tcx)),
966 TyKind::Alias(kind, alias_ty) => {
967 rustc_ty::Ty::new_alias(tcx, kind.to_rustc(tcx), alias_ty.to_rustc(tcx))
968 }
969 TyKind::Dynamic(exi_preds, re) => {
970 let preds = exi_preds
971 .iter()
972 .map(|pred| pred.to_rustc(tcx))
973 .collect_vec();
974
975 let preds = tcx.mk_poly_existential_predicates(&preds);
976 rustc_ty::Ty::new_dynamic(tcx, preds, re.to_rustc(tcx))
977 }
978 TyKind::Pat => todo!(),
979 TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => {
980 bug!("TODO: to_rustc for `{self:?}`")
981 }
982 }
983 }
984}
985
986impl_internable!(TyS, AdtDefData);
987impl_slice_internable!(
988 Ty,
989 GenericArg,
990 GenericParamDef,
991 BoundVariableKind,
992 Clause,
993 ValTree,
994 Binder<ExistentialPredicate>,
995);
996
997impl fmt::Debug for ExistentialPredicate {
998 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
999 match self {
1000 ExistentialPredicate::Trait(trait_ref) => write!(f, "{trait_ref:?}"),
1001 ExistentialPredicate::Projection(proj) => write!(f, "({proj:?})"),
1002 ExistentialPredicate::AutoTrait(def_id) => {
1003 write!(f, "{}", def_id_to_string(*def_id))
1004 }
1005 }
1006 }
1007}
1008
1009impl fmt::Debug for ExistentialTraitRef {
1010 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1011 write!(f, "{}", def_id_to_string(self.def_id))?;
1012 if !self.args.is_empty() {
1013 write!(f, "<{:?}>", self.args.iter().format(","))?;
1014 }
1015 Ok(())
1016 }
1017}
1018
1019impl fmt::Debug for ExistentialProjection {
1020 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1021 write!(f, "{}", def_id_to_string(self.def_id))?;
1022 if !self.args.is_empty() {
1023 write!(f, "<{:?}>", self.args.iter().format(","))?;
1024 }
1025 write!(f, " = {:?}", &self.term)
1026 }
1027}
1028
1029impl fmt::Debug for GenericArg {
1030 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1031 match self {
1032 GenericArg::Ty(ty) => write!(f, "{ty:?}"),
1033 GenericArg::Lifetime(region) => write!(f, "{region:?}"),
1034 GenericArg::Const(c) => write!(f, "Const({c:?})"),
1035 }
1036 }
1037}
1038
1039impl fmt::Debug for Region {
1040 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1041 write!(f, "{}", region_to_string(*self))
1042 }
1043}
1044
1045impl<T: fmt::Debug> fmt::Debug for Binder<T> {
1046 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1047 if !self.1.is_empty() {
1048 write!(f, "for<{:?}> ", self.1.iter().format(", "))?;
1049 }
1050 write!(f, "{:?}", self.0)
1051 }
1052}
1053
1054impl fmt::Debug for FnSig {
1055 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1056 write!(f, "fn({:?}) -> {:?}", self.inputs().iter().format(", "), self.output())
1057 }
1058}
1059
1060impl fmt::Debug for Ty {
1061 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1062 match self.kind() {
1063 TyKind::Adt(adt_def, args) => {
1064 let adt_name = rustc_middle::ty::tls::with(|tcx| tcx.def_path_str(adt_def.did()));
1065 write!(f, "{adt_name}")?;
1066 if !args.is_empty() {
1067 write!(f, "<{:?}>", args.iter().format(", "))?;
1068 }
1069 Ok(())
1070 }
1071 TyKind::FnDef(def_id, args) => {
1072 write!(f, "FnDef({:?}[{:?}])", def_id, args.iter().format(", "))
1073 }
1074 TyKind::Bool => write!(f, "bool"),
1075 TyKind::Str => write!(f, "str"),
1076 TyKind::Char => write!(f, "char"),
1077 TyKind::Float(float_ty) => write!(f, "{}", float_ty.name_str()),
1078 TyKind::Int(int_ty) => write!(f, "{}", int_ty.name_str()),
1079 TyKind::Uint(uint_ty) => write!(f, "{}", uint_ty.name_str()),
1080 TyKind::Never => write!(f, "!"),
1081 TyKind::Param(param_ty) => write!(f, "{param_ty}"),
1082 TyKind::Ref(region, ty, Mutability::Mut) => write!(f, "&{region:?} mut {ty:?}"),
1083 TyKind::Ref(region, ty, Mutability::Not) => write!(f, "&{region:?} {ty:?}"),
1084 TyKind::Array(ty, c) => write!(f, "[{ty:?}; {c:?}]"),
1085 TyKind::Tuple(tys) => {
1086 if let [ty] = &tys[..] {
1087 write!(f, "({ty:?},)")
1088 } else {
1089 write!(f, "({:?})", tys.iter().format(", "))
1090 }
1091 }
1092 TyKind::Slice(ty) => write!(f, "[{ty:?}]"),
1093 TyKind::RawPtr(ty, Mutability::Mut) => write!(f, "*mut {ty:?}"),
1094 TyKind::RawPtr(ty, Mutability::Not) => write!(f, "*const {ty:?}"),
1095 TyKind::FnPtr(fn_sig) => write!(f, "{fn_sig:?}"),
1096 TyKind::Closure(did, args) => {
1097 write!(f, "{}", def_id_to_string(*did))?;
1098 if !args.is_empty() {
1099 write!(f, "<{:?}>", args.iter().format(", "))?;
1100 }
1101 Ok(())
1102 }
1103 TyKind::Coroutine(did, args) => {
1104 write!(f, "{}", def_id_to_string(*did))?;
1105 if !args.is_empty() {
1106 write!(f, "<{:?}>", args.iter().format(", "))?;
1107 }
1108 Ok(())
1109 }
1110 TyKind::CoroutineWitness(did, args) => {
1111 write!(f, "{}", def_id_to_string(*did))?;
1112 if !args.is_empty() {
1113 write!(f, "<{:?}>", args.iter().format(", "))?;
1114 }
1115 Ok(())
1116 }
1117 TyKind::Alias(AliasKind::Opaque, alias_ty) => {
1118 write!(f, "{}", def_id_to_string(alias_ty.def_id))?;
1119 if !alias_ty.args.is_empty() {
1120 write!(f, "<{:?}>", alias_ty.args.iter().format(", "))?;
1121 }
1122 Ok(())
1123 }
1124 TyKind::Alias(kind, alias_ty) => {
1125 let def_id = alias_ty.def_id;
1126 let args = &alias_ty.args;
1127 write!(f, "Alias ({kind:?}, {}, ", def_id_to_string(def_id))?;
1128 if !args.is_empty() {
1129 write!(f, "<{:?}>", args.iter().format(", "))?;
1130 }
1131 write!(f, ")")?;
1132 Ok(())
1133 }
1134 TyKind::Dynamic(preds, r) => {
1135 write!(f, "dyn {:?} + {r:?}", preds.iter().format(", "))
1136 }
1137 TyKind::Foreign(def_id) => {
1138 write!(f, "Foreign {def_id:?}")
1139 }
1140 TyKind::Pat => todo!(),
1141 }
1142 }
1143}
1144
1145impl fmt::Debug for ValTree {
1146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1147 match &self {
1148 ValTree::Leaf(scalar_int) => write!(f, "Leaf({scalar_int})"),
1149 ValTree::Branch(vec) => write!(f, "Branch([{:?}])", vec.iter().format(", ")),
1150 }
1151 }
1152}
1153
1154impl fmt::Debug for Const {
1155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1156 match &self.kind {
1157 ConstKind::Param(p) => write!(f, "{}", p.name.as_str()),
1158 ConstKind::Value(_, v) => write!(f, "{v:?}"),
1159 ConstKind::Infer(infer_const) => write!(f, "{infer_const:?}"),
1160 ConstKind::Unevaluated(uneval_const) => write!(f, "{uneval_const:?}"),
1161 }
1162 }
1163}
1164
1165pub fn region_to_string(region: Region) -> String {
1166 match region {
1167 Region::ReBound(debruijn, region) => {
1168 match region.kind {
1169 BoundRegionKind::Anon => "'<annon>".to_string(),
1170 BoundRegionKind::Named(_) => {
1171 format!("{debruijn:?}{region:?}")
1172 }
1173 BoundRegionKind::ClosureEnv => "'<env>".to_string(),
1174 BoundRegionKind::NamedAnon(sym) => format!("{sym}"),
1175 }
1176 }
1177 Region::ReEarlyParam(region) => region.name.to_string(),
1178 Region::ReStatic => "'static".to_string(),
1179 Region::ReVar(rvid) => format!("{rvid:?}"),
1180 Region::ReLateParam(..) => "'<free>".to_string(),
1181 Region::ReErased => "'_".to_string(),
1182 }
1183}