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, RegionExt, 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 Inherent { def_id: DefId },
425 Free { def_id: DefId },
426 Anon { def_id: DefId },
427}
428
429impl AliasConstKind {
430 pub fn to_rustc_kind<'tcx>(self) -> rustc_middle::ty::AliasConstKind<'tcx> {
431 use rustc_middle::ty;
432 match self {
433 AliasConstKind::Projection { def_id } => ty::AliasConstKind::Projection { def_id },
434 AliasConstKind::Inherent { def_id } => ty::AliasConstKind::Inherent { def_id },
435 AliasConstKind::Free { def_id } => ty::AliasConstKind::Free { def_id },
436 AliasConstKind::Anon { def_id } => ty::AliasConstKind::Anon { def_id },
437 }
438 }
439}
440
441#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
442pub enum ValTree {
443 Leaf(ScalarInt),
444 Branch(List<Const>),
445}
446
447#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
448pub enum ConstKind {
449 Param(ParamConst),
450 Value(Ty, ValTree),
451 Infer(InferConst),
452 Alias(AliasConst),
453}
454
455#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
456pub enum GenericArg {
457 Ty(Ty),
458 Lifetime(Region),
459 Const(Const),
460}
461
462pub type GenericArgs = List<GenericArg>;
463
464#[extension(pub trait GenericArgsExt)]
465impl GenericArgs {
466 fn box_args(&self) -> (&Ty, &Ty) {
467 if let [GenericArg::Ty(deref), GenericArg::Ty(alloc)] = &self[..] {
468 (deref, alloc)
469 } else {
470 bug!("invalid generic arguments for box");
471 }
472 }
473
474 fn as_closure(&self) -> ClosureArgs {
475 ClosureArgs { args: self.clone() }
476 }
477
478 fn as_coroutine(&self) -> CoroutineArgs {
479 CoroutineArgs { args: self.clone() }
480 }
481}
482
483pub struct CoroutineArgs {
484 pub args: GenericArgs,
485}
486
487pub struct ClosureArgs {
488 pub args: GenericArgs,
489}
490
491#[expect(unused, reason = "keeping this in case we use it")]
492pub struct ClosureArgsParts<'a, T> {
493 parent_args: &'a [T],
494 closure_kind_ty: &'a T,
495 closure_sig_as_fn_ptr_ty: &'a T,
496 tupled_upvars_ty: &'a T,
497}
498
499#[derive(Debug)]
500pub struct CoroutineArgsParts<'a> {
501 pub parent_args: &'a [GenericArg],
502 pub kind_ty: &'a Ty,
503 pub resume_ty: &'a Ty,
504 pub yield_ty: &'a Ty,
505 pub return_ty: &'a Ty,
506 pub tupled_upvars_ty: &'a Ty,
507}
508
509#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
511pub struct LateParamRegion {
512 pub scope: DefId,
513 pub kind: LateParamRegionKind,
514}
515
516#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
517pub enum Region {
518 ReBound(DebruijnIndex, BoundRegion),
519 ReEarlyParam(EarlyParamRegion),
520 ReStatic,
521 ReVar(RegionVid),
522 ReLateParam(LateParamRegion),
523 ReErased,
524}
525
526impl<'tcx> ToRustc<'tcx> for Region {
527 type T = rustc_middle::ty::Region<'tcx>;
528
529 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
530 match *self {
531 Region::ReBound(debruijn, bound_region) => {
532 rustc_middle::ty::Region::new_bound(tcx, debruijn, bound_region.to_rustc(tcx))
533 }
534 Region::ReEarlyParam(epr) => rustc_middle::ty::Region::new_early_param(tcx, epr),
535 Region::ReStatic => tcx.lifetimes.re_static,
536 Region::ReVar(rvid) => rustc_middle::ty::Region::new_var(tcx, rvid),
537 Region::ReLateParam(LateParamRegion { scope, kind }) => {
538 rustc_middle::ty::Region::new_late_param(tcx, scope, kind)
539 }
540 Region::ReErased => tcx.lifetimes.re_erased,
541 }
542 }
543}
544
545#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
546pub struct BoundRegion {
547 pub var: BoundVar,
548 pub kind: BoundRegionKind,
549}
550
551impl<'tcx> ToRustc<'tcx> for BoundRegion {
552 type T = rustc_middle::ty::BoundRegion<'tcx>;
553
554 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
555 rustc_middle::ty::BoundRegion { var: self.var, kind: self.kind.to_rustc(tcx) }
556 }
557}
558
559impl Generics<'_> {
560 pub fn parent(&self) -> Option<DefId> {
561 self.orig.parent
562 }
563
564 pub fn parent_count(&self) -> usize {
565 self.orig.parent_count
566 }
567}
568
569impl Clause {
570 pub(crate) fn new(kind: Binder<ClauseKind>) -> Clause {
571 Clause { kind }
572 }
573}
574
575impl<T> EarlyBinder<T> {
576 pub fn skip_binder(self) -> T {
577 self.0
578 }
579
580 pub fn instantiate_identity(self) -> T {
581 self.0
582 }
583}
584
585impl EarlyBinder<Ty> {
586 pub fn subst(&self, args: &[GenericArg]) -> Ty {
587 self.0.subst(args)
588 }
589}
590
591impl<T> Binder<T> {
592 pub fn dummy(value: T) -> Binder<T> {
593 Binder(value, List::empty())
594 }
595
596 pub fn bind_with_vars(value: T, vars: impl Into<List<BoundVariableKind>>) -> Binder<T> {
597 Binder(value, vars.into())
598 }
599
600 pub fn skip_binder(self) -> T {
601 self.0
602 }
603
604 pub fn skip_binder_ref(&self) -> &T {
605 self.as_ref().skip_binder()
606 }
607
608 pub fn as_ref(&self) -> Binder<&T> {
609 Binder(&self.0, self.1.clone())
610 }
611
612 pub fn vars(&self) -> &List<BoundVariableKind> {
613 &self.1
614 }
615}
616
617impl FnSig {
618 pub fn inputs(&self) -> &[Ty] {
619 &self.inputs_and_output[..self.inputs_and_output.len() - 1]
620 }
621
622 pub fn output(&self) -> &Ty {
623 &self.inputs_and_output[self.inputs_and_output.len() - 1]
624 }
625}
626
627impl GenericArg {
628 pub fn expect_type(&self) -> &Ty {
629 if let GenericArg::Ty(ty) = self {
630 ty
631 } else {
632 bug!("expected `GenericArg::Ty`, found {:?}", self)
633 }
634 }
635
636 fn expect_lifetime(&self) -> Region {
637 if let GenericArg::Lifetime(re) = self {
638 *re
639 } else {
640 bug!("expected `GenericArg::Lifetime`, found {:?}", self)
641 }
642 }
643
644 fn expect_const(&self) -> &Const {
645 if let GenericArg::Const(c) = self {
646 c
647 } else {
648 bug!("expected `GenericArg::Const`, found {:?}", self)
649 }
650 }
651}
652
653impl<'tcx> ToRustc<'tcx> for GenericArgs {
654 type T = rustc_middle::ty::GenericArgsRef<'tcx>;
655
656 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
657 tcx.mk_args_from_iter(self.iter().map(|arg| arg.to_rustc(tcx)))
658 }
659}
660
661impl<'tcx> ToRustc<'tcx> for GenericArg {
662 type T = rustc_middle::ty::GenericArg<'tcx>;
663
664 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
665 use rustc_middle::ty;
666 match self {
667 GenericArg::Ty(ty) => ty::GenericArg::from(ty.to_rustc(tcx)),
668 GenericArg::Lifetime(re) => ty::GenericArg::from(re.to_rustc(tcx)),
669 GenericArg::Const(c) => ty::GenericArg::from(c.to_rustc(tcx)),
670 }
671 }
672}
673
674impl CoroutineArgs {
675 pub fn tupled_upvars_ty(&self) -> &Ty {
676 self.split().tupled_upvars_ty
677 }
678
679 pub fn upvar_tys(&self) -> impl Iterator<Item = &Ty> {
680 self.tupled_upvars_ty().tuple_fields().iter()
681 }
682
683 pub fn resume_ty(&self) -> &Ty {
684 self.split().resume_ty
685 }
686
687 fn split(&self) -> CoroutineArgsParts<'_> {
688 match &self.args[..] {
689 [parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => {
690 CoroutineArgsParts {
691 parent_args,
692 kind_ty: kind_ty.expect_type(),
693 resume_ty: resume_ty.expect_type(),
694 yield_ty: yield_ty.expect_type(),
695 return_ty: return_ty.expect_type(),
696 tupled_upvars_ty: tupled_upvars_ty.expect_type(),
697 }
698 }
699 _ => bug!("generator args missing synthetics"),
700 }
701 }
702}
703
704impl ClosureArgs {
705 pub fn tupled_upvars_ty(&self) -> &Ty {
706 self.split().tupled_upvars_ty.expect_type()
707 }
708
709 pub fn upvar_tys(&self) -> &List<Ty> {
710 self.tupled_upvars_ty().tuple_fields()
711 }
712
713 pub fn split(&self) -> ClosureArgsParts<'_, GenericArg> {
714 match &self.args[..] {
715 [parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
716 ClosureArgsParts {
717 parent_args,
718 closure_kind_ty,
719 closure_sig_as_fn_ptr_ty,
720 tupled_upvars_ty,
721 }
722 }
723 _ => bug!("closure args missing synthetics"),
724 }
725 }
726
727 pub fn sig_as_fn_ptr_ty(&self) -> &Ty {
728 self.split().closure_sig_as_fn_ptr_ty.expect_type()
729 }
730
731 pub fn kind_ty(&self) -> &Ty {
732 self.split().closure_kind_ty.expect_type()
733 }
734}
735
736impl AdtDef {
737 pub(crate) fn new(data: AdtDefData) -> Self {
738 Self(Interned::new(data))
739 }
740
741 pub fn did(&self) -> DefId {
742 self.0.did
743 }
744
745 pub fn flags(&self) -> AdtFlags {
746 self.0.flags
747 }
748
749 pub fn is_struct(&self) -> bool {
750 self.flags().contains(AdtFlags::IS_STRUCT)
751 }
752
753 pub fn is_union(&self) -> bool {
754 self.flags().contains(AdtFlags::IS_UNION)
755 }
756
757 pub fn is_enum(&self) -> bool {
758 self.flags().contains(AdtFlags::IS_ENUM)
759 }
760
761 pub fn is_box(&self) -> bool {
762 self.flags().contains(AdtFlags::IS_BOX)
763 }
764
765 pub fn variant(&self, idx: VariantIdx) -> &VariantDef {
766 &self.0.variants[idx]
767 }
768
769 pub fn variants(&self) -> &IndexSlice<VariantIdx, VariantDef> {
770 &self.0.variants
771 }
772
773 pub fn discriminants(&self) -> impl Iterator<Item = (VariantIdx, u128)> + '_ {
774 self.0
775 .discrs
776 .iter_enumerated()
777 .map(|(idx, discr)| (idx, *discr))
778 }
779
780 pub fn non_enum_variant(&self) -> &VariantDef {
781 assert!(self.is_struct() || self.is_union());
782 self.variant(FIRST_VARIANT)
783 }
784}
785
786impl<'tcx> ToRustc<'tcx> for AdtDef {
787 type T = rustc_middle::ty::AdtDef<'tcx>;
788
789 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
790 tcx.adt_def(self.did())
791 }
792}
793
794impl AdtDefData {
795 pub(crate) fn new<'tcx>(
796 tcx: TyCtxt<'tcx>,
797 adt_def: rustc_middle::ty::AdtDef<'tcx>,
798 variants: IndexVec<VariantIdx, VariantDef>,
799 ) -> Self {
800 let discrs: IndexVec<VariantIdx, u128> = if adt_def.is_enum() {
801 adt_def
802 .discriminants(tcx)
803 .map(|(_, discr)| discr.val)
804 .collect()
805 } else {
806 IndexVec::from_raw(vec![0])
807 };
808 tracked_span_assert_eq!(discrs.len(), variants.len());
809 Self { did: adt_def.did(), variants, flags: adt_def.flags(), discrs }
810 }
811}
812
813impl AliasTy {
814 pub fn self_ty(&self) -> &Ty {
816 self.args[0].expect_type()
817 }
818}
819
820impl TyKind {
821 fn intern(self) -> Ty {
822 Ty(Interned::new(TyS { kind: self }))
823 }
824}
825
826impl Ty {
827 pub fn mk_adt(adt_def: AdtDef, args: impl Into<GenericArgs>) -> Ty {
828 let args = args.into();
829 TyKind::Adt(adt_def, args).intern()
830 }
831
832 pub fn mk_closure(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
833 TyKind::Closure(def_id, args.into()).intern()
834 }
835
836 pub fn mk_fn_def(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
837 TyKind::FnDef(def_id, args.into()).intern()
838 }
839
840 pub fn mk_coroutine(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
841 TyKind::Coroutine(def_id, args.into()).intern()
842 }
843
844 pub fn mk_generator_witness(def_id: DefId, args: GenericArgs) -> Ty {
845 TyKind::CoroutineWitness(def_id, args).intern()
846 }
847
848 pub fn mk_alias(kind: AliasKind, args: impl Into<GenericArgs>) -> Ty {
849 TyKind::Alias(AliasTy { kind, args: args.into() }).intern()
850 }
851
852 pub fn mk_array(ty: Ty, c: Const) -> Ty {
853 TyKind::Array(ty, c).intern()
854 }
855
856 pub fn mk_slice(ty: Ty) -> Ty {
857 TyKind::Slice(ty).intern()
858 }
859
860 pub fn mk_fn_ptr(fn_sig: PolyFnSig) -> Ty {
861 TyKind::FnPtr(fn_sig).intern()
862 }
863
864 pub fn mk_raw_ptr(ty: Ty, mutbl: Mutability) -> Ty {
865 TyKind::RawPtr(ty, mutbl).intern()
866 }
867
868 pub fn mk_bool() -> Ty {
869 TyKind::Bool.intern()
870 }
871
872 pub fn mk_float(float_ty: FloatTy) -> Ty {
873 TyKind::Float(float_ty).intern()
874 }
875
876 pub fn mk_int(int_ty: IntTy) -> Ty {
877 TyKind::Int(int_ty).intern()
878 }
879
880 pub fn mk_never() -> Ty {
881 TyKind::Never.intern()
882 }
883
884 pub fn mk_param(param: ParamTy) -> Ty {
885 TyKind::Param(param).intern()
886 }
887
888 pub fn mk_dynamic(exi_preds: impl Into<List<Binder<ExistentialPredicate>>>, r: Region) -> Ty {
889 TyKind::Dynamic(exi_preds.into(), r).intern()
890 }
891
892 pub fn mk_ref(region: Region, ty: Ty, mutability: Mutability) -> Ty {
893 TyKind::Ref(region, ty, mutability).intern()
894 }
895
896 pub fn mk_tuple(tys: impl Into<List<Ty>>) -> Ty {
897 TyKind::Tuple(tys.into()).intern()
898 }
899
900 pub fn mk_uint(uint_ty: UintTy) -> Ty {
901 TyKind::Uint(uint_ty).intern()
902 }
903
904 pub fn mk_str() -> Ty {
905 TyKind::Str.intern()
906 }
907
908 pub fn mk_char() -> Ty {
909 TyKind::Char.intern()
910 }
911
912 pub fn mk_foreign(def_id: DefId) -> Ty {
913 TyKind::Foreign(def_id).intern()
914 }
915
916 pub fn mk_pat() -> Ty {
917 TyKind::Pat.intern()
918 }
919
920 pub fn deref(&self) -> Ty {
921 match self.kind() {
922 TyKind::Adt(adt_def, args) if adt_def.is_box() => args[0].expect_type().clone(),
923 TyKind::Ref(_, ty, _) | TyKind::RawPtr(ty, _) => ty.clone(),
924 _ => tracked_span_bug!("deref projection of non-dereferenceable ty `{self:?}`"),
925 }
926 }
927
928 pub fn kind(&self) -> &TyKind {
929 &self.0.kind
930 }
931
932 pub fn tuple_fields(&self) -> &List<Ty> {
933 match self.kind() {
934 TyKind::Tuple(tys) => tys,
935 _ => bug!("tuple_fields called on non-tuple"),
936 }
937 }
938
939 pub fn expect_adt(&self) -> (&AdtDef, &GenericArgs) {
940 match self.kind() {
941 TyKind::Adt(adt_def, args) => (adt_def, args),
942 _ => bug!("expect_adt called on non-adt"),
943 }
944 }
945
946 pub fn is_mut_ref(&self) -> bool {
947 matches!(self.kind(), TyKind::Ref(.., Mutability::Mut))
948 }
949
950 pub fn is_box(&self) -> bool {
951 matches!(self.kind(), TyKind::Adt(adt, ..) if adt.is_box())
952 }
953}
954
955impl<'tcx, V> ToRustc<'tcx> for Binder<V>
956where
957 V: ToRustc<'tcx, T: rustc_middle::ty::TypeVisitable<TyCtxt<'tcx>>>,
958{
959 type T = rustc_middle::ty::Binder<'tcx, V::T>;
960
961 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
962 let vars = BoundVariableKind::to_rustc(self.vars(), tcx);
963 let value = self.skip_binder_ref().to_rustc(tcx);
964 rustc_middle::ty::Binder::bind_with_vars(value, vars)
965 }
966}
967
968impl<'tcx> ToRustc<'tcx> for FnSig {
969 type T = rustc_middle::ty::FnSig<'tcx>;
970
971 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
972 tcx.mk_fn_sig(
973 self.inputs().iter().map(|ty| ty.to_rustc(tcx)),
974 self.output().to_rustc(tcx),
975 rustc_middle::ty::FnSigKind::default()
976 .set_abi(self.abi)
977 .set_safety(self.safety)
978 .set_c_variadic(false),
979 )
980 }
981}
982
983impl<'tcx> ToRustc<'tcx> for AliasTy {
984 type T = rustc_middle::ty::AliasTy<'tcx>;
985
986 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
987 rustc_middle::ty::AliasTy::new_from_args(
988 tcx,
989 self.kind.to_rustc_kind(),
990 self.args.to_rustc(tcx),
991 )
992 }
993}
994
995impl<'tcx> ToRustc<'tcx> for ExistentialPredicate {
996 type T = rustc_middle::ty::ExistentialPredicate<'tcx>;
997
998 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
999 match self {
1000 ExistentialPredicate::Trait(trait_ref) => {
1001 let trait_ref = rustc_middle::ty::ExistentialTraitRef::new_from_args(
1002 tcx,
1003 trait_ref.def_id,
1004 trait_ref.args.to_rustc(tcx),
1005 );
1006 rustc_middle::ty::ExistentialPredicate::Trait(trait_ref)
1007 }
1008 ExistentialPredicate::Projection(projection) => {
1009 rustc_middle::ty::ExistentialPredicate::Projection(
1010 rustc_middle::ty::ExistentialProjection::new_from_args(
1011 tcx,
1012 projection.def_id,
1013 projection.args.to_rustc(tcx),
1014 projection.term.to_rustc(tcx).into(),
1015 ),
1016 )
1017 }
1018 ExistentialPredicate::AutoTrait(def_id) => {
1019 rustc_middle::ty::ExistentialPredicate::AutoTrait(*def_id)
1020 }
1021 }
1022 }
1023}
1024
1025impl<'tcx> ToRustc<'tcx> for Ty {
1026 type T = rustc_middle::ty::Ty<'tcx>;
1027
1028 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::Ty<'tcx> {
1029 match self.kind() {
1030 TyKind::Bool => tcx.types.bool,
1031 TyKind::Str => tcx.types.str_,
1032 TyKind::Char => tcx.types.char,
1033 TyKind::Never => tcx.types.never,
1034 TyKind::Foreign(def_id) => rustc_ty::Ty::new_foreign(tcx, *def_id),
1035 TyKind::Float(float_ty) => rustc_ty::Ty::new_float(tcx, *float_ty),
1036 TyKind::Int(int_ty) => rustc_ty::Ty::new_int(tcx, *int_ty),
1037 TyKind::Uint(uint_ty) => rustc_ty::Ty::new_uint(tcx, *uint_ty),
1038 TyKind::Adt(adt_def, args) => {
1039 let adt_def = adt_def.to_rustc(tcx);
1040 let args = tcx.mk_args_from_iter(args.iter().map(|arg| arg.to_rustc(tcx)));
1041 rustc_ty::Ty::new_adt(tcx, adt_def, args)
1042 }
1043 TyKind::FnDef(def_id, args) => {
1044 let args = tcx.mk_args_from_iter(args.iter().map(|arg| arg.to_rustc(tcx)));
1045 tcx.type_of(*def_id).instantiate(tcx, args).skip_norm_wip()
1046 }
1047 TyKind::Array(ty, len) => {
1048 let ty = ty.to_rustc(tcx);
1049 let len = len.to_rustc(tcx);
1050 rustc_ty::Ty::new_array_with_const_len(tcx, ty, len)
1051 }
1052 TyKind::Param(pty) => rustc_ty::Ty::new_param(tcx, pty.index, pty.name),
1053 TyKind::Ref(re, ty, mutbl) => {
1054 rustc_ty::Ty::new_ref(tcx, re.to_rustc(tcx), ty.to_rustc(tcx), *mutbl)
1055 }
1056 TyKind::Tuple(tys) => {
1057 let ts = tys.iter().map(|ty| ty.to_rustc(tcx)).collect_vec();
1058 rustc_ty::Ty::new_tup(tcx, tcx.mk_type_list(&ts))
1059 }
1060 TyKind::Slice(ty) => rustc_ty::Ty::new_slice(tcx, ty.to_rustc(tcx)),
1061 TyKind::RawPtr(ty, mutbl) => rustc_ty::Ty::new_ptr(tcx, ty.to_rustc(tcx), *mutbl),
1062 TyKind::Closure(did, args) => rustc_ty::Ty::new_closure(tcx, *did, args.to_rustc(tcx)),
1063 TyKind::FnPtr(poly_sig) => rustc_ty::Ty::new_fn_ptr(tcx, poly_sig.to_rustc(tcx)),
1064 TyKind::Alias(alias_ty) => {
1065 rustc_ty::Ty::new_alias(tcx, rustc_ty::IsRigid::No, alias_ty.to_rustc(tcx))
1066 }
1067 TyKind::Dynamic(exi_preds, re) => {
1068 let preds = exi_preds
1069 .iter()
1070 .map(|pred| pred.to_rustc(tcx))
1071 .collect_vec();
1072
1073 let preds = tcx.mk_poly_existential_predicates(&preds);
1074 rustc_ty::Ty::new_dynamic(tcx, preds, re.to_rustc(tcx))
1075 }
1076 TyKind::Pat => todo!(),
1077 TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => {
1078 bug!("TODO: to_rustc for `{self:?}`")
1079 }
1080 }
1081 }
1082}
1083
1084impl_internable!(TyS, AdtDefData);
1085impl_slice_internable!(
1086 Ty,
1087 GenericArg,
1088 GenericParamDef,
1089 BoundVariableKind,
1090 Clause,
1091 Const,
1092 Binder<ExistentialPredicate>,
1093);
1094
1095impl fmt::Debug for ExistentialPredicate {
1096 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1097 match self {
1098 ExistentialPredicate::Trait(trait_ref) => write!(f, "{trait_ref:?}"),
1099 ExistentialPredicate::Projection(proj) => write!(f, "({proj:?})"),
1100 ExistentialPredicate::AutoTrait(def_id) => {
1101 write!(f, "{}", def_id_to_string(*def_id))
1102 }
1103 }
1104 }
1105}
1106
1107impl fmt::Debug for ExistentialTraitRef {
1108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1109 write!(f, "{}", def_id_to_string(self.def_id))?;
1110 if !self.args.is_empty() {
1111 write!(f, "<{:?}>", self.args.iter().format(","))?;
1112 }
1113 Ok(())
1114 }
1115}
1116
1117impl fmt::Debug for ExistentialProjection {
1118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1119 write!(f, "{}", def_id_to_string(self.def_id))?;
1120 if !self.args.is_empty() {
1121 write!(f, "<{:?}>", self.args.iter().format(","))?;
1122 }
1123 write!(f, " = {:?}", &self.term)
1124 }
1125}
1126
1127impl fmt::Debug for GenericArg {
1128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1129 match self {
1130 GenericArg::Ty(ty) => write!(f, "{ty:?}"),
1131 GenericArg::Lifetime(region) => write!(f, "{region:?}"),
1132 GenericArg::Const(c) => write!(f, "Const({c:?})"),
1133 }
1134 }
1135}
1136
1137impl fmt::Debug for Region {
1138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1139 write!(f, "{}", region_to_string(*self))
1140 }
1141}
1142
1143impl<T: fmt::Debug> fmt::Debug for Binder<T> {
1144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1145 if !self.1.is_empty() {
1146 write!(f, "for<{:?}> ", self.1.iter().format(", "))?;
1147 }
1148 write!(f, "{:?}", self.0)
1149 }
1150}
1151
1152impl fmt::Debug for FnSig {
1153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1154 write!(f, "fn({:?}) -> {:?}", self.inputs().iter().format(", "), self.output())
1155 }
1156}
1157
1158impl fmt::Debug for Ty {
1159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1160 match self.kind() {
1161 TyKind::Adt(adt_def, args) => {
1162 let adt_name = rustc_middle::ty::tls::with(|tcx| tcx.def_path_str(adt_def.did()));
1163 write!(f, "{adt_name}")?;
1164 if !args.is_empty() {
1165 write!(f, "<{:?}>", args.iter().format(", "))?;
1166 }
1167 Ok(())
1168 }
1169 TyKind::FnDef(def_id, args) => {
1170 write!(f, "FnDef({:?}[{:?}])", def_id, args.iter().format(", "))
1171 }
1172 TyKind::Bool => write!(f, "bool"),
1173 TyKind::Str => write!(f, "str"),
1174 TyKind::Char => write!(f, "char"),
1175 TyKind::Float(float_ty) => write!(f, "{}", float_ty.name_str()),
1176 TyKind::Int(int_ty) => write!(f, "{}", int_ty.name_str()),
1177 TyKind::Uint(uint_ty) => write!(f, "{}", uint_ty.name_str()),
1178 TyKind::Never => write!(f, "!"),
1179 TyKind::Param(param_ty) => write!(f, "{param_ty}"),
1180 TyKind::Ref(region, ty, Mutability::Mut) => write!(f, "&{region:?} mut {ty:?}"),
1181 TyKind::Ref(region, ty, Mutability::Not) => write!(f, "&{region:?} {ty:?}"),
1182 TyKind::Array(ty, c) => write!(f, "[{ty:?}; {c:?}]"),
1183 TyKind::Tuple(tys) => {
1184 if let [ty] = &tys[..] {
1185 write!(f, "({ty:?},)")
1186 } else {
1187 write!(f, "({:?})", tys.iter().format(", "))
1188 }
1189 }
1190 TyKind::Slice(ty) => write!(f, "[{ty:?}]"),
1191 TyKind::RawPtr(ty, Mutability::Mut) => write!(f, "*mut {ty:?}"),
1192 TyKind::RawPtr(ty, Mutability::Not) => write!(f, "*const {ty:?}"),
1193 TyKind::FnPtr(fn_sig) => write!(f, "{fn_sig:?}"),
1194 TyKind::Closure(did, args) => {
1195 write!(f, "{}", def_id_to_string(*did))?;
1196 if !args.is_empty() {
1197 write!(f, "<{:?}>", args.iter().format(", "))?;
1198 }
1199 Ok(())
1200 }
1201 TyKind::Coroutine(did, args) => {
1202 write!(f, "{}", def_id_to_string(*did))?;
1203 if !args.is_empty() {
1204 write!(f, "<{:?}>", args.iter().format(", "))?;
1205 }
1206 Ok(())
1207 }
1208 TyKind::CoroutineWitness(did, args) => {
1209 write!(f, "{}", def_id_to_string(*did))?;
1210 if !args.is_empty() {
1211 write!(f, "<{:?}>", args.iter().format(", "))?;
1212 }
1213 Ok(())
1214 }
1215 TyKind::Alias(AliasTy { kind: AliasKind::Opaque { def_id }, args }) => {
1216 write!(f, "{}", def_id_to_string(*def_id))?;
1217 if !args.is_empty() {
1218 write!(f, "<{:?}>", args.iter().format(", "))?;
1219 }
1220 Ok(())
1221 }
1222 TyKind::Alias(AliasTy { kind: AliasKind::Projection { def_id }, args }) => {
1223 write!(f, "Alias (Projection, {}, ", def_id_to_string(*def_id))?;
1224 if !args.is_empty() {
1225 write!(f, "<{:?}>", args.iter().format(", "))?;
1226 }
1227 write!(f, ")")?;
1228 Ok(())
1229 }
1230 TyKind::Alias(AliasTy { kind: AliasKind::Free { def_id }, args }) => {
1231 write!(f, "Alias (Free, {}, ", def_id_to_string(*def_id))?;
1232 if !args.is_empty() {
1233 write!(f, "<{:?}>", args.iter().format(", "))?;
1234 }
1235 write!(f, ")")?;
1236 Ok(())
1237 }
1238 TyKind::Dynamic(preds, r) => {
1239 write!(f, "dyn {:?} + {r:?}", preds.iter().format(", "))
1240 }
1241 TyKind::Foreign(def_id) => {
1242 write!(f, "Foreign {def_id:?}")
1243 }
1244 TyKind::Pat => todo!(),
1245 }
1246 }
1247}
1248
1249impl fmt::Debug for ValTree {
1250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1251 match &self {
1252 ValTree::Leaf(scalar_int) => write!(f, "Leaf({scalar_int})"),
1253 ValTree::Branch(vec) => write!(f, "Branch([{:?}])", vec.iter().format(", ")),
1254 }
1255 }
1256}
1257
1258impl fmt::Debug for Const {
1259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1260 match &self.kind {
1261 ConstKind::Param(p) => write!(f, "{}", p.name.as_str()),
1262 ConstKind::Value(_, v) => write!(f, "{v:?}"),
1263 ConstKind::Infer(infer_const) => write!(f, "{infer_const:?}"),
1264 ConstKind::Alias(uneval_const) => write!(f, "{uneval_const:?}"),
1265 }
1266 }
1267}
1268
1269pub fn region_to_string(region: Region) -> String {
1270 match region {
1271 Region::ReBound(debruijn, region) => {
1272 match region.kind {
1273 BoundRegionKind::Anon => "'<annon>".to_string(),
1274 BoundRegionKind::Named(_) => {
1275 format!("{debruijn:?}{region:?}")
1276 }
1277 BoundRegionKind::ClosureEnv => "'<env>".to_string(),
1278 BoundRegionKind::NamedForPrinting(sym) => format!("{sym}"),
1279 }
1280 }
1281 Region::ReEarlyParam(region) => region.name.to_string(),
1282 Region::ReStatic => "'static".to_string(),
1283 Region::ReVar(rvid) => format!("{rvid:?}"),
1284 Region::ReLateParam(..) => "'<free>".to_string(),
1285 Region::ReErased => "'_".to_string(),
1286 }
1287}