charon_lib/ast/
types_utils.rs

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