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