Skip to main content

charon_lib/ast/
types_utils.rs

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