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