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