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