charon_lib/ast/
types_utils.rs

1//! This file groups everything which is linked to implementations about [crate::types]
2use crate::ast::*;
3use crate::formatter::IntoFormatter;
4use crate::ids::Vector;
5use crate::pretty::FmtWithCtx;
6use derive_generic_visitor::*;
7use itertools::Itertools;
8use std::collections::HashSet;
9use std::convert::Infallible;
10use std::fmt::Debug;
11use std::iter::Iterator;
12use std::mem;
13
14impl TraitParam {
15    /// Constructs the trait ref that refers to this clause.
16    pub fn identity_tref(&self) -> TraitRef {
17        self.identity_tref_at_depth(DeBruijnId::zero())
18    }
19
20    /// Like `identity_tref` but uses variables bound at the given depth.
21    pub fn identity_tref_at_depth(&self, depth: DeBruijnId) -> TraitRef {
22        TraitRef {
23            kind: TraitRefKind::Clause(DeBruijnVar::bound(depth, self.clause_id)),
24            trait_decl_ref: self.trait_.clone().move_under_binders(depth),
25        }
26    }
27}
28
29impl GenericParams {
30    pub fn empty() -> Self {
31        Self::default()
32    }
33
34    pub fn is_empty(&self) -> bool {
35        self.len() == 0
36    }
37    /// Whether this has any explicit arguments (types, regions or const generics).
38    pub fn has_explicits(&self) -> bool {
39        !self.regions.is_empty() || !self.types.is_empty() || !self.const_generics.is_empty()
40    }
41    /// Whether this has any implicit arguments (trait clauses, outlives relations, associated type
42    /// equality constraints).
43    pub fn has_predicates(&self) -> bool {
44        !self.trait_clauses.is_empty()
45            || !self.types_outlive.is_empty()
46            || !self.regions_outlive.is_empty()
47            || !self.trait_type_constraints.is_empty()
48    }
49
50    /// Run some sanity checks.
51    pub fn check_consistency(&self) {
52        // Sanity check: check the clause ids are consistent.
53        assert!(
54            self.trait_clauses
55                .iter()
56                .enumerate()
57                .all(|(i, c)| c.clause_id.index() == i)
58        );
59
60        // Sanity check: region names are pairwise distinct (this caused trouble when generating
61        // names for the backward functions in Aeneas): at some point, Rustc introduced names equal
62        // to `Some("'_")` for the anonymous regions, instead of using `None` (we now check in
63        // [translate_region_name] and ignore names equal to "'_").
64        let mut s = HashSet::new();
65        for r in &self.regions {
66            if let Some(name) = &r.name {
67                assert!(
68                    !s.contains(name),
69                    "Name \"{}\" reused for two different lifetimes",
70                    name
71                );
72                s.insert(name);
73            }
74        }
75    }
76
77    pub fn len(&self) -> usize {
78        let GenericParams {
79            regions,
80            types,
81            const_generics,
82            trait_clauses,
83            regions_outlive,
84            types_outlive,
85            trait_type_constraints,
86        } = self;
87        regions.elem_count()
88            + types.elem_count()
89            + const_generics.elem_count()
90            + trait_clauses.elem_count()
91            + regions_outlive.len()
92            + types_outlive.len()
93            + trait_type_constraints.elem_count()
94    }
95
96    /// Construct a set of generic arguments in the scope of `self` that matches `self` and feeds
97    /// each required parameter with itself. E.g. given parameters for `<T, U> where U:
98    /// PartialEq<T>`, the arguments would be `<T, U>[@TraitClause0]`.
99    pub fn identity_args(&self) -> GenericArgs {
100        self.identity_args_at_depth(DeBruijnId::zero())
101    }
102
103    /// Like `identity_args` but uses variables bound at the given depth.
104    pub fn identity_args_at_depth(&self, depth: DeBruijnId) -> GenericArgs {
105        GenericArgs {
106            regions: self
107                .regions
108                .map_ref_indexed(|id, _| Region::Var(DeBruijnVar::bound(depth, id))),
109            types: self
110                .types
111                .map_ref_indexed(|id, _| TyKind::TypeVar(DeBruijnVar::bound(depth, id)).into_ty()),
112            const_generics: self
113                .const_generics
114                .map_ref_indexed(|id, _| ConstGeneric::Var(DeBruijnVar::bound(depth, id))),
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_const_generic(&mut self, x: &mut ConstGeneric) {
277                if let ConstGeneric::Var(var) = x
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: Vector<RegionId, Region>) -> T
387    where
388        T: AstVisitable,
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: AstVisitable,
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: Vector<TypeVarId, Ty>) -> Self {
444        GenericArgs {
445            types,
446            ..Self::empty()
447        }
448    }
449
450    pub fn new(
451        regions: Vector<RegionId, Region>,
452        types: Vector<TypeVarId, Ty>,
453        const_generics: Vector<ConstGenericVarId, ConstGeneric>,
454        trait_refs: Vector<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: Vector<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
595/// A value of type `T` bound by the generic parameters of item
596/// `item`. Used when dealing with multiple items at a time, to
597/// ensure we don't mix up generics.
598///
599/// To get the value, use `under_binder_of` or `subst_for`.
600#[derive(Debug, Clone, Copy)]
601pub struct ItemBinder<ItemId, T> {
602    pub item_id: ItemId,
603    val: T,
604}
605
606impl<ItemId, T> ItemBinder<ItemId, T>
607where
608    ItemId: Debug + Copy + PartialEq,
609{
610    pub fn new(item_id: ItemId, val: T) -> Self {
611        Self { item_id, val }
612    }
613
614    pub fn as_ref(&self) -> ItemBinder<ItemId, &T> {
615        ItemBinder {
616            item_id: self.item_id,
617            val: &self.val,
618        }
619    }
620
621    pub fn map_bound<U>(self, f: impl FnOnce(T) -> U) -> ItemBinder<ItemId, U> {
622        ItemBinder {
623            item_id: self.item_id,
624            val: f(self.val),
625        }
626    }
627
628    fn assert_item_id(&self, item_id: ItemId) {
629        assert_eq!(
630            self.item_id, item_id,
631            "Trying to use item bound for {:?} as if it belonged to {:?}",
632            self.item_id, item_id
633        );
634    }
635
636    /// Assert that the value is bound for item `item_id`, and returns it. This is used when we
637    /// plan to store the returned value inside that item.
638    pub fn under_binder_of(self, item_id: ItemId) -> T {
639        self.assert_item_id(item_id);
640        self.val
641    }
642
643    /// Given generic args for `item_id`, assert that the value is bound for `item_id` and
644    /// substitute it with the provided generic arguments. Because the arguments are bound in the
645    /// context of another item, so it the resulting substituted value.
646    pub fn substitute<OtherItem: Debug + Copy + PartialEq>(
647        self,
648        args: ItemBinder<OtherItem, &GenericArgs>,
649    ) -> ItemBinder<OtherItem, T>
650    where
651        ItemId: Into<ItemId>,
652        T: TyVisitable,
653    {
654        args.map_bound(|args| self.val.substitute(args))
655    }
656}
657
658/// Dummy item identifier that represents the current item when not ambiguous.
659#[derive(Debug, Clone, Copy, PartialEq, Eq)]
660pub struct CurrentItem;
661
662impl<T> ItemBinder<CurrentItem, T> {
663    pub fn under_current_binder(self) -> T {
664        self.val
665    }
666}
667
668impl Ty {
669    /// Return the unit type
670    pub fn mk_unit() -> Ty {
671        Self::mk_tuple(vec![])
672    }
673
674    pub fn mk_usize() -> Ty {
675        TyKind::Literal(LiteralTy::UInt(UIntTy::Usize)).into()
676    }
677
678    pub fn mk_tuple(tys: Vec<Ty>) -> Ty {
679        TyKind::Adt(TypeDeclRef {
680            id: TypeId::Tuple,
681            generics: Box::new(GenericArgs::new_for_builtin(tys.into())),
682        })
683        .into_ty()
684    }
685
686    pub fn mk_slice(ty: Ty) -> Ty {
687        TyKind::Adt(TypeDeclRef {
688            id: TypeId::Builtin(BuiltinTy::Slice),
689            generics: Box::new(GenericArgs::new_for_builtin(vec![ty].into())),
690        })
691        .into_ty()
692    }
693    /// Return true if it is actually unit (i.e.: 0-tuple)
694    pub fn is_unit(&self) -> bool {
695        match self.as_tuple() {
696            Some(tys) => tys.is_empty(),
697            None => false,
698        }
699    }
700
701    /// Return true if this is a scalar type
702    pub fn is_scalar(&self) -> bool {
703        match self.kind() {
704            TyKind::Literal(kind) => kind.is_int() || kind.is_uint(),
705            _ => false,
706        }
707    }
708
709    pub fn is_unsigned_scalar(&self) -> bool {
710        matches!(self.kind(), TyKind::Literal(LiteralTy::UInt(_)))
711    }
712
713    pub fn is_signed_scalar(&self) -> bool {
714        matches!(self.kind(), TyKind::Literal(LiteralTy::Int(_)))
715    }
716
717    /// Return true if the type is Box
718    pub fn is_box(&self) -> bool {
719        match self.kind() {
720            TyKind::Adt(ty_ref) if let TypeId::Builtin(BuiltinTy::Box) = ty_ref.id => true,
721            _ => false,
722        }
723    }
724
725    pub fn as_box(&self) -> Option<&Ty> {
726        match self.kind() {
727            TyKind::Adt(ty_ref) if let TypeId::Builtin(BuiltinTy::Box) = ty_ref.id => {
728                Some(&ty_ref.generics.types[0])
729            }
730            _ => None,
731        }
732    }
733
734    pub fn get_ptr_metadata(&self, translated: &TranslatedCrate) -> PtrMetadata {
735        let ref ty_decls = translated.type_decls;
736        match self.kind() {
737            TyKind::Adt(ty_ref) => {
738                // there are two cases:
739                // 1. if the declared type has a fixed metadata, just returns it
740                // 2. if it depends on some other types or the generic itself
741                match ty_ref.id {
742                    TypeId::Adt(type_decl_id) => {
743                        let Some(decl) = ty_decls.get(type_decl_id) else {
744                            return PtrMetadata::InheritFrom(Ty::new(TyKind::Error(format!(
745                                "Internal Error: type decl id not found during getting metadata: {type_decl_id}"
746                            ))));
747                        };
748                        match &decl.ptr_metadata {
749                            // if it depends on some type, recursion with the binding env
750                            PtrMetadata::InheritFrom(ty) => {
751                                let ty = ty.clone().substitute(&ty_ref.generics);
752                                ty.get_ptr_metadata(translated)
753                            }
754                            // otherwise, simply returns it
755                            meta => meta.clone().substitute(&ty_ref.generics),
756                        }
757                    }
758                    // the metadata of a tuple is simply the last field
759                    TypeId::Tuple => {
760                        match ty_ref.generics.types.iter().last() {
761                            // `None` refers to the unit type `()`
762                            None => PtrMetadata::None,
763                            // Otherwise, simply recurse
764                            Some(ty) => ty.get_ptr_metadata(translated),
765                        }
766                    }
767                    // Box is a pointer like ref & raw ptr, hence no metadata
768                    TypeId::Builtin(BuiltinTy::Box) => PtrMetadata::None,
769                    // Array: `[T; N]` has no metadata
770                    TypeId::Builtin(BuiltinTy::Array) => PtrMetadata::None,
771                    // `[T]` & `str` all have metadata length
772                    TypeId::Builtin(BuiltinTy::Slice) => PtrMetadata::Length,
773                    TypeId::Builtin(BuiltinTy::Str) => PtrMetadata::Length,
774                }
775            }
776            TyKind::DynTrait(pred) => match pred.vtable_ref(translated) {
777                Some(vtable) => PtrMetadata::VTable(vtable),
778                None => PtrMetadata::InheritFrom(
779                    TyKind::Error(format!(
780                        "Vtable for dyn trait {} not found",
781                        pred.with_ctx(&translated.into_fmt())
782                    ))
783                    .into(),
784                ),
785            },
786            TyKind::TraitType(..) | TyKind::TypeVar(_) => PtrMetadata::InheritFrom(self.clone()),
787            TyKind::Literal(_)
788            | TyKind::Never
789            | TyKind::Ref(..)
790            | TyKind::RawPtr(..)
791            | TyKind::FnPtr(..)
792            | TyKind::FnDef(..)
793            | TyKind::Error(_) => PtrMetadata::None,
794            // The metadata itself must be Sized, hence must with `PtrMetadata::None`
795            TyKind::PtrMetadata(_) => PtrMetadata::None,
796        }
797    }
798
799    pub fn as_array_or_slice(&self) -> Option<&Ty> {
800        match self.kind() {
801            TyKind::Adt(ty_ref)
802                if let TypeId::Builtin(BuiltinTy::Array | BuiltinTy::Slice) = ty_ref.id =>
803            {
804                Some(&ty_ref.generics.types[0])
805            }
806            _ => None,
807        }
808    }
809
810    pub fn as_tuple(&self) -> Option<&Vector<TypeVarId, Ty>> {
811        match self.kind() {
812            TyKind::Adt(ty_ref) if let TypeId::Tuple = ty_ref.id => Some(&ty_ref.generics.types),
813            _ => None,
814        }
815    }
816
817    pub fn as_adt(&self) -> Option<&TypeDeclRef> {
818        self.kind().as_adt()
819    }
820}
821
822impl TyKind {
823    pub fn into_ty(self) -> Ty {
824        Ty::new(self)
825    }
826}
827
828impl From<TyKind> for Ty {
829    fn from(kind: TyKind) -> Ty {
830        kind.into_ty()
831    }
832}
833
834/// Convenience for migration purposes.
835impl std::ops::Deref for Ty {
836    type Target = TyKind;
837
838    fn deref(&self) -> &Self::Target {
839        self.kind()
840    }
841}
842/// For deref patterns.
843unsafe impl std::ops::DerefPure for Ty {}
844
845impl TypeDeclRef {
846    pub fn new(id: TypeId, generics: GenericArgs) -> Self {
847        Self {
848            id,
849            generics: Box::new(generics),
850        }
851    }
852}
853
854impl TraitDeclRef {
855    pub fn self_ty<'a>(&'a self, krate: &'a TranslatedCrate) -> Option<&'a Ty> {
856        match self.generics.types.iter().next() {
857            Some(ty) => return Some(ty),
858            // TODO(mono): A monomorphized trait takes no arguments.
859            None => {
860                let name = krate.item_name(self.id)?;
861                let args = name.name.last()?.as_monomorphized()?;
862                args.types.iter().next()
863            }
864        }
865    }
866}
867
868impl TraitRef {
869    pub fn new_builtin(
870        trait_id: TraitDeclId,
871        ty: Ty,
872        parents: Vector<TraitClauseId, TraitRef>,
873    ) -> Self {
874        let trait_decl_ref = RegionBinder::empty(TraitDeclRef {
875            id: trait_id,
876            generics: Box::new(GenericArgs::new_types([ty].into())),
877        });
878        TraitRef {
879            kind: TraitRefKind::BuiltinOrAuto {
880                parent_trait_refs: parents,
881                types: Default::default(),
882            },
883            trait_decl_ref,
884        }
885    }
886}
887
888impl PtrMetadata {
889    pub fn into_type(self) -> Ty {
890        match self {
891            PtrMetadata::None => Ty::mk_unit(),
892            PtrMetadata::Length => Ty::mk_usize(),
893            PtrMetadata::VTable(type_decl_ref) => Ty::new(TyKind::Ref(
894                Region::Static,
895                Ty::new(TyKind::Adt(type_decl_ref)),
896                RefKind::Shared,
897            )),
898            PtrMetadata::InheritFrom(ty) => Ty::new(TyKind::PtrMetadata(ty)),
899        }
900    }
901}
902
903impl Field {
904    /// The new name for this field, as suggested by the `#[charon::rename]` attribute.
905    pub fn renamed_name(&self) -> Option<&str> {
906        self.attr_info.rename.as_deref().or(self.name.as_deref())
907    }
908
909    /// Whether this field has a `#[charon::opaque]` annotation.
910    pub fn is_opaque(&self) -> bool {
911        self.attr_info
912            .attributes
913            .iter()
914            .any(|attr| attr.is_opaque())
915    }
916}
917
918impl Variant {
919    /// The new name for this variant, as suggested by the `#[charon::rename]` and
920    /// `#[charon::variants_prefix]` attributes.
921    pub fn renamed_name(&self) -> &str {
922        self.attr_info
923            .rename
924            .as_deref()
925            .unwrap_or(self.name.as_ref())
926    }
927
928    /// Whether this variant has a `#[charon::opaque]` annotation.
929    pub fn is_opaque(&self) -> bool {
930        self.attr_info
931            .attributes
932            .iter()
933            .any(|attr| attr.is_opaque())
934    }
935}
936
937impl DynPredicate {
938    /// Get the vtable declaration reference with current generics applied.
939    /// Matches associated types from the vtable's generics with the dyn predicates's constraints.
940    ///
941    /// Rustc guarantees all associated types are specified in a `dyn Trait` type.
942    pub fn vtable_ref(&self, translated: &TranslatedCrate) -> Option<TypeDeclRef> {
943        // Get vtable_ref's ID with trait-ref's generics from dyn-self applied.
944        // Add associated types in correct order following the vtable's generics.
945
946        // 0. Prepare trait name for debug/error messages
947        let trait_name = self.binder.params.trait_clauses[0]
948            .trait_
949            .skip_binder
950            .id
951            .with_ctx(&translated.into_fmt())
952            .to_string();
953
954        // 1. Get vtable ref from trait declaration
955        //    Provides: 1) final return ID, 2) correct order of associated types
956        // Firstly, get the trait declaration for the vtable ref it stores.
957        let Some(trait_decl) = translated
958            .trait_decls
959            .get(self.binder.params.trait_clauses[0].trait_.skip_binder.id)
960        else {
961            return None;
962        };
963
964        // Get vtable ref from definition for correct ID.
965        // Generics in vtable ref are placeholders but provide correct order of the associated types.
966        let Some(vtable_ref) = &trait_decl.vtable else {
967            panic!(
968                "Vtable for trait {} is None, meaning the trait is non-dyn-compatible!",
969                trait_name
970            );
971        };
972
973        // 2. Get correct generics for vtable ref from `dyn_self_ty`
974        //    The binder contains all target generics info.
975        let binder = &self.binder;
976
977        // 3. Prepare "basic part" of generics from trait ref (without associated types)
978        // The trait ref `dyn Trait<_dyn, Arg1, ..., ArgN>`, no associated types.
979        // First trait clause is the target one for vtable, guaranteed by `DynPredicate`.
980        let trait_ref = binder.params.trait_clauses[0].trait_.clone().erase();
981        // Type vars (except `_dyn`) are one level deeper, move out after removing `_dyn`.
982        trace!(
983            "Getting vtable ref with trait-decl-ref {}.",
984            trait_ref.with_ctx(&translated.into_fmt())
985        );
986        let mut generics = trait_ref.generics.clone();
987        // Remove the first `_dyn` type argument
988        generics.types.remove_and_shift_ids(TypeVarId::ZERO);
989        // Move out of predicate binder for `_dyn`
990        generics = generics.move_from_under_binder().unwrap();
991
992        // 4. Prepare associated types part in same order as vtable's generics
993        // Utilise the vtable ref form:
994        // `{vtable}<TraitArg1, ..., SuperTrait::Assoc1, ..., Self::AssocN>`
995        //
996        // Use trait ID + assoc name (`Trait::AssocTy`) to uniquely identify
997        let assoc_tys = vtable_ref
998            .generics
999            .types
1000            .iter()
1001            .filter_map(|ty| {
1002                if let TyKind::TraitType(tref, name) = &ty.kind() {
1003                    Some((tref.trait_decl_ref.skip_binder.id, name.clone()))
1004                } else {
1005                    None
1006                }
1007            })
1008            .collect_vec();
1009
1010        // Find correct type argument from dyn trait's constraints for each assoc type.
1011        // TODO: use proper normalization here instead of doing it by hand
1012        for (trait_id, assoc_name) in assoc_tys {
1013            // Find it
1014            let Some(assoc_ty) = binder.params.trait_type_constraints.iter().find_map(|c| {
1015                let c = c.clone().erase();
1016                if c.trait_ref.trait_decl_ref.skip_binder.id == trait_id
1017                    && c.type_name == assoc_name
1018                {
1019                    // Move potentially bounded type out of `_dyn` binder
1020                    Some(c.ty.clone().move_from_under_binder().unwrap())
1021                } else {
1022                    None
1023                }
1024            }) else {
1025                let dyn_self_ty = Ty::new(TyKind::DynTrait(self.clone()));
1026                panic!(
1027                    "Could not find associated type {}::{} for vtable of trait {} in dyn Trait type: {}",
1028                    trait_id.with_ctx(&translated.into_fmt()),
1029                    assoc_name,
1030                    trait_name,
1031                    dyn_self_ty.with_ctx(&translated.into_fmt())
1032                );
1033            };
1034            // Push it
1035            generics.types.push(assoc_ty);
1036        }
1037
1038        // 5. Return vtable ref's ID with correct generics
1039        Some(TypeDeclRef {
1040            id: vtable_ref.id,
1041            generics,
1042        })
1043    }
1044}
1045
1046impl RefKind {
1047    pub fn mutable(x: bool) -> Self {
1048        if x { Self::Mut } else { Self::Shared }
1049    }
1050}
1051
1052/// Visitor for type-level variables. Used to visit the variables contained in a value, as seen
1053/// from the outside of the value. This means that any variable bound inside the value will be
1054/// skipped, and all the seen De Bruijn indices will count from the outside of the value. The
1055/// returned value, if any, will be put in place of the variable.
1056pub trait VarsVisitor {
1057    fn visit_region_var(&mut self, _v: RegionDbVar) -> Option<Region> {
1058        None
1059    }
1060    fn visit_type_var(&mut self, _v: TypeDbVar) -> Option<Ty> {
1061        None
1062    }
1063    fn visit_const_generic_var(&mut self, _v: ConstGenericDbVar) -> Option<ConstGeneric> {
1064        None
1065    }
1066    fn visit_clause_var(&mut self, _v: ClauseDbVar) -> Option<TraitRefKind> {
1067        None
1068    }
1069    fn visit_self_clause(&mut self) -> Option<TraitRefKind> {
1070        None
1071    }
1072}
1073
1074/// Visitor for the [TyVisitable::substitute] function.
1075/// This substitutes variables bound at the level where we start to substitute (level 0).
1076#[derive(Visitor)]
1077pub(crate) struct SubstVisitor<'a> {
1078    generics: &'a GenericArgs,
1079    self_ref: &'a TraitRefKind,
1080    /// Whether to substitute explicit variables only (types, regions, const generics).
1081    explicits_only: bool,
1082}
1083impl<'a> SubstVisitor<'a> {
1084    pub(crate) fn new(
1085        generics: &'a GenericArgs,
1086        self_ref: &'a TraitRefKind,
1087        explicits_only: bool,
1088    ) -> Self {
1089        Self {
1090            generics,
1091            self_ref,
1092            explicits_only,
1093        }
1094    }
1095
1096    /// Returns the value for this variable, if any.
1097    fn process_var<Id, T>(&self, var: DeBruijnVar<Id>, get: impl Fn(Id) -> &'a T) -> Option<T>
1098    where
1099        Id: Copy,
1100        T: Clone + TyVisitable,
1101        DeBruijnVar<Id>: Into<T>,
1102    {
1103        match var {
1104            DeBruijnVar::Bound(dbid, varid) => {
1105                Some(if let Some(dbid) = dbid.sub(DeBruijnId::one()) {
1106                    // This is bound outside the binder we're substituting for.
1107                    DeBruijnVar::Bound(dbid, varid).into()
1108                } else {
1109                    get(varid).clone()
1110                })
1111            }
1112            DeBruijnVar::Free(..) => None,
1113        }
1114    }
1115}
1116impl VarsVisitor for SubstVisitor<'_> {
1117    fn visit_region_var(&mut self, v: RegionDbVar) -> Option<Region> {
1118        self.process_var(v, |id| &self.generics[id])
1119    }
1120    fn visit_type_var(&mut self, v: TypeDbVar) -> Option<Ty> {
1121        self.process_var(v, |id| &self.generics[id])
1122    }
1123    fn visit_const_generic_var(&mut self, v: ConstGenericDbVar) -> Option<ConstGeneric> {
1124        self.process_var(v, |id| &self.generics[id])
1125    }
1126    fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
1127        if self.explicits_only {
1128            None
1129        } else {
1130            self.process_var(v, |id| &self.generics[id].kind)
1131        }
1132    }
1133    fn visit_self_clause(&mut self) -> Option<TraitRefKind> {
1134        Some(self.self_ref.clone())
1135    }
1136}
1137
1138/// Types that are involved at the type-level and may be substituted around.
1139pub trait TyVisitable: Sized + AstVisitable {
1140    /// Visit the variables contained in `self`, as seen from the outside of `self`. This means
1141    /// that any variable bound inside `self` will be skipped, and all the seen De Bruijn indices
1142    /// will count from the outside of `self`.
1143    fn visit_vars(&mut self, v: &mut impl VarsVisitor) {
1144        #[derive(Visitor)]
1145        struct Wrap<'v, V> {
1146            v: &'v mut V,
1147            depth: DeBruijnId,
1148        }
1149        impl<V: VarsVisitor> VisitAstMut for Wrap<'_, V> {
1150            fn enter_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
1151                self.depth = self.depth.incr()
1152            }
1153            fn exit_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
1154                self.depth = self.depth.decr()
1155            }
1156            fn enter_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
1157                self.depth = self.depth.incr()
1158            }
1159            fn exit_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
1160                self.depth = self.depth.decr()
1161            }
1162
1163            fn exit_region(&mut self, r: &mut Region) {
1164                if let Region::Var(var) = r
1165                    && let Some(var) = var.move_out_from_depth(self.depth)
1166                    && let Some(new_r) = self.v.visit_region_var(var)
1167                {
1168                    *r = new_r.move_under_binders(self.depth);
1169                }
1170            }
1171            fn exit_ty(&mut self, ty: &mut Ty) {
1172                if let TyKind::TypeVar(var) = ty.kind()
1173                    && let Some(var) = var.move_out_from_depth(self.depth)
1174                    && let Some(new_ty) = self.v.visit_type_var(var)
1175                {
1176                    *ty = new_ty.move_under_binders(self.depth);
1177                }
1178            }
1179            fn exit_const_generic(&mut self, cg: &mut ConstGeneric) {
1180                if let ConstGeneric::Var(var) = cg
1181                    && let Some(var) = var.move_out_from_depth(self.depth)
1182                    && let Some(new_cg) = self.v.visit_const_generic_var(var)
1183                {
1184                    *cg = new_cg.move_under_binders(self.depth);
1185                }
1186            }
1187            fn exit_constant_expr(&mut self, ce: &mut ConstantExpr) {
1188                if let ConstantExprKind::Var(var) = &mut ce.kind
1189                    && let Some(var) = var.move_out_from_depth(self.depth)
1190                    && let Some(new_cg) = self.v.visit_const_generic_var(var)
1191                {
1192                    ce.kind = new_cg.move_under_binders(self.depth).into();
1193                }
1194            }
1195            fn exit_trait_ref_kind(&mut self, kind: &mut TraitRefKind) {
1196                match kind {
1197                    TraitRefKind::SelfId => {
1198                        if let Some(new_kind) = self.v.visit_self_clause() {
1199                            *kind = new_kind.move_under_binders(self.depth);
1200                        }
1201                    }
1202                    TraitRefKind::Clause(var) => {
1203                        if let Some(var) = var.move_out_from_depth(self.depth)
1204                            && let Some(new_kind) = self.v.visit_clause_var(var)
1205                        {
1206                            *kind = new_kind.move_under_binders(self.depth);
1207                        }
1208                    }
1209                    _ => {}
1210                }
1211            }
1212        }
1213        let _ = self.drive_mut(&mut Wrap {
1214            v,
1215            depth: DeBruijnId::zero(),
1216        });
1217    }
1218
1219    /// Substitute the generic variables inside `self` by replacing them with the provided values.
1220    /// Note: if `self` is an item that comes from a `TraitDecl`, you most likely want to use
1221    /// `substitute_with_self`.
1222    fn substitute(self, generics: &GenericArgs) -> Self {
1223        self.substitute_with_self(generics, &TraitRefKind::SelfId)
1224    }
1225    /// Substitute only the type, region and const generic args.
1226    fn substitute_explicits(mut self, generics: &GenericArgs) -> Self {
1227        let _ = self.visit_vars(&mut SubstVisitor::new(
1228            generics,
1229            &TraitRefKind::SelfId,
1230            true,
1231        ));
1232        self
1233    }
1234    /// Substitute the generic variables as well as the `TraitRefKind::Self` trait ref.
1235    fn substitute_with_self(mut self, generics: &GenericArgs, self_ref: &TraitRefKind) -> Self {
1236        let _ = self.visit_vars(&mut SubstVisitor::new(generics, self_ref, false));
1237        self
1238    }
1239
1240    /// Move under one binder.
1241    fn move_under_binder(self) -> Self {
1242        self.move_under_binders(DeBruijnId::one())
1243    }
1244
1245    /// Move under `depth` binders.
1246    fn move_under_binders(mut self, depth: DeBruijnId) -> Self {
1247        if !depth.is_zero() {
1248            let Continue(()) = self.visit_db_id::<Infallible>(|id| {
1249                *id = id.plus(depth);
1250                Continue(())
1251            });
1252        }
1253        self
1254    }
1255
1256    /// Move from under one binder.
1257    fn move_from_under_binder(self) -> Option<Self> {
1258        self.move_from_under_binders(DeBruijnId::one())
1259    }
1260
1261    /// Move the value out of `depth` binders. Returns `None` if it contains a variable bound in
1262    /// one of these `depth` binders.
1263    fn move_from_under_binders(mut self, depth: DeBruijnId) -> Option<Self> {
1264        self.visit_db_id::<()>(|id| match id.sub(depth) {
1265            Some(sub) => {
1266                *id = sub;
1267                Continue(())
1268            }
1269            None => Break(()),
1270        })
1271        .is_continue()
1272        .then_some(self)
1273    }
1274
1275    /// Visit the de Bruijn ids contained in `self`, as seen from the outside of `self`. This means
1276    /// that any variable bound inside `self` will be skipped, and all the seen indices will count
1277    /// from the outside of self.
1278    fn visit_db_id<B>(
1279        &mut self,
1280        f: impl FnMut(&mut DeBruijnId) -> ControlFlow<B>,
1281    ) -> ControlFlow<B> {
1282        struct Wrap<F> {
1283            f: F,
1284            depth: DeBruijnId,
1285        }
1286        impl<B, F> Visitor for Wrap<F>
1287        where
1288            F: FnMut(&mut DeBruijnId) -> ControlFlow<B>,
1289        {
1290            type Break = B;
1291        }
1292        impl<B, F> VisitAstMut for Wrap<F>
1293        where
1294            F: FnMut(&mut DeBruijnId) -> ControlFlow<B>,
1295        {
1296            fn enter_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
1297                self.depth = self.depth.incr()
1298            }
1299            fn exit_region_binder<T: AstVisitable>(&mut self, _: &mut RegionBinder<T>) {
1300                self.depth = self.depth.decr()
1301            }
1302            fn enter_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
1303                self.depth = self.depth.incr()
1304            }
1305            fn exit_binder<T: AstVisitable>(&mut self, _: &mut Binder<T>) {
1306                self.depth = self.depth.decr()
1307            }
1308
1309            fn visit_de_bruijn_id(&mut self, x: &mut DeBruijnId) -> ControlFlow<Self::Break> {
1310                if let Some(mut shifted) = x.sub(self.depth) {
1311                    (self.f)(&mut shifted)?;
1312                    *x = shifted.plus(self.depth)
1313                }
1314                Continue(())
1315            }
1316        }
1317        self.drive_mut(&mut Wrap {
1318            f,
1319            depth: DeBruijnId::zero(),
1320        })
1321    }
1322}
1323
1324impl TypeDecl {
1325    /// Looks up the variant corresponding to the tag (i.e. the in-memory bytes that represent the discriminant).
1326    /// Returns `None` for types that don't have a relevant discriminant (e.g. uninhabited types).
1327    ///
1328    /// If the `tag` does not correspond to any valid discriminant but there is a niche,
1329    /// the resulting `VariantId` will be for the untagged variant [`TagEncoding::Niche::untagged_variant`].
1330    pub fn get_variant_from_tag(&self, tag: ScalarValue) -> Option<VariantId> {
1331        let layout = self.layout.as_ref()?;
1332        if layout.uninhabited {
1333            return None;
1334        };
1335        let discr_layout = layout.discriminant_layout.as_ref()?;
1336
1337        let variant_for_tag =
1338            layout
1339                .variant_layouts
1340                .iter_indexed()
1341                .find_map(|(id, variant_layout)| {
1342                    if variant_layout.tag == Some(tag) {
1343                        Some(id)
1344                    } else {
1345                        None
1346                    }
1347                });
1348
1349        match &discr_layout.encoding {
1350            TagEncoding::Direct => {
1351                assert_eq!(tag.get_integer_ty(), discr_layout.tag_ty);
1352                variant_for_tag
1353            }
1354            TagEncoding::Niche { untagged_variant } => variant_for_tag.or(Some(*untagged_variant)),
1355        }
1356    }
1357
1358    pub fn is_c_repr(&self) -> bool {
1359        self.repr
1360            .as_ref()
1361            .is_some_and(|repr| repr.repr_algo == ReprAlgorithm::C)
1362    }
1363
1364    pub fn get_field_by_name(
1365        &self,
1366        variant: Option<VariantId>,
1367        field_name: &str,
1368    ) -> Option<(FieldId, &Field)> {
1369        let fields = match &self.kind {
1370            TypeDeclKind::Struct(fields) | TypeDeclKind::Union(fields) => fields,
1371            TypeDeclKind::Enum(variants) => &variants[variant.unwrap()].fields,
1372            _ => return None,
1373        };
1374        fields
1375            .iter_indexed()
1376            .find(|(_, field)| field.name.as_deref() == Some(field_name))
1377    }
1378}
1379
1380impl Layout {
1381    pub fn is_variant_uninhabited(&self, variant_id: VariantId) -> bool {
1382        if let Some(v) = self.variant_layouts.get(variant_id) {
1383            v.uninhabited
1384        } else {
1385            false
1386        }
1387    }
1388}
1389
1390impl ReprOptions {
1391    /// Whether this representation options guarantee a fixed
1392    /// field ordering for the type.
1393    ///
1394    /// Since we don't support `repr(simd)` or `repr(linear)` yet, this is
1395    /// the case if it's either `repr(C)` or an explicit discriminant type for
1396    /// an enum with fields (if it doesn't have fields, this obviously doesn't matter anyway).
1397    ///
1398    /// Cf. <https://doc.rust-lang.org/reference/type-layout.html#r-layout.repr.c.struct>
1399    /// and <https://doc.rust-lang.org/reference/type-layout.html#r-layout.repr.primitive.adt>.
1400    pub fn guarantees_fixed_field_order(&self) -> bool {
1401        self.repr_algo == ReprAlgorithm::C || self.explicit_discr_type
1402    }
1403}
1404
1405impl<T: AstVisitable> TyVisitable for T {}
1406
1407impl Eq for TraitParam {}
1408
1409mk_index_impls!(GenericArgs.regions[RegionId]: Region);
1410mk_index_impls!(GenericArgs.types[TypeVarId]: Ty);
1411mk_index_impls!(GenericArgs.const_generics[ConstGenericVarId]: ConstGeneric);
1412mk_index_impls!(GenericArgs.trait_refs[TraitClauseId]: TraitRef);
1413mk_index_impls!(GenericParams.regions[RegionId]: RegionParam);
1414mk_index_impls!(GenericParams.types[TypeVarId]: TypeParam);
1415mk_index_impls!(GenericParams.const_generics[ConstGenericVarId]: ConstGenericParam);
1416mk_index_impls!(GenericParams.trait_clauses[TraitClauseId]: TraitParam);