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_usize() -> Ty {
693        TyKind::Literal(LiteralTy::UInt(UIntTy::Usize)).into()
694    }
695
696    pub fn mk_tuple(tys: Vec<Ty>) -> Ty {
697        TyKind::Adt(TypeDeclRef {
698            id: TypeId::Tuple,
699            generics: Box::new(GenericArgs::new_for_builtin(tys.into())),
700        })
701        .into_ty()
702    }
703
704    pub fn mk_array(ty: Ty, len: ConstantExpr) -> Ty {
705        TyKind::Array(ty, Box::new(len)).into_ty()
706    }
707
708    pub fn mk_slice(ty: Ty) -> Ty {
709        TyKind::Slice(ty).into_ty()
710    }
711    /// Return true if it is actually unit (i.e.: 0-tuple)
712    pub fn is_unit(&self) -> bool {
713        match self.as_tuple() {
714            Some(tys) => tys.is_empty(),
715            None => false,
716        }
717    }
718
719    /// Return true if this is a scalar type
720    pub fn is_scalar(&self) -> bool {
721        match self.kind() {
722            TyKind::Literal(kind) => kind.is_int() || kind.is_uint(),
723            _ => false,
724        }
725    }
726
727    pub fn is_unsigned_scalar(&self) -> bool {
728        matches!(self.kind(), TyKind::Literal(LiteralTy::UInt(_)))
729    }
730
731    pub fn is_signed_scalar(&self) -> bool {
732        matches!(self.kind(), TyKind::Literal(LiteralTy::Int(_)))
733    }
734
735    pub fn is_str(&self) -> bool {
736        match self.kind() {
737            TyKind::Adt(ty_ref) if let TypeId::Builtin(BuiltinTy::Str) = ty_ref.id => true,
738            _ => false,
739        }
740    }
741
742    /// Return true if the type is Box
743    pub fn is_box(&self) -> bool {
744        match self.kind() {
745            TyKind::Adt(ty_ref) if let TypeId::Builtin(BuiltinTy::Box) = ty_ref.id => true,
746            _ => false,
747        }
748    }
749
750    pub fn as_box(&self) -> Option<&Ty> {
751        match self.kind() {
752            TyKind::Adt(ty_ref) if let TypeId::Builtin(BuiltinTy::Box) = ty_ref.id => {
753                Some(&ty_ref.generics.types[0])
754            }
755            _ => None,
756        }
757    }
758
759    pub fn get_ptr_metadata(&self, translated: &TranslatedCrate) -> PtrMetadata {
760        let ref ty_decls = translated.type_decls;
761        match self.kind() {
762            TyKind::Adt(ty_ref) => {
763                // there are two cases:
764                // 1. if the declared type has a fixed metadata, just returns it
765                // 2. if it depends on some other types or the generic itself
766                match ty_ref.id {
767                    TypeId::Adt(type_decl_id) => {
768                        let Some(decl) = ty_decls.get(type_decl_id) else {
769                            return PtrMetadata::InheritFrom(self.clone());
770                        };
771                        match decl.ptr_metadata.clone().substitute(&ty_ref.generics) {
772                            // if it depends on some type, recursion with the binding env
773                            PtrMetadata::InheritFrom(ty) => ty.get_ptr_metadata(translated),
774                            // otherwise, simply return it
775                            meta => meta,
776                        }
777                    }
778                    // the metadata of a tuple is simply the last field
779                    TypeId::Tuple => {
780                        match ty_ref.generics.types.iter().last() {
781                            // `None` refers to the unit type `()`
782                            None => PtrMetadata::None,
783                            // Otherwise, simply recurse
784                            Some(ty) => ty.get_ptr_metadata(translated),
785                        }
786                    }
787                    // Box is a pointer like ref & raw ptr, hence no metadata
788                    TypeId::Builtin(BuiltinTy::Box) => PtrMetadata::None,
789                    // `str` has metadata length
790                    TypeId::Builtin(BuiltinTy::Str) => PtrMetadata::Length,
791                }
792            }
793            TyKind::DynTrait(pred) => match pred.vtable_ref(translated) {
794                Some(vtable) => PtrMetadata::VTable(vtable),
795                None => PtrMetadata::InheritFrom(self.clone()),
796            },
797            // `[T]` has metadata length
798            TyKind::Slice(..) => PtrMetadata::Length,
799            TyKind::TraitType(..) | TyKind::TypeVar(_) => PtrMetadata::InheritFrom(self.clone()),
800            TyKind::Literal(_)
801            | TyKind::Never
802            | TyKind::Ref(..)
803            | TyKind::RawPtr(..)
804            | TyKind::FnPtr(..)
805            | TyKind::FnDef(..)
806            | TyKind::Array(..)
807            | TyKind::Error(_) => PtrMetadata::None,
808            // The metadata itself must be Sized, hence must with `PtrMetadata::None`
809            TyKind::PtrMetadata(_) => PtrMetadata::None,
810        }
811    }
812
813    pub fn as_ref_or_ptr(&self) -> Option<&Ty> {
814        match self.kind() {
815            TyKind::RawPtr(ty, _) | TyKind::Ref(_, ty, _) => Some(ty),
816            _ => None,
817        }
818    }
819
820    pub fn as_array_or_slice(&self) -> Option<&Ty> {
821        match self.kind() {
822            TyKind::Slice(ty) | TyKind::Array(ty, _) => Some(ty),
823            _ => None,
824        }
825    }
826
827    pub fn as_tuple(&self) -> Option<&IndexMap<TypeVarId, Ty>> {
828        match self.kind() {
829            TyKind::Adt(ty_ref) if let TypeId::Tuple = ty_ref.id => Some(&ty_ref.generics.types),
830            _ => None,
831        }
832    }
833
834    pub fn as_adt(&self) -> Option<&TypeDeclRef> {
835        self.kind().as_adt()
836    }
837}
838
839impl TyKind {
840    pub fn into_ty(self) -> Ty {
841        Ty::new(self)
842    }
843}
844
845impl From<TyKind> for Ty {
846    fn from(kind: TyKind) -> Ty {
847        kind.into_ty()
848    }
849}
850
851/// Convenience for migration purposes.
852impl std::ops::Deref for Ty {
853    type Target = TyKind;
854
855    fn deref(&self) -> &Self::Target {
856        self.kind()
857    }
858}
859/// For deref patterns.
860unsafe impl std::ops::DerefPure for Ty {}
861
862impl TypeDeclRef {
863    pub fn new(id: TypeId, generics: GenericArgs) -> Self {
864        Self {
865            id,
866            generics: Box::new(generics),
867        }
868    }
869}
870
871impl TraitDeclRef {
872    pub fn self_ty<'a>(&'a self, krate: &'a TranslatedCrate) -> Option<&'a Ty> {
873        match self.generics.types.iter().next() {
874            Some(ty) => return Some(ty),
875            // TODO(mono): A monomorphized trait takes no arguments.
876            None => {
877                let name = krate.item_name(self.id)?;
878                let args = name.name.last()?.as_monomorphized()?;
879                args.types.iter().next()
880            }
881        }
882    }
883}
884
885impl TraitRef {
886    pub fn new(kind: TraitRefKind, trait_decl_ref: PolyTraitDeclRef) -> Self {
887        TraitRefContents {
888            kind,
889            trait_decl_ref,
890        }
891        .intern()
892    }
893
894    pub fn new_builtin(
895        trait_id: TraitDeclId,
896        ty: Ty,
897        parents: IndexMap<TraitClauseId, TraitRef>,
898        builtin_data: BuiltinImplData,
899    ) -> Self {
900        let trait_decl_ref = RegionBinder::empty(TraitDeclRef {
901            id: trait_id,
902            generics: Box::new(GenericArgs::new_types([ty].into())),
903        });
904        Self::new(
905            TraitRefKind::BuiltinOrAuto {
906                builtin_data,
907                parent_trait_refs: parents,
908                types: Default::default(),
909            },
910            trait_decl_ref,
911        )
912    }
913
914    /// Get mutable access to the contents. This cloned the value and will re-intern the modified
915    /// value at the end of the function.
916    pub fn with_contents_mut<R>(&mut self, f: impl FnOnce(&mut TraitRefContents) -> R) -> R {
917        self.0.with_inner_mut(f)
918    }
919}
920impl TraitRefContents {
921    pub fn intern(self) -> TraitRef {
922        TraitRef(HashConsed::new(self))
923    }
924}
925
926impl std::ops::Deref for TraitRef {
927    type Target = TraitRefContents;
928    fn deref(&self) -> &Self::Target {
929        &self.0
930    }
931}
932
933impl BuiltinImplData {
934    pub fn as_closure_kind(&self) -> Option<ClosureKind> {
935        match self {
936            BuiltinImplData::FnOnce => Some(ClosureKind::FnOnce),
937            BuiltinImplData::FnMut => Some(ClosureKind::FnMut),
938            BuiltinImplData::Fn => Some(ClosureKind::Fn),
939            _ => None,
940        }
941    }
942}
943
944impl PtrMetadata {
945    pub fn into_type(self) -> Ty {
946        match self {
947            PtrMetadata::None => Ty::mk_unit(),
948            PtrMetadata::Length => Ty::mk_usize(),
949            PtrMetadata::VTable(type_decl_ref) => Ty::new(TyKind::Ref(
950                Region::Static,
951                Ty::new(TyKind::Adt(type_decl_ref)),
952                RefKind::Shared,
953            )),
954            PtrMetadata::InheritFrom(ty) => Ty::new(TyKind::PtrMetadata(ty)),
955        }
956    }
957}
958
959impl Field {
960    /// The new name for this field, as suggested by the `#[charon::rename]` attribute.
961    pub fn renamed_name(&self) -> Option<&str> {
962        self.attr_info.rename.as_deref().or(self.name.as_deref())
963    }
964
965    /// Whether this field has a `#[charon::opaque]` annotation.
966    pub fn is_opaque(&self) -> bool {
967        self.attr_info
968            .attributes
969            .iter()
970            .any(|attr| attr.is_opaque())
971    }
972}
973
974impl Variant {
975    /// The new name for this variant, as suggested by the `#[charon::rename]` and
976    /// `#[charon::variants_prefix]` attributes.
977    pub fn renamed_name(&self) -> &str {
978        self.attr_info
979            .rename
980            .as_deref()
981            .unwrap_or(self.name.as_ref())
982    }
983
984    /// Whether this variant has a `#[charon::opaque]` annotation.
985    pub fn is_opaque(&self) -> bool {
986        self.attr_info
987            .attributes
988            .iter()
989            .any(|attr| attr.is_opaque())
990    }
991}
992
993impl DynPredicate {
994    /// Get a reference to the vtable type that corresponds to this predicate.
995    pub fn vtable_ref(&self, translated: &TranslatedCrate) -> Option<TypeDeclRef> {
996        // The first clause is the one relevant for the vtable.
997        let relevant_tref = self.binder.params.trait_clauses[0].trait_.clone().erase();
998
999        // Get the vtable ref from the trait decl
1000        let trait_decl = translated.trait_decls.get(relevant_tref.id)?;
1001        let vtable_ref = trait_decl
1002            .vtable
1003            .clone()?
1004            .substitute(&relevant_tref.generics);
1005        Some(vtable_ref)
1006    }
1007}
1008
1009impl RefKind {
1010    pub fn mutable(x: bool) -> Self {
1011        if x { Self::Mut } else { Self::Shared }
1012    }
1013}
1014
1015/// Visitor for type-level variables. Used to visit the variables contained in a value, as seen
1016/// from the outside of the value. This means that any variable bound inside the value will be
1017/// skipped, and all the seen De Bruijn indices will count from the outside of the value. The
1018/// returned value, if any, will be put in place of the variable.
1019pub trait VarsVisitor {
1020    fn visit_erased_region(&mut self) -> Option<Region> {
1021        None
1022    }
1023    fn visit_region_var(&mut self, _v: RegionDbVar) -> Option<Region> {
1024        None
1025    }
1026    fn visit_type_var(&mut self, _v: TypeDbVar) -> Option<Ty> {
1027        None
1028    }
1029    fn visit_const_generic_var(&mut self, _v: ConstGenericDbVar) -> Option<ConstantExprKind> {
1030        None
1031    }
1032    fn visit_clause_var(&mut self, _v: ClauseDbVar) -> Option<TraitRefKind> {
1033        None
1034    }
1035    fn visit_self_clause(&mut self) -> Option<TraitRefKind> {
1036        None
1037    }
1038}
1039
1040/// Visitor for the [TyVisitable::substitute] function.
1041/// This substitutes variables bound at the level where we start to substitute (level 0).
1042#[derive(Visitor)]
1043pub(crate) struct SubstVisitor<'a> {
1044    generics: &'a GenericArgs,
1045    self_ref: &'a TraitRefKind,
1046    /// Whether to substitute explicit variables only (types, regions, const generics).
1047    explicits_only: bool,
1048    had_error: bool,
1049}
1050impl<'a> SubstVisitor<'a> {
1051    pub(crate) fn new(
1052        generics: &'a GenericArgs,
1053        self_ref: &'a TraitRefKind,
1054        explicits_only: bool,
1055    ) -> Self {
1056        Self {
1057            generics,
1058            self_ref,
1059            explicits_only,
1060            had_error: false,
1061        }
1062    }
1063
1064    pub fn visit<T: TyVisitable>(mut self, mut x: T) -> Result<T, GenericsMismatch> {
1065        let _ = x.visit_vars(&mut self);
1066        if self.had_error {
1067            Err(GenericsMismatch)
1068        } else {
1069            Ok(x)
1070        }
1071    }
1072
1073    /// Returns the value for this variable, if any.
1074    fn process_var<Id, T>(
1075        &mut self,
1076        var: DeBruijnVar<Id>,
1077        get: impl Fn(Id) -> Option<&'a T>,
1078    ) -> Option<T>
1079    where
1080        Id: Copy,
1081        T: Clone + TyVisitable,
1082        DeBruijnVar<Id>: Into<T>,
1083    {
1084        match var {
1085            DeBruijnVar::Bound(dbid, varid) => {
1086                Some(if let Some(dbid) = dbid.sub(DeBruijnId::one()) {
1087                    // This is bound outside the binder we're substituting for.
1088                    DeBruijnVar::Bound(dbid, varid).into()
1089                } else {
1090                    match get(varid) {
1091                        Some(v) => v.clone(),
1092                        None => {
1093                            self.had_error = true;
1094                            return None;
1095                        }
1096                    }
1097                })
1098            }
1099            DeBruijnVar::Free(..) => None,
1100        }
1101    }
1102}
1103impl VarsVisitor for SubstVisitor<'_> {
1104    fn visit_region_var(&mut self, v: RegionDbVar) -> Option<Region> {
1105        self.process_var(v, |id| self.generics.regions.get(id))
1106    }
1107    fn visit_type_var(&mut self, v: TypeDbVar) -> Option<Ty> {
1108        self.process_var(v, |id| self.generics.types.get(id))
1109    }
1110    fn visit_const_generic_var(&mut self, v: ConstGenericDbVar) -> Option<ConstantExprKind> {
1111        self.process_var(v, |id| {
1112            self.generics.const_generics.get(id).map(|c| &c.kind)
1113        })
1114    }
1115    fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
1116        if self.explicits_only {
1117            None
1118        } else {
1119            self.process_var(v, |id| Some(&self.generics.trait_refs.get(id)?.kind))
1120        }
1121    }
1122    fn visit_self_clause(&mut self) -> Option<TraitRefKind> {
1123        Some(self.self_ref.clone())
1124    }
1125}
1126
1127#[derive(Debug)]
1128pub struct GenericsMismatch;
1129
1130/// Types that are involved at the type-level and may be substituted around.
1131pub trait TyVisitable: Sized + AstVisitable {
1132    /// Visit the variables contained in `self`, as seen from the outside of `self`. This means
1133    /// that any variable bound inside `self` will be skipped, and all the seen De Bruijn indices
1134    /// will count from the outside of `self`.
1135    fn visit_vars(&mut self, v: &mut impl VarsVisitor) {
1136        #[derive(Visitor)]
1137        struct Wrap<'v, V> {
1138            v: &'v mut V,
1139            depth: DeBruijnId,
1140        }
1141        impl<V> VisitorWithBinderDepth for Wrap<'_, V> {
1142            fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
1143                &mut self.depth
1144            }
1145        }
1146        impl<V: VarsVisitor> VisitAstMut for Wrap<'_, V> {
1147            fn visit<'a, T: AstVisitable>(&'a mut self, x: &mut T) -> ControlFlow<Self::Break> {
1148                VisitWithBinderDepth::new(self).visit(x)
1149            }
1150
1151            fn exit_region(&mut self, r: &mut Region) {
1152                match r {
1153                    Region::Var(var)
1154                        if let Some(var) = var.move_out_from_depth(self.depth)
1155                            && let Some(new_r) = self.v.visit_region_var(var) =>
1156                    {
1157                        *r = new_r.move_under_binders(self.depth);
1158                    }
1159                    Region::Erased | Region::Body(..)
1160                        if let Some(new_r) = self.v.visit_erased_region() =>
1161                    {
1162                        *r = new_r.move_under_binders(self.depth);
1163                    }
1164                    _ => (),
1165                }
1166            }
1167            fn exit_ty(&mut self, ty: &mut Ty) {
1168                if let TyKind::TypeVar(var) = ty.kind()
1169                    && let Some(var) = var.move_out_from_depth(self.depth)
1170                    && let Some(new_ty) = self.v.visit_type_var(var)
1171                {
1172                    *ty = new_ty.move_under_binders(self.depth);
1173                }
1174            }
1175            fn exit_constant_expr(&mut self, ce: &mut ConstantExpr) {
1176                if let ConstantExprKind::Var(var) = &mut ce.kind
1177                    && let Some(var) = var.move_out_from_depth(self.depth)
1178                    && let Some(new_cg) = self.v.visit_const_generic_var(var)
1179                {
1180                    ce.kind = new_cg.move_under_binders(self.depth);
1181                }
1182            }
1183            fn exit_trait_ref_kind(&mut self, kind: &mut TraitRefKind) {
1184                match kind {
1185                    TraitRefKind::SelfId => {
1186                        if let Some(new_kind) = self.v.visit_self_clause() {
1187                            *kind = new_kind.move_under_binders(self.depth);
1188                        }
1189                    }
1190                    TraitRefKind::Clause(var) => {
1191                        if let Some(var) = var.move_out_from_depth(self.depth)
1192                            && let Some(new_kind) = self.v.visit_clause_var(var)
1193                        {
1194                            *kind = new_kind.move_under_binders(self.depth);
1195                        }
1196                    }
1197                    _ => {}
1198                }
1199            }
1200        }
1201        Wrap {
1202            v,
1203            depth: DeBruijnId::zero(),
1204        }
1205        .visit(self);
1206    }
1207
1208    /// Substitute the generic variables inside `self` by replacing them with the provided values.
1209    /// Note: if `self` is an item that comes from a `TraitDecl`, you most likely want to use
1210    /// `substitute_with_self`.
1211    fn substitute(self, generics: &GenericArgs) -> Self {
1212        self.substitute_with_self(generics, &TraitRefKind::SelfId)
1213    }
1214    /// Substitute only the type, region and const generic args.
1215    fn substitute_explicits(self, generics: &GenericArgs) -> Self {
1216        SubstVisitor::new(generics, &TraitRefKind::SelfId, true)
1217            .visit(self)
1218            .unwrap()
1219    }
1220    /// Substitute the generic variables as well as the `TraitRefKind::Self` trait ref.
1221    fn substitute_with_self(self, generics: &GenericArgs, self_ref: &TraitRefKind) -> Self {
1222        self.try_substitute_with_self(generics, self_ref).unwrap()
1223    }
1224
1225    fn try_substitute(self, generics: &GenericArgs) -> Result<Self, GenericsMismatch> {
1226        self.try_substitute_with_self(generics, &TraitRefKind::SelfId)
1227    }
1228    fn try_substitute_with_self(
1229        self,
1230        generics: &GenericArgs,
1231        self_ref: &TraitRefKind,
1232    ) -> Result<Self, GenericsMismatch> {
1233        SubstVisitor::new(generics, self_ref, false).visit(self)
1234    }
1235
1236    /// Move under one binder.
1237    fn move_under_binder(self) -> Self {
1238        self.move_under_binders(DeBruijnId::one())
1239    }
1240
1241    /// Move under `depth` binders.
1242    fn move_under_binders(mut self, depth: DeBruijnId) -> Self {
1243        if !depth.is_zero() {
1244            let Continue(()) = self.visit_db_id::<Infallible>(|id| {
1245                *id = id.plus(depth);
1246                Continue(())
1247            });
1248        }
1249        self
1250    }
1251
1252    /// Move from under one binder.
1253    fn move_from_under_binder(self) -> Option<Self> {
1254        self.move_from_under_binders(DeBruijnId::one())
1255    }
1256
1257    /// Move the value out of `depth` binders. Returns `None` if it contains a variable bound in
1258    /// one of these `depth` binders.
1259    fn move_from_under_binders(mut self, depth: DeBruijnId) -> Option<Self> {
1260        self.visit_db_id::<()>(|id| match id.sub(depth) {
1261            Some(sub) => {
1262                *id = sub;
1263                Continue(())
1264            }
1265            None => Break(()),
1266        })
1267        .is_continue()
1268        .then_some(self)
1269    }
1270
1271    /// Visit the de Bruijn ids contained in `self`, as seen from the outside of `self`. This means
1272    /// that any variable bound inside `self` will be skipped, and all the seen indices will count
1273    /// from the outside of self.
1274    fn visit_db_id<B>(
1275        &mut self,
1276        f: impl FnMut(&mut DeBruijnId) -> ControlFlow<B>,
1277    ) -> ControlFlow<B> {
1278        struct Wrap<F> {
1279            f: F,
1280            depth: DeBruijnId,
1281        }
1282        impl<B, F> Visitor for Wrap<F>
1283        where
1284            F: FnMut(&mut DeBruijnId) -> ControlFlow<B>,
1285        {
1286            type Break = B;
1287        }
1288        impl<B, F> VisitAstMut for Wrap<F>
1289        where
1290            F: FnMut(&mut DeBruijnId) -> ControlFlow<B>,
1291        {
1292            fn enter_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
1293                self.depth = self.depth.incr()
1294            }
1295            fn exit_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
1296                self.depth = self.depth.decr()
1297            }
1298            fn enter_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
1299                self.depth = self.depth.incr()
1300            }
1301            fn exit_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
1302                self.depth = self.depth.decr()
1303            }
1304
1305            fn visit_de_bruijn_id(&mut self, x: &mut DeBruijnId) -> ControlFlow<Self::Break> {
1306                if let Some(mut shifted) = x.sub(self.depth) {
1307                    (self.f)(&mut shifted)?;
1308                    *x = shifted.plus(self.depth)
1309                }
1310                Continue(())
1311            }
1312        }
1313        self.drive_mut(&mut Wrap {
1314            f,
1315            depth: DeBruijnId::zero(),
1316        })
1317    }
1318
1319    /// Replace all the erased regions by the output of the provided function. Binders levels are
1320    /// handled automatically.
1321    fn replace_erased_regions(mut self, f: impl FnMut() -> Region) -> Self {
1322        #[derive(Visitor)]
1323        struct RefreshErasedRegions<F>(F);
1324        impl<F: FnMut() -> Region> VarsVisitor for RefreshErasedRegions<F> {
1325            fn visit_erased_region(&mut self) -> Option<Region> {
1326                Some((self.0)())
1327            }
1328        }
1329        self.visit_vars(&mut RefreshErasedRegions(f));
1330        self
1331    }
1332}
1333
1334/// A value of type `T` applied to some `GenericArgs`, except we havent applied them yet to avoid a
1335/// deep clone.
1336#[derive(Debug, Clone)]
1337pub struct Substituted<'a, T> {
1338    pub val: &'a T,
1339    pub generics: Cow<'a, GenericArgs>,
1340    pub trait_self: Option<&'a TraitRefKind>,
1341}
1342
1343impl<'a, T> Substituted<'a, T> {
1344    pub fn new(val: &'a T, generics: &'a GenericArgs) -> Self {
1345        Self {
1346            val,
1347            generics: Cow::Borrowed(generics),
1348            trait_self: None,
1349        }
1350    }
1351    pub fn new_for_trait(
1352        val: &'a T,
1353        generics: &'a GenericArgs,
1354        trait_self: &'a TraitRefKind,
1355    ) -> Self {
1356        Self {
1357            val,
1358            generics: Cow::Borrowed(generics),
1359            trait_self: Some(trait_self),
1360        }
1361    }
1362    pub fn new_for_trait_ref(val: &'a T, tref: &'a TraitRef) -> Self {
1363        Self {
1364            val,
1365            generics: Cow::Owned(*tref.trait_decl_ref.clone().erase().generics),
1366            trait_self: Some(&tref.kind),
1367        }
1368    }
1369
1370    pub fn rebind<U>(&self, val: &'a U) -> Substituted<'a, U> {
1371        Substituted {
1372            val,
1373            generics: self.generics.clone(),
1374            trait_self: self.trait_self.clone(),
1375        }
1376    }
1377
1378    pub fn substitute(&self) -> T
1379    where
1380        T: TyVisitable + Clone,
1381    {
1382        self.try_substitute().unwrap()
1383    }
1384    pub fn try_substitute(&self) -> Result<T, GenericsMismatch>
1385    where
1386        T: TyVisitable + Clone,
1387    {
1388        match self.trait_self {
1389            None => self.val.clone().try_substitute(&self.generics),
1390            Some(trait_self) => self
1391                .val
1392                .clone()
1393                .try_substitute_with_self(&self.generics, trait_self),
1394        }
1395    }
1396
1397    pub fn iter<Item: 'a>(&self) -> impl Iterator<Item = Substituted<'a, Item>>
1398    where
1399        &'a T: IntoIterator<Item = &'a Item>,
1400    {
1401        self.val.into_iter().map(move |x| self.rebind(x))
1402    }
1403}
1404
1405impl TypeDecl {
1406    /// Looks up the variant corresponding to the tag (i.e. the in-memory bytes that represent the discriminant).
1407    /// Returns `None` for types that don't have a relevant discriminant (e.g. uninhabited types).
1408    ///
1409    /// If the `tag` does not correspond to any valid discriminant but there is a niche,
1410    /// the resulting `VariantId` will be for the untagged variant [`TagEncoding::Niche::untagged_variant`].
1411    pub fn get_variant_from_tag(&self, tag: ScalarValue) -> Option<VariantId> {
1412        let layout = self.layout.as_ref()?;
1413        if layout.uninhabited {
1414            return None;
1415        };
1416        let discr_layout = layout.discriminant_layout.as_ref()?;
1417
1418        let variant_for_tag =
1419            layout
1420                .variant_layouts
1421                .iter_enumerated()
1422                .find_map(|(id, variant_layout)| {
1423                    if variant_layout.tag == Some(tag) {
1424                        Some(id)
1425                    } else {
1426                        None
1427                    }
1428                });
1429
1430        match &discr_layout.encoding {
1431            TagEncoding::Direct => {
1432                assert_eq!(tag.get_integer_ty(), discr_layout.tag_ty);
1433                variant_for_tag
1434            }
1435            TagEncoding::Niche { untagged_variant } => variant_for_tag.or(Some(*untagged_variant)),
1436        }
1437    }
1438
1439    pub fn is_c_repr(&self) -> bool {
1440        self.repr
1441            .as_ref()
1442            .is_some_and(|repr| repr.repr_algo == ReprAlgorithm::C)
1443    }
1444
1445    pub fn get_field_by_name(
1446        &self,
1447        variant: Option<VariantId>,
1448        field_name: &str,
1449    ) -> Option<(FieldId, &Field)> {
1450        let fields = match &self.kind {
1451            TypeDeclKind::Struct(fields) | TypeDeclKind::Union(fields) => fields,
1452            TypeDeclKind::Enum(variants) => &variants[variant.unwrap()].fields,
1453            _ => return None,
1454        };
1455        fields
1456            .iter_indexed()
1457            .find(|(_, field)| field.name.as_deref() == Some(field_name))
1458    }
1459}
1460
1461impl Layout {
1462    pub fn is_variant_uninhabited(&self, variant_id: VariantId) -> bool {
1463        if let Some(v) = self.variant_layouts.get(variant_id) {
1464            v.uninhabited
1465        } else {
1466            false
1467        }
1468    }
1469}
1470
1471impl ReprOptions {
1472    /// Whether this representation options guarantee a fixed
1473    /// field ordering for the type.
1474    ///
1475    /// Since we don't support `repr(simd)` or `repr(linear)` yet, this is
1476    /// the case if it's either `repr(C)` or an explicit discriminant type for
1477    /// an enum with fields (if it doesn't have fields, this obviously doesn't matter anyway).
1478    ///
1479    /// Cf. <https://doc.rust-lang.org/reference/type-layout.html#r-layout.repr.c.struct>
1480    /// and <https://doc.rust-lang.org/reference/type-layout.html#r-layout.repr.primitive.adt>.
1481    pub fn guarantees_fixed_field_order(&self) -> bool {
1482        self.repr_algo == ReprAlgorithm::C || self.explicit_discr_type
1483    }
1484}
1485
1486impl<T: AstVisitable> TyVisitable for T {}
1487
1488impl Eq for TraitParam {}
1489
1490mk_index_impls!(GenericArgs.regions[RegionId]: Region);
1491mk_index_impls!(GenericArgs.types[TypeVarId]: Ty);
1492mk_index_impls!(GenericArgs.const_generics[ConstGenericVarId]: ConstantExpr);
1493mk_index_impls!(GenericArgs.trait_refs[TraitClauseId]: TraitRef);
1494mk_index_impls!(GenericParams.regions[RegionId]: RegionParam);
1495mk_index_impls!(GenericParams.types[TypeVarId]: TypeParam);
1496mk_index_impls!(GenericParams.const_generics[ConstGenericVarId]: ConstGenericParam);
1497mk_index_impls!(GenericParams.trait_clauses[TraitClauseId]: TraitParam);