Skip to main content

charon_lib/ast/
types_utils.rs

1//! This file groups everything which is linked to implementations about [crate::types]
2use crate::ast::*;
3use crate::ids::IndexMap;
4use derive_generic_visitor::*;
5use itertools::Itertools;
6use std::borrow::Cow;
7use std::collections::HashSet;
8use std::convert::Infallible;
9use std::fmt::Debug;
10use std::iter::Iterator;
11use std::mem;
12
13impl TraitParam {
14    /// Constructs the trait ref that refers to this clause.
15    pub fn identity_tref(&self) -> TraitRef {
16        self.identity_tref_at_depth(DeBruijnId::zero())
17    }
18
19    /// Like `identity_tref` but uses variables bound at the given depth.
20    pub fn identity_tref_at_depth(&self, depth: DeBruijnId) -> TraitRef {
21        TraitRef::new(
22            TraitRefKind::Clause(DeBruijnVar::bound(depth, self.clause_id)),
23            self.trait_.clone().move_under_binders(depth),
24        )
25    }
26}
27
28impl GenericParams {
29    pub fn empty() -> Self {
30        Self::default()
31    }
32
33    pub fn is_empty(&self) -> bool {
34        self.len() == 0
35    }
36    /// Whether this has any explicit arguments (types, regions or const generics).
37    pub fn has_explicits(&self) -> bool {
38        !self.regions.is_empty() || !self.types.is_empty() || !self.const_generics.is_empty()
39    }
40    /// Whether this has any implicit arguments (trait clauses, outlives relations, associated type
41    /// equality constraints).
42    pub fn has_predicates(&self) -> bool {
43        !self.trait_clauses.is_empty()
44            || !self.types_outlive.is_empty()
45            || !self.regions_outlive.is_empty()
46            || !self.trait_type_constraints.is_empty()
47    }
48
49    /// Run some sanity checks.
50    pub fn check_consistency(&self) {
51        // Sanity check: check the clause ids are consistent.
52        assert!(
53            self.trait_clauses
54                .iter()
55                .enumerate()
56                .all(|(i, c)| c.clause_id.index() == i)
57        );
58
59        // Sanity check: region names are pairwise distinct (this caused trouble when generating
60        // names for the backward functions in Aeneas): at some point, Rustc introduced names equal
61        // to `Some("'_")` for the anonymous regions, instead of using `None` (we now check in
62        // [translate_region_name] and ignore names equal to "'_").
63        let mut s = HashSet::new();
64        for r in &self.regions {
65            if let Some(name) = &r.name {
66                assert!(
67                    !s.contains(name),
68                    "Name \"{}\" reused for two different lifetimes",
69                    name
70                );
71                s.insert(name);
72            }
73        }
74    }
75
76    pub fn len(&self) -> usize {
77        let GenericParams {
78            regions,
79            types,
80            const_generics,
81            trait_clauses,
82            regions_outlive,
83            types_outlive,
84            trait_type_constraints,
85        } = self;
86        regions.elem_count()
87            + types.elem_count()
88            + const_generics.elem_count()
89            + trait_clauses.elem_count()
90            + regions_outlive.len()
91            + types_outlive.len()
92            + trait_type_constraints.elem_count()
93    }
94
95    /// Construct a set of generic arguments in the scope of `self` that matches `self` and feeds
96    /// each required parameter with itself. E.g. given parameters for `<T, U> where U:
97    /// PartialEq<T>`, the arguments would be `<T, U>[@TraitClause0]`.
98    pub fn identity_args(&self) -> GenericArgs {
99        self.identity_args_at_depth(DeBruijnId::zero())
100    }
101
102    /// Like `identity_args` but uses variables bound at the given depth.
103    pub fn identity_args_at_depth(&self, depth: DeBruijnId) -> GenericArgs {
104        GenericArgs {
105            regions: self
106                .regions
107                .map_ref_indexed(|id, _| Region::Var(DeBruijnVar::bound(depth, id))),
108            types: self
109                .types
110                .map_ref_indexed(|id, _| TyKind::TypeVar(DeBruijnVar::bound(depth, id)).into_ty()),
111            const_generics: self.const_generics.map_ref_indexed(|id, c| ConstantExpr {
112                ty: c.ty.clone(),
113                kind: ConstantExprKind::Var(DeBruijnVar::bound(depth, id)),
114            }),
115            trait_refs: self
116                .trait_clauses
117                .map_ref(|clause| clause.identity_tref_at_depth(depth)),
118        }
119    }
120
121    /// Take the predicates from the another `GenericParams`. This assumes the clause ids etc are
122    /// already consistent.
123    pub fn take_predicates_from(&mut self, other: GenericParams) {
124        assert!(!other.has_explicits());
125        let num_clauses = self.trait_clauses.slot_count();
126        let GenericParams {
127            regions: _,
128            types: _,
129            const_generics: _,
130            trait_clauses,
131            regions_outlive,
132            types_outlive,
133            trait_type_constraints,
134        } = other;
135        self.trait_clauses
136            .extend(trait_clauses.into_iter().update(|clause| {
137                clause.clause_id += num_clauses;
138            }));
139        self.regions_outlive.extend(regions_outlive);
140        self.types_outlive.extend(types_outlive);
141        self.trait_type_constraints.extend(trait_type_constraints);
142    }
143
144    /// Take the predicates from the another `GenericParams`. This assumes that the two
145    /// `GenericParams` are independent, hence will shift clause ids if `other` has any
146    /// trait refs that reference its own clauses.
147    pub fn merge_predicates_from(&mut self, mut other: GenericParams) {
148        // Drop the explicits params.
149        other.types.clear();
150        other.regions.clear();
151        other.const_generics.clear();
152        // The contents of `other` may refer to its own trait clauses, so we must shift clause ids.
153        struct ShiftClausesVisitor(usize);
154        impl VarsVisitor for ShiftClausesVisitor {
155            fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
156                if let DeBruijnVar::Bound(DeBruijnId::ZERO, clause_id) = v {
157                    // Replace clause 0 and decrement the others.
158                    Some(TraitRefKind::Clause(DeBruijnVar::Bound(
159                        DeBruijnId::ZERO,
160                        clause_id + self.0,
161                    )))
162                } else {
163                    None
164                }
165            }
166        }
167        let num_clauses = self.trait_clauses.slot_count();
168        other.visit_vars(&mut ShiftClausesVisitor(num_clauses));
169        self.take_predicates_from(other);
170    }
171}
172
173impl<T> Binder<T> {
174    /// Wrap the value in an empty binder, shifting variables appropriately.
175    pub fn empty(kind: BinderKind, x: T) -> Self
176    where
177        T: TyVisitable,
178    {
179        Binder {
180            params: Default::default(),
181            skip_binder: x.move_under_binder(),
182            kind,
183        }
184    }
185    pub fn new(kind: BinderKind, params: GenericParams, skip_binder: T) -> Self {
186        Self {
187            params,
188            skip_binder,
189            kind,
190        }
191    }
192
193    /// Whether this binder binds any variables.
194    pub fn binds_anything(&self) -> bool {
195        !self.params.is_empty()
196    }
197
198    /// Retreive the contents of this binder if the binder binds no variables. This is the invers
199    /// of `Binder::empty`.
200    pub fn get_if_binds_nothing(&self) -> Option<T>
201    where
202        T: TyVisitable + Clone,
203    {
204        self.params
205            .is_empty()
206            .then(|| self.skip_binder.clone().move_from_under_binder().unwrap())
207    }
208
209    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Binder<U> {
210        Binder {
211            params: self.params,
212            skip_binder: f(self.skip_binder),
213            kind: self.kind.clone(),
214        }
215    }
216
217    pub fn map_ref<U>(&self, f: impl FnOnce(&T) -> U) -> Binder<U> {
218        Binder {
219            params: self.params.clone(),
220            skip_binder: f(&self.skip_binder),
221            kind: self.kind.clone(),
222        }
223    }
224
225    /// Substitute the provided arguments for the variables bound in this binder and return the
226    /// substituted inner value.
227    pub fn apply(self, args: &GenericArgs) -> T
228    where
229        T: TyVisitable,
230    {
231        self.skip_binder.substitute(args)
232    }
233}
234
235impl<T: AstVisitable> Binder<Binder<T>> {
236    /// Flatten two levels of binders into a single one.
237    pub fn flatten(self) -> Binder<T> {
238        #[derive(Visitor)]
239        struct FlattenVisitor<'a> {
240            shift_by: &'a GenericParams,
241            binder_depth: DeBruijnId,
242        }
243        impl VisitorWithBinderDepth for FlattenVisitor<'_> {
244            fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
245                &mut self.binder_depth
246            }
247        }
248        impl VisitAstMut for FlattenVisitor<'_> {
249            fn visit<'a, T: AstVisitable>(&'a mut self, x: &mut T) -> ControlFlow<Self::Break> {
250                VisitWithBinderDepth::new(self).visit(x)
251            }
252
253            fn enter_de_bruijn_id(&mut self, db_id: &mut DeBruijnId) {
254                if *db_id > self.binder_depth {
255                    // We started visiting at the inner binder, so in this branch we're either
256                    // mentioning the outer binder or a binder further beyond. Either way we
257                    // decrease the depth; variables that point to the outer binder don't have to
258                    // be shifted.
259                    *db_id = db_id.decr();
260                }
261            }
262            fn enter_region(&mut self, x: &mut Region) {
263                if let Region::Var(var) = x
264                    && let Some(id) = var.bound_at_depth_mut(self.binder_depth)
265                {
266                    *id += self.shift_by.regions.slot_count();
267                }
268            }
269            fn enter_ty_kind(&mut self, x: &mut TyKind) {
270                if let TyKind::TypeVar(var) = x
271                    && let Some(id) = var.bound_at_depth_mut(self.binder_depth)
272                {
273                    *id += self.shift_by.types.slot_count();
274                }
275            }
276            fn enter_constant_expr(&mut self, x: &mut ConstantExpr) {
277                if let ConstantExprKind::Var(ref mut var) = x.kind
278                    && let Some(id) = var.bound_at_depth_mut(self.binder_depth)
279                {
280                    *id += self.shift_by.const_generics.slot_count();
281                }
282            }
283            fn enter_trait_ref_kind(&mut self, x: &mut TraitRefKind) {
284                if let TraitRefKind::Clause(var) = x
285                    && let Some(id) = var.bound_at_depth_mut(self.binder_depth)
286                {
287                    *id += self.shift_by.trait_clauses.slot_count();
288                }
289            }
290        }
291
292        // We will concatenate both sets of params.
293        let mut outer_params = self.params;
294
295        // The inner value needs to change:
296        // - at binder level 0 we shift all variable ids to match the concatenated params;
297        // - at binder level > 0 we decrease binding level because there's one fewer binder.
298        let mut bound_value = self.skip_binder.skip_binder;
299        let _ = bound_value.drive_mut(&mut FlattenVisitor {
300            shift_by: &outer_params,
301            binder_depth: Default::default(),
302        });
303
304        // The inner params must also be updated, as they can refer to themselves and the outer
305        // one.
306        let mut inner_params = self.skip_binder.params;
307        let _ = inner_params.drive_mut(&mut FlattenVisitor {
308            shift_by: &outer_params,
309            binder_depth: Default::default(),
310        });
311        inner_params
312            .regions
313            .iter_mut()
314            .for_each(|v| v.index += outer_params.regions.slot_count());
315        inner_params
316            .types
317            .iter_mut()
318            .for_each(|v| v.index += outer_params.types.slot_count());
319        inner_params
320            .const_generics
321            .iter_mut()
322            .for_each(|v| v.index += outer_params.const_generics.slot_count());
323        inner_params
324            .trait_clauses
325            .iter_mut()
326            .for_each(|v| v.clause_id += outer_params.trait_clauses.slot_count());
327
328        let GenericParams {
329            regions,
330            types,
331            const_generics,
332            trait_clauses,
333            regions_outlive,
334            types_outlive,
335            trait_type_constraints,
336        } = &inner_params;
337        outer_params.regions.extend_from_slice(regions);
338        outer_params.types.extend_from_slice(types);
339        outer_params
340            .const_generics
341            .extend_from_slice(const_generics);
342        outer_params.trait_clauses.extend_from_slice(trait_clauses);
343        outer_params
344            .regions_outlive
345            .extend_from_slice(regions_outlive);
346        outer_params.types_outlive.extend_from_slice(types_outlive);
347        outer_params
348            .trait_type_constraints
349            .extend_from_slice(trait_type_constraints);
350
351        Binder {
352            params: outer_params,
353            skip_binder: bound_value,
354            kind: BinderKind::Other,
355        }
356    }
357}
358
359impl<T> RegionBinder<T> {
360    /// Wrap the value in an empty region binder, shifting variables appropriately.
361    pub fn empty(x: T) -> Self
362    where
363        T: TyVisitable,
364    {
365        RegionBinder {
366            regions: Default::default(),
367            skip_binder: x.move_under_binder(),
368        }
369    }
370
371    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> RegionBinder<U> {
372        RegionBinder {
373            regions: self.regions,
374            skip_binder: f(self.skip_binder),
375        }
376    }
377
378    pub fn map_ref<U>(&self, f: impl FnOnce(&T) -> U) -> RegionBinder<U> {
379        RegionBinder {
380            regions: self.regions.clone(),
381            skip_binder: f(&self.skip_binder),
382        }
383    }
384
385    /// Substitute the bound variables with the given lifetimes.
386    pub fn apply(self, regions: IndexMap<RegionId, Region>) -> T
387    where
388        T: TyVisitable,
389    {
390        assert_eq!(regions.slot_count(), self.regions.slot_count());
391        let args = GenericArgs {
392            regions,
393            ..GenericArgs::empty()
394        };
395        self.skip_binder.substitute(&args)
396    }
397
398    /// Substitute the bound variables with erased lifetimes.
399    pub fn erase(self) -> T
400    where
401        T: TyVisitable,
402    {
403        let regions = self.regions.map_ref_indexed(|_, _| Region::Erased);
404        self.apply(regions)
405    }
406}
407
408impl GenericArgs {
409    pub fn len(&self) -> usize {
410        let GenericArgs {
411            regions,
412            types,
413            const_generics,
414            trait_refs,
415        } = self;
416        regions.elem_count()
417            + types.elem_count()
418            + const_generics.elem_count()
419            + trait_refs.elem_count()
420    }
421
422    pub fn is_empty(&self) -> bool {
423        self.len() == 0
424    }
425    /// Whether this has any explicit arguments (types, regions or const generics).
426    pub fn has_explicits(&self) -> bool {
427        !self.regions.is_empty() || !self.types.is_empty() || !self.const_generics.is_empty()
428    }
429    /// Whether this has any implicit arguments (trait refs).
430    pub fn has_implicits(&self) -> bool {
431        !self.trait_refs.is_empty()
432    }
433
434    pub fn empty() -> Self {
435        GenericArgs {
436            regions: Default::default(),
437            types: Default::default(),
438            const_generics: Default::default(),
439            trait_refs: Default::default(),
440        }
441    }
442
443    pub fn new_for_builtin(types: IndexMap<TypeVarId, Ty>) -> Self {
444        GenericArgs {
445            types,
446            ..Self::empty()
447        }
448    }
449
450    pub fn new(
451        regions: IndexMap<RegionId, Region>,
452        types: IndexMap<TypeVarId, Ty>,
453        const_generics: IndexMap<ConstGenericVarId, ConstantExpr>,
454        trait_refs: IndexMap<TraitClauseId, TraitRef>,
455    ) -> Self {
456        Self {
457            regions,
458            types,
459            const_generics,
460            trait_refs,
461        }
462    }
463
464    pub fn new_types(types: IndexMap<TypeVarId, Ty>) -> Self {
465        Self {
466            types,
467            ..Self::empty()
468        }
469    }
470
471    /// Check whether this matches the given `GenericParams`.
472    /// TODO: check more things, e.g. that the trait refs use the correct trait and generics.
473    pub fn matches(&self, params: &GenericParams) -> bool {
474        params.regions.elem_count() == self.regions.elem_count()
475            && params.types.elem_count() == self.types.elem_count()
476            && params.const_generics.elem_count() == self.const_generics.elem_count()
477            && params.trait_clauses.elem_count() == self.trait_refs.elem_count()
478    }
479
480    /// Return the same generics, but where we pop the first type arguments.
481    /// This is useful for trait references (for pretty printing for instance),
482    /// because the first type argument is the type for which the trait is
483    /// implemented.
484    pub fn pop_first_type_arg(&self) -> (Ty, Self) {
485        let mut generics = self.clone();
486        let mut it = mem::take(&mut generics.types).into_iter();
487        let ty = it.next().unwrap();
488        generics.types = it.collect();
489        (ty, generics)
490    }
491
492    /// Concatenate this set of arguments with another one. Use with care, you must manage the
493    /// order of arguments correctly.
494    pub fn concat(mut self, other: &Self) -> Self {
495        let Self {
496            regions,
497            types,
498            const_generics,
499            trait_refs,
500        } = other;
501        self.regions.extend_from_slice(regions);
502        self.types.extend_from_slice(types);
503        self.const_generics.extend_from_slice(const_generics);
504        self.trait_refs.extend_from_slice(trait_refs);
505        self
506    }
507}
508
509impl IntTy {
510    /// Important: this returns the target byte count for the types.
511    /// Must not be used for host types from rustc.
512    pub fn target_size(&self, ptr_size: ByteCount) -> usize {
513        match self {
514            IntTy::Isize => ptr_size as usize,
515            IntTy::I8 => size_of::<i8>(),
516            IntTy::I16 => size_of::<i16>(),
517            IntTy::I32 => size_of::<i32>(),
518            IntTy::I64 => size_of::<i64>(),
519            IntTy::I128 => size_of::<i128>(),
520        }
521    }
522}
523impl UIntTy {
524    /// Important: this returns the target byte count for the types.
525    /// Must not be used for host types from rustc.
526    pub fn target_size(&self, ptr_size: ByteCount) -> usize {
527        match self {
528            UIntTy::Usize => ptr_size as usize,
529            UIntTy::U8 => size_of::<u8>(),
530            UIntTy::U16 => size_of::<u16>(),
531            UIntTy::U32 => size_of::<u32>(),
532            UIntTy::U64 => size_of::<u64>(),
533            UIntTy::U128 => size_of::<u128>(),
534        }
535    }
536}
537impl FloatTy {
538    /// Important: this returns the target byte count for the types.
539    /// Must not be used for host types from rustc.
540    pub fn target_size(&self) -> usize {
541        match self {
542            FloatTy::F16 => size_of::<u16>(),
543            FloatTy::F32 => size_of::<u32>(),
544            FloatTy::F64 => size_of::<u64>(),
545            FloatTy::F128 => size_of::<u128>(),
546        }
547    }
548}
549
550impl IntegerTy {
551    pub fn to_unsigned(&self) -> Self {
552        match self {
553            IntegerTy::Signed(IntTy::Isize) => IntegerTy::Unsigned(UIntTy::Usize),
554            IntegerTy::Signed(IntTy::I8) => IntegerTy::Unsigned(UIntTy::U8),
555            IntegerTy::Signed(IntTy::I16) => IntegerTy::Unsigned(UIntTy::U16),
556            IntegerTy::Signed(IntTy::I32) => IntegerTy::Unsigned(UIntTy::U32),
557            IntegerTy::Signed(IntTy::I64) => IntegerTy::Unsigned(UIntTy::U64),
558            IntegerTy::Signed(IntTy::I128) => IntegerTy::Unsigned(UIntTy::U128),
559            _ => *self,
560        }
561    }
562
563    /// Important: this returns the target byte count for the types.
564    /// Must not be used for host types from rustc.
565    pub fn target_size(&self, ptr_size: ByteCount) -> usize {
566        match self {
567            IntegerTy::Signed(ty) => ty.target_size(ptr_size),
568            IntegerTy::Unsigned(ty) => ty.target_size(ptr_size),
569        }
570    }
571}
572
573impl LiteralTy {
574    pub fn to_integer_ty(&self) -> Option<IntegerTy> {
575        match self {
576            Self::Int(int_ty) => Some(IntegerTy::Signed(*int_ty)),
577            Self::UInt(uint_ty) => Some(IntegerTy::Unsigned(*uint_ty)),
578            _ => None,
579        }
580    }
581
582    /// Important: this returns the target byte count for the types.
583    /// Must not be used for host types from rustc.
584    pub fn target_size(&self, ptr_size: ByteCount) -> usize {
585        match self {
586            LiteralTy::Int(int_ty) => int_ty.target_size(ptr_size),
587            LiteralTy::UInt(uint_ty) => uint_ty.target_size(ptr_size),
588            LiteralTy::Float(float_ty) => float_ty.target_size(),
589            LiteralTy::Char => 4,
590            LiteralTy::Bool => 1,
591        }
592    }
593}
594
595impl From<LiteralTy> for Ty {
596    fn from(value: LiteralTy) -> Self {
597        TyKind::Literal(value).into_ty()
598    }
599}
600
601/// A value of type `T` bound by the generic parameters of item
602/// `item`. Used when dealing with multiple items at a time, to
603/// ensure we don't mix up generics.
604///
605/// To get the value, use `under_binder_of` or `subst_for`.
606#[derive(Debug, Clone, Copy)]
607pub struct ItemBinder<ItemId, T> {
608    pub item_id: ItemId,
609    val: T,
610}
611
612impl<ItemId, T> ItemBinder<ItemId, T>
613where
614    ItemId: Debug + Copy + PartialEq,
615{
616    pub fn new(item_id: ItemId, val: T) -> Self {
617        Self { item_id, val }
618    }
619
620    pub fn as_ref(&self) -> ItemBinder<ItemId, &T> {
621        ItemBinder {
622            item_id: self.item_id,
623            val: &self.val,
624        }
625    }
626
627    pub fn map_bound<U>(self, f: impl FnOnce(T) -> U) -> ItemBinder<ItemId, U> {
628        ItemBinder {
629            item_id: self.item_id,
630            val: f(self.val),
631        }
632    }
633
634    fn assert_item_id(&self, item_id: ItemId) {
635        assert_eq!(
636            self.item_id, item_id,
637            "Trying to use item bound for {:?} as if it belonged to {:?}",
638            self.item_id, item_id
639        );
640    }
641
642    /// Assert that the value is bound for item `item_id`, and returns it. This is used when we
643    /// plan to store the returned value inside that item.
644    pub fn under_binder_of(self, item_id: ItemId) -> T {
645        self.assert_item_id(item_id);
646        self.val
647    }
648
649    /// Given generic args for `item_id`, assert that the value is bound for `item_id` and
650    /// substitute it with the provided generic arguments. Because the arguments are bound in the
651    /// context of another item, so it the resulting substituted value.
652    pub fn substitute<OtherItem: Debug + Copy + PartialEq>(
653        self,
654        args: ItemBinder<OtherItem, &GenericArgs>,
655    ) -> ItemBinder<OtherItem, T>
656    where
657        ItemId: Into<ItemId>,
658        T: TyVisitable,
659    {
660        args.map_bound(|args| self.val.substitute(args))
661    }
662}
663
664/// Dummy item identifier that represents the current item when not ambiguous.
665#[derive(Debug, Clone, Copy, PartialEq, Eq)]
666pub struct CurrentItem;
667
668impl<T> ItemBinder<CurrentItem, T> {
669    pub fn under_current_binder(self) -> T {
670        self.val
671    }
672}
673
674impl Ty {
675    pub fn new(kind: TyKind) -> Self {
676        Ty(HashConsed::new(kind))
677    }
678
679    pub fn kind(&self) -> &TyKind {
680        self.0.inner()
681    }
682
683    pub fn with_kind_mut<R>(&mut self, f: impl FnOnce(&mut TyKind) -> R) -> R {
684        self.0.with_inner_mut(f)
685    }
686
687    /// Return the unit type
688    pub fn mk_unit() -> Ty {
689        Self::mk_tuple(vec![])
690    }
691
692    pub fn mk_bool() -> Ty {
693        TyKind::Literal(LiteralTy::Bool).into()
694    }
695
696    pub fn mk_usize() -> Ty {
697        TyKind::Literal(LiteralTy::UInt(UIntTy::Usize)).into()
698    }
699
700    pub fn mk_tuple(tys: Vec<Ty>) -> Ty {
701        TyKind::Adt(TypeDeclRef {
702            id: TypeId::Tuple,
703            generics: Box::new(GenericArgs::new_for_builtin(tys.into())),
704        })
705        .into_ty()
706    }
707
708    pub fn mk_array(ty: Ty, len: ConstantExpr) -> Ty {
709        TyKind::Array(ty, Box::new(len)).into_ty()
710    }
711
712    pub fn mk_slice(ty: Ty) -> Ty {
713        TyKind::Slice(ty).into_ty()
714    }
715    /// Return true if it is actually unit (i.e.: 0-tuple)
716    pub fn is_unit(&self) -> bool {
717        match self.as_tuple() {
718            Some(tys) => tys.is_empty(),
719            None => false,
720        }
721    }
722
723    /// Return true if this is a scalar type
724    pub fn is_scalar(&self) -> bool {
725        match self.kind() {
726            TyKind::Literal(kind) => kind.is_int() || kind.is_uint(),
727            _ => false,
728        }
729    }
730
731    pub fn is_unsigned_scalar(&self) -> bool {
732        matches!(self.kind(), TyKind::Literal(LiteralTy::UInt(_)))
733    }
734
735    pub fn is_signed_scalar(&self) -> bool {
736        matches!(self.kind(), TyKind::Literal(LiteralTy::Int(_)))
737    }
738
739    pub fn is_str(&self) -> bool {
740        match self.kind() {
741            TyKind::Adt(ty_ref) if let TypeId::Builtin(BuiltinTy::Str) = ty_ref.id => true,
742            _ => false,
743        }
744    }
745
746    /// Return true if the type is Box
747    pub fn is_box(&self) -> bool {
748        match self.kind() {
749            TyKind::Adt(ty_ref) if let TypeId::Builtin(BuiltinTy::Box) = ty_ref.id => true,
750            _ => false,
751        }
752    }
753
754    pub fn as_box(&self) -> Option<&Ty> {
755        match self.kind() {
756            TyKind::Adt(ty_ref) if let TypeId::Builtin(BuiltinTy::Box) = ty_ref.id => {
757                Some(&ty_ref.generics.types[0])
758            }
759            _ => None,
760        }
761    }
762
763    pub fn get_ptr_metadata(&self, translated: &TranslatedCrate) -> PtrMetadata {
764        let ref ty_decls = translated.type_decls;
765        match self.kind() {
766            TyKind::Adt(ty_ref) => {
767                // there are two cases:
768                // 1. if the declared type has a fixed metadata, just returns it
769                // 2. if it depends on some other types or the generic itself
770                match ty_ref.id {
771                    TypeId::Adt(type_decl_id) => {
772                        let Some(decl) = ty_decls.get(type_decl_id) else {
773                            return PtrMetadata::InheritFrom(self.clone());
774                        };
775                        match decl.ptr_metadata.clone().substitute(&ty_ref.generics) {
776                            // if it depends on some type, recursion with the binding env
777                            PtrMetadata::InheritFrom(ty) => ty.get_ptr_metadata(translated),
778                            // otherwise, simply return it
779                            meta => meta,
780                        }
781                    }
782                    // the metadata of a tuple is simply the last field
783                    TypeId::Tuple => {
784                        match ty_ref.generics.types.iter().last() {
785                            // `None` refers to the unit type `()`
786                            None => PtrMetadata::None,
787                            // Otherwise, simply recurse
788                            Some(ty) => ty.get_ptr_metadata(translated),
789                        }
790                    }
791                    // Box is a pointer like ref & raw ptr, hence no metadata
792                    TypeId::Builtin(BuiltinTy::Box) => PtrMetadata::None,
793                    // `str` has metadata length
794                    TypeId::Builtin(BuiltinTy::Str) => PtrMetadata::Length,
795                }
796            }
797            TyKind::DynTrait(pred) => match pred.vtable_ref(translated) {
798                Some(vtable) => PtrMetadata::VTable(vtable),
799                None => PtrMetadata::InheritFrom(self.clone()),
800            },
801            // `[T]` has metadata length
802            TyKind::Slice(..) => PtrMetadata::Length,
803            TyKind::TraitType(..) | TyKind::TypeVar(_) => PtrMetadata::InheritFrom(self.clone()),
804            TyKind::Literal(_)
805            | TyKind::Never
806            | TyKind::Ref(..)
807            | TyKind::RawPtr(..)
808            | TyKind::FnPtr(..)
809            | TyKind::FnDef(..)
810            | TyKind::Array(..)
811            | TyKind::Error(_) => PtrMetadata::None,
812            // The metadata itself must be Sized, hence must with `PtrMetadata::None`
813            TyKind::PtrMetadata(_) => PtrMetadata::None,
814        }
815    }
816
817    pub fn as_ref_or_ptr(&self) -> Option<&Ty> {
818        match self.kind() {
819            TyKind::RawPtr(ty, _) | TyKind::Ref(_, ty, _) => Some(ty),
820            _ => None,
821        }
822    }
823
824    pub fn as_array_or_slice(&self) -> Option<&Ty> {
825        match self.kind() {
826            TyKind::Slice(ty) | TyKind::Array(ty, _) => Some(ty),
827            _ => None,
828        }
829    }
830
831    pub fn as_tuple(&self) -> Option<&IndexMap<TypeVarId, Ty>> {
832        match self.kind() {
833            TyKind::Adt(ty_ref) if let TypeId::Tuple = ty_ref.id => Some(&ty_ref.generics.types),
834            _ => None,
835        }
836    }
837
838    pub fn as_adt(&self) -> Option<&TypeDeclRef> {
839        self.kind().as_adt()
840    }
841}
842
843impl TyKind {
844    pub fn into_ty(self) -> Ty {
845        Ty::new(self)
846    }
847}
848
849impl From<TyKind> for Ty {
850    fn from(kind: TyKind) -> Ty {
851        kind.into_ty()
852    }
853}
854
855/// Convenience for migration purposes.
856impl std::ops::Deref for Ty {
857    type Target = TyKind;
858
859    fn deref(&self) -> &Self::Target {
860        self.kind()
861    }
862}
863/// For deref patterns.
864unsafe impl std::ops::DerefPure for Ty {}
865
866impl TypeDeclRef {
867    pub fn new(id: TypeId, generics: GenericArgs) -> Self {
868        Self {
869            id,
870            generics: Box::new(generics),
871        }
872    }
873}
874
875impl TraitDeclRef {
876    pub fn self_ty<'a>(&'a self, krate: &'a TranslatedCrate) -> Option<&'a Ty> {
877        match self.generics.types.iter().next() {
878            Some(ty) => return Some(ty),
879            // TODO(mono): A monomorphized trait takes no arguments.
880            None => {
881                let name = krate.item_name(self.id)?;
882                let args = name.name.last()?.as_monomorphized()?;
883                args.types.iter().next()
884            }
885        }
886    }
887}
888
889impl TraitRef {
890    pub fn new(kind: TraitRefKind, trait_decl_ref: PolyTraitDeclRef) -> Self {
891        TraitRefContents {
892            kind,
893            trait_decl_ref,
894        }
895        .intern()
896    }
897
898    pub fn new_builtin(
899        trait_id: TraitDeclId,
900        ty: Ty,
901        parents: IndexMap<TraitClauseId, TraitRef>,
902        builtin_data: BuiltinImplData,
903    ) -> Self {
904        let trait_decl_ref = RegionBinder::empty(TraitDeclRef {
905            id: trait_id,
906            generics: Box::new(GenericArgs::new_types([ty].into())),
907        });
908        Self::new(
909            TraitRefKind::BuiltinOrAuto {
910                builtin_data,
911                parent_trait_refs: parents,
912                types: Default::default(),
913            },
914            trait_decl_ref,
915        )
916    }
917
918    /// Get mutable access to the contents. This cloned the value and will re-intern the modified
919    /// value at the end of the function.
920    pub fn with_contents_mut<R>(&mut self, f: impl FnOnce(&mut TraitRefContents) -> R) -> R {
921        self.0.with_inner_mut(f)
922    }
923}
924impl TraitRefContents {
925    pub fn intern(self) -> TraitRef {
926        TraitRef(HashConsed::new(self))
927    }
928}
929
930impl std::ops::Deref for TraitRef {
931    type Target = TraitRefContents;
932    fn deref(&self) -> &Self::Target {
933        &self.0
934    }
935}
936
937impl BuiltinImplData {
938    pub fn as_closure_kind(&self) -> Option<ClosureKind> {
939        match self {
940            BuiltinImplData::FnOnce => Some(ClosureKind::FnOnce),
941            BuiltinImplData::FnMut => Some(ClosureKind::FnMut),
942            BuiltinImplData::Fn => Some(ClosureKind::Fn),
943            _ => None,
944        }
945    }
946}
947
948impl PtrMetadata {
949    pub fn into_type(self) -> Ty {
950        match self {
951            PtrMetadata::None => Ty::mk_unit(),
952            PtrMetadata::Length => Ty::mk_usize(),
953            PtrMetadata::VTable(type_decl_ref) => Ty::new(TyKind::Ref(
954                Region::Static,
955                Ty::new(TyKind::Adt(type_decl_ref)),
956                RefKind::Shared,
957            )),
958            PtrMetadata::InheritFrom(ty) => Ty::new(TyKind::PtrMetadata(ty)),
959        }
960    }
961}
962
963impl Field {
964    /// The new name for this field, as suggested by the `#[charon::rename]` attribute.
965    pub fn renamed_name(&self) -> Option<&str> {
966        self.attr_info.rename.as_deref().or(self.name.as_deref())
967    }
968
969    /// Whether this field has a `#[charon::opaque]` annotation.
970    pub fn is_opaque(&self) -> bool {
971        self.attr_info
972            .attributes
973            .iter()
974            .any(|attr| attr.is_opaque())
975    }
976}
977
978impl Variant {
979    /// The new name for this variant, as suggested by the `#[charon::rename]` and
980    /// `#[charon::variants_prefix]` attributes.
981    pub fn renamed_name(&self) -> &str {
982        self.attr_info
983            .rename
984            .as_deref()
985            .unwrap_or(self.name.as_ref())
986    }
987
988    /// Whether this variant has a `#[charon::opaque]` annotation.
989    pub fn is_opaque(&self) -> bool {
990        self.attr_info
991            .attributes
992            .iter()
993            .any(|attr| attr.is_opaque())
994    }
995}
996
997impl DynPredicate {
998    /// Get a reference to the vtable type that corresponds to this predicate.
999    pub fn vtable_ref(&self, translated: &TranslatedCrate) -> Option<TypeDeclRef> {
1000        // The first clause is the one relevant for the vtable.
1001        let relevant_tref = self.binder.params.trait_clauses[0].trait_.clone().erase();
1002
1003        // Get the vtable ref from the trait decl
1004        let trait_decl = translated.trait_decls.get(relevant_tref.id)?;
1005        let vtable_ref = trait_decl
1006            .vtable
1007            .clone()?
1008            .substitute(&relevant_tref.generics);
1009        Some(vtable_ref)
1010    }
1011}
1012
1013impl RefKind {
1014    pub fn mutable(x: bool) -> Self {
1015        if x { Self::Mut } else { Self::Shared }
1016    }
1017}
1018
1019/// Visitor for type-level variables. Used to visit the variables contained in a value, as seen
1020/// from the outside of the value. This means that any variable bound inside the value will be
1021/// skipped, and all the seen De Bruijn indices will count from the outside of the value. The
1022/// returned value, if any, will be put in place of the variable.
1023pub trait VarsVisitor {
1024    fn visit_erased_region(&mut self) -> Option<Region> {
1025        None
1026    }
1027    fn visit_region_var(&mut self, _v: RegionDbVar) -> Option<Region> {
1028        None
1029    }
1030    fn visit_type_var(&mut self, _v: TypeDbVar) -> Option<Ty> {
1031        None
1032    }
1033    fn visit_const_generic_var(&mut self, _v: ConstGenericDbVar) -> Option<ConstantExprKind> {
1034        None
1035    }
1036    fn visit_clause_var(&mut self, _v: ClauseDbVar) -> Option<TraitRefKind> {
1037        None
1038    }
1039    fn visit_self_clause(&mut self) -> Option<TraitRefKind> {
1040        None
1041    }
1042}
1043
1044/// Visitor for the [TyVisitable::substitute] function.
1045/// This substitutes variables bound at the level where we start to substitute (level 0).
1046#[derive(Visitor)]
1047pub(crate) struct SubstVisitor<'a> {
1048    generics: &'a GenericArgs,
1049    self_ref: &'a TraitRefKind,
1050    /// Whether to substitute explicit variables only (types, regions, const generics).
1051    explicits_only: bool,
1052    had_error: bool,
1053}
1054impl<'a> SubstVisitor<'a> {
1055    pub(crate) fn new(
1056        generics: &'a GenericArgs,
1057        self_ref: &'a TraitRefKind,
1058        explicits_only: bool,
1059    ) -> Self {
1060        Self {
1061            generics,
1062            self_ref,
1063            explicits_only,
1064            had_error: false,
1065        }
1066    }
1067
1068    pub fn visit<T: TyVisitable>(mut self, mut x: T) -> Result<T, GenericsMismatch> {
1069        let _ = x.visit_vars(&mut self);
1070        if self.had_error {
1071            Err(GenericsMismatch)
1072        } else {
1073            Ok(x)
1074        }
1075    }
1076
1077    /// Returns the value for this variable, if any.
1078    fn process_var<Id, T>(
1079        &mut self,
1080        var: DeBruijnVar<Id>,
1081        get: impl Fn(Id) -> Option<&'a T>,
1082    ) -> Option<T>
1083    where
1084        Id: Copy,
1085        T: Clone + TyVisitable,
1086        DeBruijnVar<Id>: Into<T>,
1087    {
1088        match var {
1089            DeBruijnVar::Bound(dbid, varid) => {
1090                Some(if let Some(dbid) = dbid.sub(DeBruijnId::one()) {
1091                    // This is bound outside the binder we're substituting for.
1092                    DeBruijnVar::Bound(dbid, varid).into()
1093                } else {
1094                    match get(varid) {
1095                        Some(v) => v.clone(),
1096                        None => {
1097                            self.had_error = true;
1098                            return None;
1099                        }
1100                    }
1101                })
1102            }
1103            DeBruijnVar::Free(..) => None,
1104        }
1105    }
1106}
1107impl VarsVisitor for SubstVisitor<'_> {
1108    fn visit_region_var(&mut self, v: RegionDbVar) -> Option<Region> {
1109        self.process_var(v, |id| self.generics.regions.get(id))
1110    }
1111    fn visit_type_var(&mut self, v: TypeDbVar) -> Option<Ty> {
1112        self.process_var(v, |id| self.generics.types.get(id))
1113    }
1114    fn visit_const_generic_var(&mut self, v: ConstGenericDbVar) -> Option<ConstantExprKind> {
1115        self.process_var(v, |id| {
1116            self.generics.const_generics.get(id).map(|c| &c.kind)
1117        })
1118    }
1119    fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
1120        if self.explicits_only {
1121            None
1122        } else {
1123            self.process_var(v, |id| Some(&self.generics.trait_refs.get(id)?.kind))
1124        }
1125    }
1126    fn visit_self_clause(&mut self) -> Option<TraitRefKind> {
1127        Some(self.self_ref.clone())
1128    }
1129}
1130
1131#[derive(Debug)]
1132pub struct GenericsMismatch;
1133
1134/// Types that are involved at the type-level and may be substituted around.
1135pub trait TyVisitable: Sized + AstVisitable {
1136    /// Visit the variables contained in `self`, as seen from the outside of `self`. This means
1137    /// that any variable bound inside `self` will be skipped, and all the seen De Bruijn indices
1138    /// will count from the outside of `self`.
1139    fn visit_vars(&mut self, v: &mut impl VarsVisitor) {
1140        #[derive(Visitor)]
1141        struct Wrap<'v, V> {
1142            v: &'v mut V,
1143            depth: DeBruijnId,
1144        }
1145        impl<V> VisitorWithBinderDepth for Wrap<'_, V> {
1146            fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
1147                &mut self.depth
1148            }
1149        }
1150        impl<V: VarsVisitor> VisitAstMut for Wrap<'_, V> {
1151            fn visit<'a, T: AstVisitable>(&'a mut self, x: &mut T) -> ControlFlow<Self::Break> {
1152                VisitWithBinderDepth::new(self).visit(x)
1153            }
1154
1155            fn exit_region(&mut self, r: &mut Region) {
1156                match r {
1157                    Region::Var(var)
1158                        if let Some(var) = var.move_out_from_depth(self.depth)
1159                            && let Some(new_r) = self.v.visit_region_var(var) =>
1160                    {
1161                        *r = new_r.move_under_binders(self.depth);
1162                    }
1163                    Region::Erased | Region::Body(..)
1164                        if let Some(new_r) = self.v.visit_erased_region() =>
1165                    {
1166                        *r = new_r.move_under_binders(self.depth);
1167                    }
1168                    _ => (),
1169                }
1170            }
1171            fn exit_ty(&mut self, ty: &mut Ty) {
1172                if let TyKind::TypeVar(var) = ty.kind()
1173                    && let Some(var) = var.move_out_from_depth(self.depth)
1174                    && let Some(new_ty) = self.v.visit_type_var(var)
1175                {
1176                    *ty = new_ty.move_under_binders(self.depth);
1177                }
1178            }
1179            fn exit_constant_expr(&mut self, ce: &mut ConstantExpr) {
1180                if let ConstantExprKind::Var(var) = &mut ce.kind
1181                    && let Some(var) = var.move_out_from_depth(self.depth)
1182                    && let Some(new_cg) = self.v.visit_const_generic_var(var)
1183                {
1184                    ce.kind = new_cg.move_under_binders(self.depth);
1185                }
1186            }
1187            fn exit_trait_ref_kind(&mut self, kind: &mut TraitRefKind) {
1188                match kind {
1189                    TraitRefKind::SelfId => {
1190                        if let Some(new_kind) = self.v.visit_self_clause() {
1191                            *kind = new_kind.move_under_binders(self.depth);
1192                        }
1193                    }
1194                    TraitRefKind::Clause(var) => {
1195                        if let Some(var) = var.move_out_from_depth(self.depth)
1196                            && let Some(new_kind) = self.v.visit_clause_var(var)
1197                        {
1198                            *kind = new_kind.move_under_binders(self.depth);
1199                        }
1200                    }
1201                    _ => {}
1202                }
1203            }
1204        }
1205        Wrap {
1206            v,
1207            depth: DeBruijnId::zero(),
1208        }
1209        .visit(self);
1210    }
1211
1212    /// Substitute the generic variables inside `self` by replacing them with the provided values.
1213    /// Note: if `self` is an item that comes from a `TraitDecl`, you most likely want to use
1214    /// `substitute_with_self`.
1215    fn substitute(self, generics: &GenericArgs) -> Self {
1216        self.substitute_with_self(generics, &TraitRefKind::SelfId)
1217    }
1218    /// Substitute only the type, region and const generic args.
1219    fn substitute_explicits(self, generics: &GenericArgs) -> Self {
1220        SubstVisitor::new(generics, &TraitRefKind::SelfId, true)
1221            .visit(self)
1222            .unwrap()
1223    }
1224    /// Substitute the generic variables as well as the `TraitRefKind::Self` trait ref.
1225    fn substitute_with_self(self, generics: &GenericArgs, self_ref: &TraitRefKind) -> Self {
1226        self.try_substitute_with_self(generics, self_ref).unwrap()
1227    }
1228
1229    fn try_substitute(self, generics: &GenericArgs) -> Result<Self, GenericsMismatch> {
1230        self.try_substitute_with_self(generics, &TraitRefKind::SelfId)
1231    }
1232    fn try_substitute_with_self(
1233        self,
1234        generics: &GenericArgs,
1235        self_ref: &TraitRefKind,
1236    ) -> Result<Self, GenericsMismatch> {
1237        SubstVisitor::new(generics, self_ref, false).visit(self)
1238    }
1239
1240    /// Move under one binder.
1241    fn move_under_binder(self) -> Self {
1242        self.move_under_binders(DeBruijnId::one())
1243    }
1244
1245    /// Move under `depth` binders.
1246    fn move_under_binders(mut self, depth: DeBruijnId) -> Self {
1247        if !depth.is_zero() {
1248            let Continue(()) = self.visit_db_id::<Infallible>(|id| {
1249                *id = id.plus(depth);
1250                Continue(())
1251            });
1252        }
1253        self
1254    }
1255
1256    /// Move from under one binder.
1257    fn move_from_under_binder(self) -> Option<Self> {
1258        self.move_from_under_binders(DeBruijnId::one())
1259    }
1260
1261    /// Move the value out of `depth` binders. Returns `None` if it contains a variable bound in
1262    /// one of these `depth` binders.
1263    fn move_from_under_binders(mut self, depth: DeBruijnId) -> Option<Self> {
1264        self.visit_db_id::<()>(|id| match id.sub(depth) {
1265            Some(sub) => {
1266                *id = sub;
1267                Continue(())
1268            }
1269            None => Break(()),
1270        })
1271        .is_continue()
1272        .then_some(self)
1273    }
1274
1275    /// Visit the de Bruijn ids contained in `self`, as seen from the outside of `self`. This means
1276    /// that any variable bound inside `self` will be skipped, and all the seen indices will count
1277    /// from the outside of self.
1278    fn visit_db_id<B>(
1279        &mut self,
1280        f: impl FnMut(&mut DeBruijnId) -> ControlFlow<B>,
1281    ) -> ControlFlow<B> {
1282        struct Wrap<F> {
1283            f: F,
1284            depth: DeBruijnId,
1285        }
1286        impl<B, F> Visitor for Wrap<F>
1287        where
1288            F: FnMut(&mut DeBruijnId) -> ControlFlow<B>,
1289        {
1290            type Break = B;
1291        }
1292        impl<B, F> VisitAstMut for Wrap<F>
1293        where
1294            F: FnMut(&mut DeBruijnId) -> ControlFlow<B>,
1295        {
1296            fn enter_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
1297                self.depth = self.depth.incr()
1298            }
1299            fn exit_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
1300                self.depth = self.depth.decr()
1301            }
1302            fn enter_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
1303                self.depth = self.depth.incr()
1304            }
1305            fn exit_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
1306                self.depth = self.depth.decr()
1307            }
1308
1309            fn visit_de_bruijn_id(&mut self, x: &mut DeBruijnId) -> ControlFlow<Self::Break> {
1310                if let Some(mut shifted) = x.sub(self.depth) {
1311                    (self.f)(&mut shifted)?;
1312                    *x = shifted.plus(self.depth)
1313                }
1314                Continue(())
1315            }
1316        }
1317        self.drive_mut(&mut Wrap {
1318            f,
1319            depth: DeBruijnId::zero(),
1320        })
1321    }
1322
1323    /// Replace all the erased regions by the output of the provided function. Binders levels are
1324    /// handled automatically.
1325    fn replace_erased_regions(mut self, f: impl FnMut() -> Region) -> Self {
1326        #[derive(Visitor)]
1327        struct RefreshErasedRegions<F>(F);
1328        impl<F: FnMut() -> Region> VarsVisitor for RefreshErasedRegions<F> {
1329            fn visit_erased_region(&mut self) -> Option<Region> {
1330                Some((self.0)())
1331            }
1332        }
1333        self.visit_vars(&mut RefreshErasedRegions(f));
1334        self
1335    }
1336}
1337
1338/// A value of type `T` applied to some `GenericArgs`, except we havent applied them yet to avoid a
1339/// deep clone.
1340#[derive(Debug, Clone)]
1341pub struct Substituted<'a, T> {
1342    pub val: &'a T,
1343    pub generics: Cow<'a, GenericArgs>,
1344    pub trait_self: Option<&'a TraitRefKind>,
1345}
1346
1347impl<'a, T> Substituted<'a, T> {
1348    pub fn new(val: &'a T, generics: &'a GenericArgs) -> Self {
1349        Self {
1350            val,
1351            generics: Cow::Borrowed(generics),
1352            trait_self: None,
1353        }
1354    }
1355    pub fn new_for_trait(
1356        val: &'a T,
1357        generics: &'a GenericArgs,
1358        trait_self: &'a TraitRefKind,
1359    ) -> Self {
1360        Self {
1361            val,
1362            generics: Cow::Borrowed(generics),
1363            trait_self: Some(trait_self),
1364        }
1365    }
1366    pub fn new_for_trait_ref(val: &'a T, tref: &'a TraitRef) -> Self {
1367        Self {
1368            val,
1369            generics: Cow::Owned(*tref.trait_decl_ref.clone().erase().generics),
1370            trait_self: Some(&tref.kind),
1371        }
1372    }
1373
1374    pub fn rebind<U>(&self, val: &'a U) -> Substituted<'a, U> {
1375        Substituted {
1376            val,
1377            generics: self.generics.clone(),
1378            trait_self: self.trait_self.clone(),
1379        }
1380    }
1381
1382    pub fn substitute(&self) -> T
1383    where
1384        T: TyVisitable + Clone,
1385    {
1386        self.try_substitute().unwrap()
1387    }
1388    pub fn try_substitute(&self) -> Result<T, GenericsMismatch>
1389    where
1390        T: TyVisitable + Clone,
1391    {
1392        match self.trait_self {
1393            None => self.val.clone().try_substitute(&self.generics),
1394            Some(trait_self) => self
1395                .val
1396                .clone()
1397                .try_substitute_with_self(&self.generics, trait_self),
1398        }
1399    }
1400
1401    pub fn iter<Item: 'a>(&self) -> impl Iterator<Item = Substituted<'a, Item>>
1402    where
1403        &'a T: IntoIterator<Item = &'a Item>,
1404    {
1405        self.val.into_iter().map(move |x| self.rebind(x))
1406    }
1407}
1408
1409impl TypeDecl {
1410    /// Looks up the variant corresponding to the tag (i.e. the in-memory bytes that represent the discriminant).
1411    /// Returns `None` for types that don't have a relevant discriminant (e.g. uninhabited types).
1412    ///
1413    /// If the `tag` does not correspond to any valid discriminant but there is a niche,
1414    /// the resulting `VariantId` will be for the untagged variant [`TagEncoding::Niche::untagged_variant`].
1415    pub fn get_variant_from_tag(&self, tag: ScalarValue) -> Option<VariantId> {
1416        let layout = self.layout.as_ref()?;
1417        if layout.uninhabited {
1418            return None;
1419        };
1420        let discr_layout = layout.discriminant_layout.as_ref()?;
1421
1422        let variant_for_tag =
1423            layout
1424                .variant_layouts
1425                .iter_enumerated()
1426                .find_map(|(id, variant_layout)| {
1427                    if variant_layout.tag == Some(tag) {
1428                        Some(id)
1429                    } else {
1430                        None
1431                    }
1432                });
1433
1434        match &discr_layout.encoding {
1435            TagEncoding::Direct => {
1436                assert_eq!(tag.get_integer_ty(), discr_layout.tag_ty);
1437                variant_for_tag
1438            }
1439            TagEncoding::Niche { untagged_variant } => variant_for_tag.or(Some(*untagged_variant)),
1440        }
1441    }
1442
1443    pub fn is_c_repr(&self) -> bool {
1444        self.repr
1445            .as_ref()
1446            .is_some_and(|repr| repr.repr_algo == ReprAlgorithm::C)
1447    }
1448
1449    pub fn get_field_by_name(
1450        &self,
1451        variant: Option<VariantId>,
1452        field_name: &str,
1453    ) -> Option<(FieldId, &Field)> {
1454        let fields = match &self.kind {
1455            TypeDeclKind::Struct(fields) | TypeDeclKind::Union(fields) => fields,
1456            TypeDeclKind::Enum(variants) => &variants[variant.unwrap()].fields,
1457            _ => return None,
1458        };
1459        fields
1460            .iter_indexed()
1461            .find(|(_, field)| field.name.as_deref() == Some(field_name))
1462    }
1463}
1464
1465impl Layout {
1466    pub fn is_variant_uninhabited(&self, variant_id: VariantId) -> bool {
1467        if let Some(v) = self.variant_layouts.get(variant_id) {
1468            v.uninhabited
1469        } else {
1470            false
1471        }
1472    }
1473}
1474
1475impl ReprOptions {
1476    /// Whether this representation options guarantee a fixed
1477    /// field ordering for the type.
1478    ///
1479    /// Since we don't support `repr(simd)` or `repr(linear)` yet, this is
1480    /// the case if it's either `repr(C)` or an explicit discriminant type for
1481    /// an enum with fields (if it doesn't have fields, this obviously doesn't matter anyway).
1482    ///
1483    /// Cf. <https://doc.rust-lang.org/reference/type-layout.html#r-layout.repr.c.struct>
1484    /// and <https://doc.rust-lang.org/reference/type-layout.html#r-layout.repr.primitive.adt>.
1485    pub fn guarantees_fixed_field_order(&self) -> bool {
1486        self.repr_algo == ReprAlgorithm::C || self.explicit_discr_type
1487    }
1488}
1489
1490impl<T: AstVisitable> TyVisitable for T {}
1491
1492impl Eq for TraitParam {}
1493
1494mk_index_impls!(GenericArgs.regions[RegionId]: Region);
1495mk_index_impls!(GenericArgs.types[TypeVarId]: Ty);
1496mk_index_impls!(GenericArgs.const_generics[ConstGenericVarId]: ConstantExpr);
1497mk_index_impls!(GenericArgs.trait_refs[TraitClauseId]: TraitRef);
1498mk_index_impls!(GenericParams.regions[RegionId]: RegionParam);
1499mk_index_impls!(GenericParams.types[TypeVarId]: TypeParam);
1500mk_index_impls!(GenericParams.const_generics[ConstGenericVarId]: ConstGenericParam);
1501mk_index_impls!(GenericParams.trait_clauses[TraitClauseId]: TraitParam);