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