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