flux_middle/rty/
mod.rs

1//! Defines how flux represents refinement types internally. Definitions in this module are used
2//! during refinement type checking. A couple of important differences between definitions in this
3//! module and in [`crate::fhir`] are:
4//!
5//! * Types in this module use debruijn indices to represent local binders.
6//! * Data structures are interned so they can be cheaply cloned.
7mod binder;
8pub mod canonicalize;
9mod expr;
10pub mod fold;
11pub mod normalize;
12mod pretty;
13pub mod refining;
14pub mod region_matching;
15pub mod subst;
16use std::{borrow::Cow, cmp::Ordering, fmt, hash::Hash, sync::LazyLock};
17
18pub use binder::{Binder, BoundReftKind, BoundVariableKind, BoundVariableKinds, EarlyBinder};
19use bitflags::bitflags;
20pub use expr::{
21    AggregateKind, AliasReft, BinOp, BoundReft, Constant, Ctor, ESpan, EVid, EarlyReftParam, Expr,
22    ExprKind, FieldProj, HoleKind, InternalFuncKind, KVar, KVid, Lambda, Loc, Name, Path, Real,
23    SpecFuncKind, UnOp, Var,
24};
25pub use flux_arc_interner::List;
26use flux_arc_interner::{Interned, impl_internable, impl_slice_internable};
27use flux_common::{bug, tracked_span_assert_eq, tracked_span_bug};
28use flux_config::OverflowMode;
29use flux_macros::{TypeFoldable, TypeVisitable};
30pub use flux_rustc_bridge::ty::{
31    AliasKind, BoundRegion, BoundRegionKind, BoundVar, Const, ConstKind, ConstVid, DebruijnIndex,
32    EarlyParamRegion, LateParamRegion, LateParamRegionKind,
33    Region::{self, *},
34    RegionVid,
35};
36use flux_rustc_bridge::{
37    ToRustc,
38    mir::{Place, RawPtrKind},
39    ty::{self, GenericArgsExt as _, VariantDef},
40};
41use itertools::Itertools;
42pub use normalize::{NormalizeInfo, NormalizedDefns, local_deps};
43use refining::{Refine as _, Refiner};
44use rustc_abi;
45pub use rustc_abi::{FIRST_VARIANT, VariantIdx};
46use rustc_data_structures::{fx::FxIndexMap, snapshot_map::SnapshotMap, unord::UnordMap};
47use rustc_hir::{LangItem, Safety, def_id::DefId};
48use rustc_index::{IndexSlice, IndexVec, newtype_index};
49use rustc_macros::{Decodable, Encodable, TyDecodable, TyEncodable, extension};
50use rustc_middle::ty::{TyCtxt, fast_reject::SimplifiedType};
51pub use rustc_middle::{
52    mir::Mutability,
53    ty::{AdtFlags, ClosureKind, FloatTy, IntTy, ParamConst, ParamTy, ScalarInt, UintTy},
54};
55use rustc_span::{DUMMY_SP, Span, Symbol, sym, symbol::kw};
56use rustc_type_ir::Upcast as _;
57pub use rustc_type_ir::{INNERMOST, TyVid};
58
59use self::fold::TypeFoldable;
60pub use crate::fhir::InferMode;
61use crate::{
62    LocalDefId,
63    def_id::{FluxDefId, FluxLocalDefId},
64    fhir::{self, FhirId, FluxOwnerId},
65    global_env::GlobalEnv,
66    pretty::{Pretty, PrettyCx},
67    queries::{QueryErr, QueryResult},
68    rty::subst::SortSubst,
69};
70
71/// The definition of the data sort automatically generated for a struct or enum.
72#[derive(Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
73pub struct AdtSortDef(Interned<AdtSortDefData>);
74
75#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
76pub struct AdtSortVariant {
77    /// The list of field names as declared in the `#[flux::refined_by(...)]` annotation
78    field_names: Vec<Symbol>,
79    /// The sort of each of the fields. Note that these can contain [sort variables]. Methods used
80    /// to access these sorts guarantee they are properly instantiated.
81    ///
82    /// [sort variables]: Sort::Var
83    sorts: List<Sort>,
84}
85
86impl AdtSortVariant {
87    pub fn new(fields: Vec<(Symbol, Sort)>) -> Self {
88        let (field_names, sorts) = fields.into_iter().unzip();
89        AdtSortVariant { field_names, sorts: List::from_vec(sorts) }
90    }
91
92    pub fn fields(&self) -> usize {
93        self.sorts.len()
94    }
95
96    pub fn field_names(&self) -> &Vec<Symbol> {
97        &self.field_names
98    }
99
100    pub fn sort_by_field_name(&self, args: &[Sort]) -> FxIndexMap<Symbol, Sort> {
101        std::iter::zip(&self.field_names, &self.sorts.fold_with(&mut SortSubst::new(args)))
102            .map(|(name, sort)| (*name, sort.clone()))
103            .collect()
104    }
105
106    pub fn field_by_name(
107        &self,
108        def_id: DefId,
109        args: &[Sort],
110        name: Symbol,
111    ) -> Option<(FieldProj, Sort)> {
112        let idx = self.field_names.iter().position(|it| name == *it)?;
113        let proj = FieldProj::Adt { def_id, field: idx as u32 };
114        let sort = self.sorts[idx].fold_with(&mut SortSubst::new(args));
115        Some((proj, sort))
116    }
117
118    pub fn field_sorts(&self, args: &[Sort]) -> List<Sort> {
119        self.sorts.fold_with(&mut SortSubst::new(args))
120    }
121
122    pub fn field_sorts_instantiate_identity(&self) -> List<Sort> {
123        self.sorts.clone()
124    }
125
126    pub fn projections(&self, def_id: DefId) -> impl Iterator<Item = FieldProj> {
127        (0..self.fields()).map(move |i| FieldProj::Adt { def_id, field: i as u32 })
128    }
129}
130
131#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
132struct AdtSortDefData {
133    /// [`DefId`] of the struct or enum this data sort is associated to.
134    def_id: DefId,
135    /// The list of the type parameters used in the `#[flux::refined_by(..)]` annotation.
136    ///
137    /// See [`fhir::RefinedBy::sort_params`] for more details. This is a version of that but using
138    /// [`ParamTy`] instead of [`DefId`].
139    ///
140    /// The length of this list corresponds to the number of sort variables bound by this definition.
141    params: Vec<ParamTy>,
142    /// A vec of variants of the ADT;
143    /// - a `struct` sort -- used for types with a `refined_by` has a single variant;
144    /// - a `reflected` sort -- used for `reflected` enums have multiple variants
145    variants: IndexVec<VariantIdx, AdtSortVariant>,
146    is_reflected: bool,
147    is_struct: bool,
148}
149
150impl AdtSortDef {
151    pub fn new(
152        def_id: DefId,
153        params: Vec<ParamTy>,
154        variants: IndexVec<VariantIdx, AdtSortVariant>,
155        is_reflected: bool,
156        is_struct: bool,
157    ) -> Self {
158        Self(Interned::new(AdtSortDefData { def_id, params, variants, is_reflected, is_struct }))
159    }
160
161    pub fn did(&self) -> DefId {
162        self.0.def_id
163    }
164
165    pub fn variant(&self, idx: VariantIdx) -> &AdtSortVariant {
166        &self.0.variants[idx]
167    }
168
169    pub fn variants(&self) -> &IndexSlice<VariantIdx, AdtSortVariant> {
170        &self.0.variants
171    }
172
173    pub fn opt_struct_variant(&self) -> Option<&AdtSortVariant> {
174        if self.is_struct() { Some(self.struct_variant()) } else { None }
175    }
176
177    #[track_caller]
178    pub fn struct_variant(&self) -> &AdtSortVariant {
179        tracked_span_assert_eq!(self.0.is_struct, true);
180        &self.0.variants[FIRST_VARIANT]
181    }
182
183    pub fn is_reflected(&self) -> bool {
184        self.0.is_reflected
185    }
186
187    pub fn is_struct(&self) -> bool {
188        self.0.is_struct
189    }
190
191    pub fn to_sort(&self, args: &[GenericArg]) -> Sort {
192        let sorts = self
193            .filter_generic_args(args)
194            .map(|arg| arg.expect_base().sort())
195            .collect();
196
197        Sort::App(SortCtor::Adt(self.clone()), sorts)
198    }
199
200    /// Given a list of generic args, returns an iterator of the generic arguments that should be
201    /// mapped to sorts for instantiation.
202    pub fn filter_generic_args<'a, A>(&'a self, args: &'a [A]) -> impl Iterator<Item = &'a A> + 'a {
203        self.0.params.iter().map(|p| &args[p.index as usize])
204    }
205
206    pub fn identity_args(&self) -> List<Sort> {
207        (0..self.0.params.len())
208            .map(|i| Sort::Var(ParamSort::from(i)))
209            .collect()
210    }
211
212    /// Gives the number of sort variables bound by this definition.
213    pub fn param_count(&self) -> usize {
214        self.0.params.len()
215    }
216}
217
218#[derive(Debug, Clone, Default, Encodable, Decodable)]
219pub struct Generics {
220    pub parent: Option<DefId>,
221    pub parent_count: usize,
222    pub own_params: List<GenericParamDef>,
223    pub has_self: bool,
224}
225
226impl Generics {
227    pub fn count(&self) -> usize {
228        self.parent_count + self.own_params.len()
229    }
230
231    pub fn own_default_count(&self) -> usize {
232        self.own_params
233            .iter()
234            .filter(|param| {
235                match param.kind {
236                    GenericParamDefKind::Type { has_default }
237                    | GenericParamDefKind::Const { has_default }
238                    | GenericParamDefKind::Base { has_default } => has_default,
239                    GenericParamDefKind::Lifetime => false,
240                }
241            })
242            .count()
243    }
244
245    pub fn param_at(&self, param_index: usize, genv: GlobalEnv) -> QueryResult<GenericParamDef> {
246        if let Some(index) = param_index.checked_sub(self.parent_count) {
247            Ok(self.own_params[index].clone())
248        } else {
249            let parent = self.parent.expect("parent_count > 0 but no parent?");
250            genv.generics_of(parent)?.param_at(param_index, genv)
251        }
252    }
253
254    pub fn const_params(&self, genv: GlobalEnv) -> QueryResult<Vec<(ParamConst, Sort)>> {
255        // FIXME(nilehmann) this shouldn't use the methods in `flux_middle::sort_of` to get the sort
256        let mut res = vec![];
257        for i in 0..self.count() {
258            let param = self.param_at(i, genv)?;
259            if let GenericParamDefKind::Const { .. } = param.kind
260                && let Some(sort) = genv.sort_of_generic_param(param.def_id)?
261            {
262                let param_const = ParamConst { name: param.name, index: param.index };
263                res.push((param_const, sort));
264            }
265        }
266        Ok(res)
267    }
268}
269
270#[derive(Debug, Clone, TyEncodable, TyDecodable)]
271pub struct RefinementGenerics {
272    pub parent: Option<DefId>,
273    pub parent_count: usize,
274    pub own_params: List<RefineParam>,
275}
276
277#[derive(
278    PartialEq, Eq, Debug, Clone, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
279)]
280pub struct RefineParam {
281    pub sort: Sort,
282    pub name: Symbol,
283    pub mode: InferMode,
284}
285
286#[derive(Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
287pub struct GenericParamDef {
288    pub kind: GenericParamDefKind,
289    pub def_id: DefId,
290    pub index: u32,
291    pub name: Symbol,
292}
293
294#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
295pub enum GenericParamDefKind {
296    Type { has_default: bool },
297    Base { has_default: bool },
298    Lifetime,
299    Const { has_default: bool },
300}
301
302pub const SELF_PARAM_TY: ParamTy = ParamTy { index: 0, name: kw::SelfUpper };
303
304#[derive(Debug, Clone, TyEncodable, TyDecodable)]
305pub struct GenericPredicates {
306    pub parent: Option<DefId>,
307    pub predicates: List<Clause>,
308}
309
310#[derive(
311    Debug, PartialEq, Eq, Hash, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
312)]
313pub struct Clause {
314    kind: Binder<ClauseKind>,
315}
316
317impl Clause {
318    pub fn new(vars: impl Into<List<BoundVariableKind>>, kind: ClauseKind) -> Self {
319        Clause { kind: Binder::bind_with_vars(kind, vars.into()) }
320    }
321
322    pub fn kind(&self) -> Binder<ClauseKind> {
323        self.kind.clone()
324    }
325
326    fn as_trait_clause(&self) -> Option<Binder<TraitPredicate>> {
327        let clause = self.kind();
328        if let ClauseKind::Trait(trait_clause) = clause.skip_binder_ref() {
329            Some(clause.rebind(trait_clause.clone()))
330        } else {
331            None
332        }
333    }
334
335    pub fn as_projection_clause(&self) -> Option<Binder<ProjectionPredicate>> {
336        let clause = self.kind();
337        if let ClauseKind::Projection(proj_clause) = clause.skip_binder_ref() {
338            Some(clause.rebind(proj_clause.clone()))
339        } else {
340            None
341        }
342    }
343
344    // FIXME(nilehmann) we should deal with the binder in all the places this is used instead of
345    // blindly skipping it here
346    pub fn kind_skipping_binder(&self) -> ClauseKind {
347        self.kind.clone().skip_binder()
348    }
349
350    /// Group `Fn` trait clauses with their corresponding `FnOnce::Output` projection
351    /// predicate. This assumes there's exactly one corresponding projection predicate and will
352    /// crash otherwise.
353    pub fn split_off_fn_trait_clauses(
354        genv: GlobalEnv,
355        clauses: &Clauses,
356    ) -> (Vec<Clause>, Vec<Binder<FnTraitPredicate>>) {
357        let mut fn_trait_clauses = vec![];
358        let mut fn_trait_output_clauses = vec![];
359        let mut rest = vec![];
360        for clause in clauses {
361            if let Some(trait_clause) = clause.as_trait_clause()
362                && let Some(kind) = genv.tcx().fn_trait_kind_from_def_id(trait_clause.def_id())
363            {
364                fn_trait_clauses.push((kind, trait_clause));
365            } else if let Some(proj_clause) = clause.as_projection_clause()
366                && genv.is_fn_output(proj_clause.projection_def_id())
367            {
368                fn_trait_output_clauses.push(proj_clause);
369            } else {
370                rest.push(clause.clone());
371            }
372        }
373        let fn_trait_clauses = fn_trait_clauses
374            .into_iter()
375            .map(|(kind, fn_trait_clause)| {
376                let mut candidates = vec![];
377                for fn_trait_output_clause in &fn_trait_output_clauses {
378                    if fn_trait_output_clause.self_ty() == fn_trait_clause.self_ty() {
379                        candidates.push(fn_trait_output_clause.clone());
380                    }
381                }
382                tracked_span_assert_eq!(candidates.len(), 1);
383                let proj_pred = candidates.pop().unwrap().skip_binder();
384                fn_trait_clause.map(|fn_trait_clause| {
385                    FnTraitPredicate {
386                        kind,
387                        self_ty: fn_trait_clause.self_ty().to_ty(),
388                        tupled_args: fn_trait_clause.trait_ref.args[1].expect_base().to_ty(),
389                        output: proj_pred.term.to_ty(),
390                    }
391                })
392            })
393            .collect_vec();
394        (rest, fn_trait_clauses)
395    }
396}
397
398impl<'tcx> ToRustc<'tcx> for Clause {
399    type T = rustc_middle::ty::Clause<'tcx>;
400
401    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
402        self.kind.to_rustc(tcx).upcast(tcx)
403    }
404}
405
406impl From<Binder<ClauseKind>> for Clause {
407    fn from(kind: Binder<ClauseKind>) -> Self {
408        Clause { kind }
409    }
410}
411
412pub type Clauses = List<Clause>;
413
414#[derive(
415    Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
416)]
417pub enum ClauseKind {
418    Trait(TraitPredicate),
419    Projection(ProjectionPredicate),
420    RegionOutlives(RegionOutlivesPredicate),
421    TypeOutlives(TypeOutlivesPredicate),
422    ConstArgHasType(Const, Ty),
423}
424
425impl<'tcx> ToRustc<'tcx> for ClauseKind {
426    type T = rustc_middle::ty::ClauseKind<'tcx>;
427
428    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
429        match self {
430            ClauseKind::Trait(trait_predicate) => {
431                rustc_middle::ty::ClauseKind::Trait(trait_predicate.to_rustc(tcx))
432            }
433            ClauseKind::Projection(projection_predicate) => {
434                rustc_middle::ty::ClauseKind::Projection(projection_predicate.to_rustc(tcx))
435            }
436            ClauseKind::RegionOutlives(outlives_predicate) => {
437                rustc_middle::ty::ClauseKind::RegionOutlives(outlives_predicate.to_rustc(tcx))
438            }
439            ClauseKind::TypeOutlives(outlives_predicate) => {
440                rustc_middle::ty::ClauseKind::TypeOutlives(outlives_predicate.to_rustc(tcx))
441            }
442            ClauseKind::ConstArgHasType(constant, ty) => {
443                rustc_middle::ty::ClauseKind::ConstArgHasType(
444                    constant.to_rustc(tcx),
445                    ty.to_rustc(tcx),
446                )
447            }
448        }
449    }
450}
451
452#[derive(Eq, PartialEq, Hash, Clone, Debug, TyEncodable, TyDecodable)]
453pub struct OutlivesPredicate<T>(pub T, pub Region);
454
455pub type TypeOutlivesPredicate = OutlivesPredicate<Ty>;
456pub type RegionOutlivesPredicate = OutlivesPredicate<Region>;
457
458impl<'tcx, V: ToRustc<'tcx>> ToRustc<'tcx> for OutlivesPredicate<V> {
459    type T = rustc_middle::ty::OutlivesPredicate<'tcx, V::T>;
460
461    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
462        rustc_middle::ty::OutlivesPredicate(self.0.to_rustc(tcx), self.1.to_rustc(tcx))
463    }
464}
465
466#[derive(
467    Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
468)]
469pub struct TraitPredicate {
470    pub trait_ref: TraitRef,
471}
472
473impl TraitPredicate {
474    fn self_ty(&self) -> SubsetTyCtor {
475        self.trait_ref.self_ty()
476    }
477}
478
479impl<'tcx> ToRustc<'tcx> for TraitPredicate {
480    type T = rustc_middle::ty::TraitPredicate<'tcx>;
481
482    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
483        rustc_middle::ty::TraitPredicate {
484            polarity: rustc_middle::ty::PredicatePolarity::Positive,
485            trait_ref: self.trait_ref.to_rustc(tcx),
486        }
487    }
488}
489
490pub type PolyTraitPredicate = Binder<TraitPredicate>;
491
492impl PolyTraitPredicate {
493    fn def_id(&self) -> DefId {
494        self.skip_binder_ref().trait_ref.def_id
495    }
496
497    fn self_ty(&self) -> Binder<SubsetTyCtor> {
498        self.clone().map(|predicate| predicate.self_ty())
499    }
500}
501
502#[derive(
503    Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
504)]
505pub struct TraitRef {
506    pub def_id: DefId,
507    pub args: GenericArgs,
508}
509
510impl TraitRef {
511    pub fn self_ty(&self) -> SubsetTyCtor {
512        self.args[0].expect_base().clone()
513    }
514}
515
516impl<'tcx> ToRustc<'tcx> for TraitRef {
517    type T = rustc_middle::ty::TraitRef<'tcx>;
518
519    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
520        rustc_middle::ty::TraitRef::new(tcx, self.def_id, self.args.to_rustc(tcx))
521    }
522}
523
524pub type PolyTraitRef = Binder<TraitRef>;
525
526impl PolyTraitRef {
527    pub fn def_id(&self) -> DefId {
528        self.as_ref().skip_binder().def_id
529    }
530}
531
532#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
533pub enum ExistentialPredicate {
534    Trait(ExistentialTraitRef),
535    Projection(ExistentialProjection),
536    AutoTrait(DefId),
537}
538
539pub type PolyExistentialPredicate = Binder<ExistentialPredicate>;
540
541impl ExistentialPredicate {
542    /// See [`rustc_middle::ty::ExistentialPredicateStableCmpExt`]
543    pub fn stable_cmp(&self, tcx: TyCtxt, other: &Self) -> Ordering {
544        match (self, other) {
545            (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
546            (ExistentialPredicate::Projection(a), ExistentialPredicate::Projection(b)) => {
547                tcx.def_path_hash(a.def_id)
548                    .cmp(&tcx.def_path_hash(b.def_id))
549            }
550            (ExistentialPredicate::AutoTrait(a), ExistentialPredicate::AutoTrait(b)) => {
551                tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
552            }
553            (ExistentialPredicate::Trait(_), _) => Ordering::Less,
554            (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
555                Ordering::Greater
556            }
557            (ExistentialPredicate::Projection(_), _) => Ordering::Less,
558            (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
559        }
560    }
561}
562
563impl<'tcx> ToRustc<'tcx> for ExistentialPredicate {
564    type T = rustc_middle::ty::ExistentialPredicate<'tcx>;
565
566    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
567        match self {
568            ExistentialPredicate::Trait(trait_ref) => {
569                let trait_ref = rustc_middle::ty::ExistentialTraitRef::new_from_args(
570                    tcx,
571                    trait_ref.def_id,
572                    trait_ref.args.to_rustc(tcx),
573                );
574                rustc_middle::ty::ExistentialPredicate::Trait(trait_ref)
575            }
576            ExistentialPredicate::Projection(projection) => {
577                rustc_middle::ty::ExistentialPredicate::Projection(
578                    rustc_middle::ty::ExistentialProjection::new_from_args(
579                        tcx,
580                        projection.def_id,
581                        projection.args.to_rustc(tcx),
582                        projection.term.skip_binder_ref().to_rustc(tcx).into(),
583                    ),
584                )
585            }
586            ExistentialPredicate::AutoTrait(def_id) => {
587                rustc_middle::ty::ExistentialPredicate::AutoTrait(*def_id)
588            }
589        }
590    }
591}
592
593#[derive(
594    Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
595)]
596pub struct ExistentialTraitRef {
597    pub def_id: DefId,
598    pub args: GenericArgs,
599}
600
601pub type PolyExistentialTraitRef = Binder<ExistentialTraitRef>;
602
603impl PolyExistentialTraitRef {
604    pub fn def_id(&self) -> DefId {
605        self.as_ref().skip_binder().def_id
606    }
607}
608
609#[derive(
610    Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
611)]
612pub struct ExistentialProjection {
613    pub def_id: DefId,
614    pub args: GenericArgs,
615    pub term: SubsetTyCtor,
616}
617
618#[derive(
619    PartialEq, Eq, Hash, Debug, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
620)]
621pub struct ProjectionPredicate {
622    pub projection_ty: AliasTy,
623    pub term: SubsetTyCtor,
624}
625
626impl Pretty for ProjectionPredicate {
627    fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
628        write!(
629            f,
630            "ProjectionPredicate << projection_ty = {:?}, term = {:?} >>",
631            self.projection_ty, self.term
632        )
633    }
634}
635
636impl ProjectionPredicate {
637    pub fn self_ty(&self) -> SubsetTyCtor {
638        self.projection_ty.self_ty().clone()
639    }
640}
641
642impl<'tcx> ToRustc<'tcx> for ProjectionPredicate {
643    type T = rustc_middle::ty::ProjectionPredicate<'tcx>;
644
645    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
646        rustc_middle::ty::ProjectionPredicate {
647            projection_term: rustc_middle::ty::AliasTerm::new_from_args(
648                tcx,
649                self.projection_ty.def_id,
650                self.projection_ty.args.to_rustc(tcx),
651            ),
652            term: self.term.as_bty_skipping_binder().to_rustc(tcx).into(),
653        }
654    }
655}
656
657pub type PolyProjectionPredicate = Binder<ProjectionPredicate>;
658
659impl PolyProjectionPredicate {
660    pub fn projection_def_id(&self) -> DefId {
661        self.skip_binder_ref().projection_ty.def_id
662    }
663
664    pub fn self_ty(&self) -> Binder<SubsetTyCtor> {
665        self.clone().map(|predicate| predicate.self_ty())
666    }
667}
668
669#[derive(
670    Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
671)]
672pub struct FnTraitPredicate {
673    pub self_ty: Ty,
674    pub tupled_args: Ty,
675    pub output: Ty,
676    pub kind: ClosureKind,
677}
678
679impl Pretty for FnTraitPredicate {
680    fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
681        write!(
682            f,
683            "self = {:?}, args = {:?}, output = {:?}, kind = {}",
684            self.self_ty, self.tupled_args, self.output, self.kind
685        )
686    }
687}
688
689impl FnTraitPredicate {
690    pub fn fndef_sig(&self) -> FnSig {
691        let inputs = self.tupled_args.expect_tuple().iter().cloned().collect();
692        let ret = self.output.clone().shift_in_escaping(1);
693        let output = Binder::bind_with_vars(FnOutput::new(ret, vec![]), List::empty());
694        FnSig::new(Safety::Safe, rustc_abi::ExternAbi::Rust, List::empty(), inputs, output)
695    }
696}
697
698pub fn to_closure_sig(
699    tcx: TyCtxt,
700    closure_id: LocalDefId,
701    tys: &[Ty],
702    args: &flux_rustc_bridge::ty::GenericArgs,
703    poly_sig: &PolyFnSig,
704) -> PolyFnSig {
705    let closure_args = args.as_closure();
706    let kind_ty = closure_args.kind_ty().to_rustc(tcx);
707    let Some(kind) = kind_ty.to_opt_closure_kind() else {
708        bug!("to_closure_sig: expected closure kind, found {kind_ty:?}");
709    };
710
711    let mut vars = poly_sig.vars().clone().to_vec();
712    let fn_sig = poly_sig.clone().skip_binder();
713    let closure_ty = Ty::closure(closure_id.into(), tys, args);
714    let env_ty = match kind {
715        ClosureKind::Fn => {
716            vars.push(BoundVariableKind::Region(BoundRegionKind::ClosureEnv));
717            let br = BoundRegion {
718                var: BoundVar::from_usize(vars.len() - 1),
719                kind: BoundRegionKind::ClosureEnv,
720            };
721            Ty::mk_ref(ReBound(INNERMOST, br), closure_ty, Mutability::Not)
722        }
723        ClosureKind::FnMut => {
724            vars.push(BoundVariableKind::Region(BoundRegionKind::ClosureEnv));
725            let br = BoundRegion {
726                var: BoundVar::from_usize(vars.len() - 1),
727                kind: BoundRegionKind::ClosureEnv,
728            };
729            Ty::mk_ref(ReBound(INNERMOST, br), closure_ty, Mutability::Mut)
730        }
731        ClosureKind::FnOnce => closure_ty,
732    };
733
734    let inputs = std::iter::once(env_ty)
735        .chain(fn_sig.inputs().iter().cloned())
736        .collect::<Vec<_>>();
737    let output = fn_sig.output().clone();
738
739    let fn_sig = crate::rty::FnSig::new(
740        fn_sig.safety,
741        fn_sig.abi,
742        fn_sig.requires.clone(), // crate::rty::List::empty(),
743        inputs.into(),
744        output,
745    );
746
747    PolyFnSig::bind_with_vars(fn_sig, List::from(vars))
748}
749
750#[derive(
751    Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
752)]
753pub struct CoroutineObligPredicate {
754    pub def_id: DefId,
755    pub resume_ty: Ty,
756    pub upvar_tys: List<Ty>,
757    pub output: Ty,
758}
759
760#[derive(Copy, Clone, Encodable, Decodable, Hash, PartialEq, Eq)]
761pub struct AssocReft {
762    pub def_id: FluxDefId,
763    // NOTE: Field is used to denote final associated generic refinements on Traits
764    pub final_: bool,
765    pub span: Span,
766}
767
768impl AssocReft {
769    pub fn new(def_id: FluxDefId, final_: bool, span: Span) -> Self {
770        Self { def_id, final_, span }
771    }
772
773    pub fn name(&self) -> Symbol {
774        self.def_id.name()
775    }
776
777    pub fn def_id(&self) -> FluxDefId {
778        self.def_id
779    }
780}
781
782#[derive(Clone, Encodable, Decodable)]
783pub struct AssocRefinements {
784    pub items: List<AssocReft>,
785}
786
787impl Default for AssocRefinements {
788    fn default() -> Self {
789        Self { items: List::empty() }
790    }
791}
792
793impl AssocRefinements {
794    pub fn get(&self, assoc_id: FluxDefId) -> AssocReft {
795        *self
796            .items
797            .into_iter()
798            .find(|it| it.def_id == assoc_id)
799            .unwrap_or_else(|| bug!("caller should guarantee existence of associated refinement"))
800    }
801
802    pub fn find(&self, name: Symbol) -> Option<AssocReft> {
803        Some(*self.items.into_iter().find(|it| it.name() == name)?)
804    }
805}
806
807#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
808pub enum SortCtor {
809    Set,
810    Map,
811    Adt(AdtSortDef),
812    User(FluxDefId),
813}
814
815newtype_index! {
816    /// [`ParamSort`] is used for polymorphic sorts (`Set`, `Map`, etc.) and [bit-vector size parameters].
817    /// They should occur "bound" under a [`PolyFuncSort`] or an [`AdtSortDef`]. We assume there's a
818    /// single binder and a [`ParamSort`] represents a variable as an index into the list of variables
819    /// bound by that binder, i.e., the representation doesnt't support higher-ranked sorts.
820    ///
821    /// [bit-vector size parameters]: BvSize::Param
822    #[debug_format = "?{}s"]
823    #[encodable]
824    pub struct ParamSort {}
825}
826
827newtype_index! {
828    /// A *sort* *v*variable *id*
829    #[debug_format = "?{}s"]
830    #[encodable]
831    pub struct SortVid {}
832}
833
834impl ena::unify::UnifyKey for SortVid {
835    type Value = SortVarVal;
836
837    #[inline]
838    fn index(&self) -> u32 {
839        self.as_u32()
840    }
841
842    #[inline]
843    fn from_index(u: u32) -> Self {
844        SortVid::from_u32(u)
845    }
846
847    fn tag() -> &'static str {
848        "SortVid"
849    }
850}
851
852bitflags! {
853    /// A *sort constraint* is a set of operations a sort must support.
854    ///
855    /// During sort checking, we accumulate the operations required for each sort variable. As
856    /// unification progresses, these constraints become more specific, i.e, a sort must support
857    /// more operations to satisfy them.
858    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
859    pub struct SortCstr: u16 {
860        /// An empty constraint (any sort satisfies it)
861        const BOT     = 0b0000000000;
862        /// `*`
863        const MUL     = 0b0000000001;
864        /// `/`
865        const DIV     = 0b0000000010;
866        /// `%`
867        const MOD     = 0b0000000100;
868        /// `+`
869        const ADD     = 0b0000001000;
870        /// `-`
871        const SUB     = 0b0000010000;
872        /// `|`
873        const BIT_OR  = 0b0000100000;
874        /// `&`
875        const BIT_AND = 0b0001000000;
876        /// `>>`
877        const BIT_SHL = 0b0010000000;
878        /// `<<`
879        const BIT_SHR = 0b0100000000;
880        /// `^`
881        const BIT_XOR = 0b1000000000;
882
883        /// The set of operations supported by all _numeric_ sorts.
884        const NUMERIC = Self::ADD.bits() | Self::SUB.bits() | Self::MUL.bits() | Self::DIV.bits();
885        /// The set of operations supported by integers.
886        const INT = Self::DIV.bits()
887            | Self::MUL.bits()
888            | Self::MOD.bits()
889            | Self::ADD.bits()
890            | Self::SUB.bits();
891        /// The set of operations supported by reals.
892        const REAL = Self::ADD.bits() | Self::SUB.bits() | Self::MUL.bits() | Self::DIV.bits();
893        /// The set of operations supported by bit vectors.
894        const BITVEC =  Self::DIV.bits()
895            | Self::MUL.bits()
896            | Self::MOD.bits()
897            | Self::ADD.bits()
898            | Self::SUB.bits()
899            | Self::BIT_OR.bits()
900            | Self::BIT_AND.bits()
901            | Self::BIT_SHL.bits()
902            | Self::BIT_SHR.bits()
903            | Self::BIT_XOR.bits();
904        /// The set of operations supported by sets.
905        const SET = Self::SUB.bits() | Self::BIT_OR.bits() | Self::BIT_AND.bits();
906    }
907}
908
909impl SortCstr {
910    /// Returns a constraint that only requires the specified binary operation.
911    pub fn from_bin_op(op: fhir::BinOp) -> Self {
912        match op {
913            fhir::BinOp::Add => Self::ADD,
914            fhir::BinOp::Sub => Self::SUB,
915            fhir::BinOp::Mul => Self::MUL,
916            fhir::BinOp::Div => Self::DIV,
917            fhir::BinOp::Mod => Self::MOD,
918            fhir::BinOp::BitAnd => Self::BIT_AND,
919            fhir::BinOp::BitOr => Self::BIT_OR,
920            fhir::BinOp::BitXor => Self::BIT_XOR,
921            fhir::BinOp::BitShl => Self::BIT_SHL,
922            fhir::BinOp::BitShr => Self::BIT_SHR,
923            _ => bug!("{op:?} not supported as a constraint"),
924        }
925    }
926
927    /// Returns whether a sort satisfies this constraint
928    fn satisfy(self, sort: &Sort) -> bool {
929        match sort {
930            Sort::Int => SortCstr::INT.contains(self),
931            Sort::Real => SortCstr::REAL.contains(self),
932            Sort::BitVec(_) => SortCstr::BITVEC.contains(self),
933            Sort::App(SortCtor::Set, _) => SortCstr::SET.contains(self),
934            _ => self == SortCstr::BOT,
935        }
936    }
937}
938
939/// Unification value for sort variables used during sort checking.
940#[derive(Debug, Clone, PartialEq, Eq)]
941pub enum SortVarVal {
942    /// The variable is not yet solved but the solution must satisfy some constraint.
943    Unsolved(SortCstr),
944    /// The variable has been solved to a sort.
945    Solved(Sort),
946}
947
948impl Default for SortVarVal {
949    fn default() -> Self {
950        SortVarVal::Unsolved(SortCstr::BOT)
951    }
952}
953
954impl SortVarVal {
955    pub fn solved_or(&self, sort: &Sort) -> Sort {
956        match self {
957            SortVarVal::Unsolved(_) => sort.clone(),
958            SortVarVal::Solved(sort) => sort.clone(),
959        }
960    }
961
962    pub fn map_solved(&self, f: impl FnOnce(&Sort) -> Sort) -> SortVarVal {
963        match self {
964            SortVarVal::Unsolved(cstr) => SortVarVal::Unsolved(*cstr),
965            SortVarVal::Solved(sort) => SortVarVal::Solved(f(sort)),
966        }
967    }
968}
969
970impl ena::unify::UnifyValue for SortVarVal {
971    type Error = ();
972
973    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
974        match (value1, value2) {
975            (SortVarVal::Solved(s1), SortVarVal::Solved(s2)) if s1 == s2 => {
976                Ok(SortVarVal::Solved(s1.clone()))
977            }
978            (SortVarVal::Unsolved(a), SortVarVal::Unsolved(b)) => Ok(SortVarVal::Unsolved(*a | *b)),
979            (SortVarVal::Unsolved(v), SortVarVal::Solved(sort))
980            | (SortVarVal::Solved(sort), SortVarVal::Unsolved(v))
981                if v.satisfy(sort) =>
982            {
983                Ok(SortVarVal::Solved(sort.clone()))
984            }
985            _ => Err(()),
986        }
987    }
988}
989
990newtype_index! {
991    /// A *b*it *v*ector *size* *v*variable *id*
992    #[debug_format = "?{}size"]
993    #[encodable]
994    pub struct BvSizeVid {}
995}
996
997impl ena::unify::UnifyKey for BvSizeVid {
998    type Value = Option<BvSize>;
999
1000    #[inline]
1001    fn index(&self) -> u32 {
1002        self.as_u32()
1003    }
1004
1005    #[inline]
1006    fn from_index(u: u32) -> Self {
1007        BvSizeVid::from_u32(u)
1008    }
1009
1010    fn tag() -> &'static str {
1011        "BvSizeVid"
1012    }
1013}
1014
1015impl ena::unify::EqUnifyValue for BvSize {}
1016
1017#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1018pub enum Sort {
1019    Int,
1020    Bool,
1021    Real,
1022    BitVec(BvSize),
1023    Str,
1024    Char,
1025    Loc,
1026    Param(ParamTy),
1027    Tuple(List<Sort>),
1028    Alias(AliasKind, AliasTy),
1029    Func(PolyFuncSort),
1030    App(SortCtor, List<Sort>),
1031    Var(ParamSort),
1032    Infer(SortVid),
1033    Err,
1034}
1035
1036pub enum CastKind {
1037    /// Identity cast, which is erasable (e.g. int -> int, char -> int)
1038    Identity,
1039    /// From bool to int
1040    BoolToInt,
1041    /// Casts to unit index, (e.g. int -> float)
1042    IntoUnit,
1043    /// Uninterpreted casts, only allowed with explicit flag
1044    Uninterpreted,
1045}
1046
1047impl Sort {
1048    pub fn tuple(sorts: impl Into<List<Sort>>) -> Self {
1049        Sort::Tuple(sorts.into())
1050    }
1051
1052    pub fn app(ctor: SortCtor, sorts: List<Sort>) -> Self {
1053        Sort::App(ctor, sorts)
1054    }
1055
1056    pub fn unit() -> Self {
1057        Self::tuple(vec![])
1058    }
1059
1060    #[track_caller]
1061    pub fn expect_func(&self) -> &PolyFuncSort {
1062        if let Sort::Func(sort) = self { sort } else { bug!("expected `Sort::Func`") }
1063    }
1064
1065    pub fn is_loc(&self) -> bool {
1066        matches!(self, Sort::Loc)
1067    }
1068
1069    pub fn is_unit(&self) -> bool {
1070        matches!(self, Sort::Tuple(sorts) if sorts.is_empty())
1071    }
1072
1073    pub fn is_unit_adt(&self) -> Option<DefId> {
1074        if let Sort::App(SortCtor::Adt(sort_def), _) = self
1075            && let Some(variant) = sort_def.opt_struct_variant()
1076            && variant.fields() == 0
1077        {
1078            Some(sort_def.did())
1079        } else {
1080            None
1081        }
1082    }
1083
1084    /// Whether the sort is a function with return sort bool
1085    pub fn is_pred(&self) -> bool {
1086        matches!(self, Sort::Func(fsort) if fsort.skip_binders().output().is_bool())
1087    }
1088
1089    /// Returns `true` if the sort is [`Bool`].
1090    ///
1091    /// [`Bool`]: Sort::Bool
1092    #[must_use]
1093    pub fn is_bool(&self) -> bool {
1094        matches!(self, Self::Bool)
1095    }
1096
1097    pub fn cast_kind(self: &Sort, to: &Sort) -> CastKind {
1098        if self == to
1099            || (matches!(self, Sort::Char | Sort::Int) && matches!(to, Sort::Char | Sort::Int))
1100        {
1101            CastKind::Identity
1102        } else if matches!(self, Sort::Bool) && matches!(to, Sort::Int) {
1103            CastKind::BoolToInt
1104        } else if to.is_unit() {
1105            CastKind::IntoUnit
1106        } else {
1107            CastKind::Uninterpreted
1108        }
1109    }
1110
1111    pub fn walk(&self, mut f: impl FnMut(&Sort, &[FieldProj])) {
1112        fn go(sort: &Sort, f: &mut impl FnMut(&Sort, &[FieldProj]), proj: &mut Vec<FieldProj>) {
1113            match sort {
1114                Sort::Tuple(flds) => {
1115                    for (i, sort) in flds.iter().enumerate() {
1116                        proj.push(FieldProj::Tuple { arity: flds.len(), field: i as u32 });
1117                        go(sort, f, proj);
1118                        proj.pop();
1119                    }
1120                }
1121                Sort::App(SortCtor::Adt(sort_def), args) if sort_def.is_struct() => {
1122                    let field_sorts = sort_def.struct_variant().field_sorts(args);
1123                    for (i, sort) in field_sorts.iter().enumerate() {
1124                        proj.push(FieldProj::Adt { def_id: sort_def.did(), field: i as u32 });
1125                        go(sort, f, proj);
1126                        proj.pop();
1127                    }
1128                }
1129                _ => {
1130                    f(sort, proj);
1131                }
1132            }
1133        }
1134        go(self, &mut f, &mut vec![]);
1135    }
1136}
1137
1138/// The size of a [bit-vector]
1139///
1140/// [bit-vector]: Sort::BitVec
1141#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1142pub enum BvSize {
1143    /// A fixed size
1144    Fixed(u32),
1145    /// A size that has been parameterized, e.g., bound under a [`PolyFuncSort`]
1146    Param(ParamSort),
1147    /// A size that needs to be inferred. Used during sort checking to instantiate bit-vector
1148    /// sizes at call-sites.
1149    Infer(BvSizeVid),
1150}
1151
1152impl rustc_errors::IntoDiagArg for Sort {
1153    fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1154        rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1155    }
1156}
1157
1158impl rustc_errors::IntoDiagArg for FuncSort {
1159    fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1160        rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1161    }
1162}
1163
1164#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
1165pub struct FuncSort {
1166    pub inputs_and_output: List<Sort>,
1167}
1168
1169impl FuncSort {
1170    pub fn new(mut inputs: Vec<Sort>, output: Sort) -> Self {
1171        inputs.push(output);
1172        FuncSort { inputs_and_output: List::from_vec(inputs) }
1173    }
1174
1175    pub fn inputs(&self) -> &[Sort] {
1176        &self.inputs_and_output[0..self.inputs_and_output.len() - 1]
1177    }
1178
1179    pub fn output(&self) -> &Sort {
1180        &self.inputs_and_output[self.inputs_and_output.len() - 1]
1181    }
1182
1183    pub fn to_poly(&self) -> PolyFuncSort {
1184        PolyFuncSort::new(List::empty(), self.clone())
1185    }
1186}
1187
1188/// See [`PolyFuncSort`]
1189#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
1190pub enum SortParamKind {
1191    Sort,
1192    BvSize,
1193}
1194
1195/// A polymorphic function sort parametric over [sorts] or [bit-vector sizes].
1196///
1197/// Parameterizing over bit-vector sizes is a bit of a stretch, because smtlib doesn't support full
1198/// parametric reasoning over them. As long as we used functions parameterized over a size monomorphically
1199/// we should be fine. Right now, we can guarantee this, because size parameters are not exposed in
1200/// the surface syntax and they are only used for predefined (interpreted) theory functions.
1201///
1202/// [sorts]: Sort
1203/// [bit-vector sizes]: BvSize::Param
1204#[derive(Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
1205pub struct PolyFuncSort {
1206    /// The list of parameters including sorts and bit vector sizes
1207    params: List<SortParamKind>,
1208    fsort: FuncSort,
1209}
1210
1211impl PolyFuncSort {
1212    pub fn new(params: List<SortParamKind>, fsort: FuncSort) -> Self {
1213        PolyFuncSort { params, fsort }
1214    }
1215
1216    pub fn skip_binders(&self) -> FuncSort {
1217        self.fsort.clone()
1218    }
1219
1220    pub fn instantiate_identity(&self) -> FuncSort {
1221        self.fsort.clone()
1222    }
1223
1224    pub fn expect_mono(&self) -> FuncSort {
1225        assert!(self.params.is_empty());
1226        self.fsort.clone()
1227    }
1228
1229    pub fn params(&self) -> impl ExactSizeIterator<Item = SortParamKind> + '_ {
1230        self.params.iter().copied()
1231    }
1232
1233    pub fn instantiate(&self, args: &[SortArg]) -> FuncSort {
1234        self.fsort.fold_with(&mut SortSubst::new(args))
1235    }
1236}
1237
1238/// An argument for a generic parameter in a [`Sort`] which can be either a generic sort or a
1239/// generic bit-vector size.
1240#[derive(
1241    Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
1242)]
1243pub enum SortArg {
1244    Sort(Sort),
1245    BvSize(BvSize),
1246}
1247
1248#[derive(Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1249pub enum ConstantInfo {
1250    /// An uninterpreted constant
1251    Uninterpreted,
1252    /// A non-integral constant whose value is specified by the user
1253    Interpreted(Expr, Sort),
1254}
1255
1256#[derive(Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1257pub struct AdtDef(Interned<AdtDefData>);
1258
1259#[derive(Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1260pub struct AdtDefData {
1261    invariants: Vec<Invariant>,
1262    sort_def: AdtSortDef,
1263    opaque: bool,
1264    rustc: ty::AdtDef,
1265}
1266
1267/// Option-like enum to explicitly mark that we don't have information about an ADT because it was
1268/// annotated with `#[flux::opaque]`. Note that only structs can be marked as opaque.
1269#[derive(Clone, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
1270pub enum Opaqueness<T> {
1271    Opaque,
1272    Transparent(T),
1273}
1274
1275impl<T> Opaqueness<T> {
1276    pub fn map<S>(self, f: impl FnOnce(T) -> S) -> Opaqueness<S> {
1277        match self {
1278            Opaqueness::Opaque => Opaqueness::Opaque,
1279            Opaqueness::Transparent(value) => Opaqueness::Transparent(f(value)),
1280        }
1281    }
1282
1283    pub fn as_ref(&self) -> Opaqueness<&T> {
1284        match self {
1285            Opaqueness::Opaque => Opaqueness::Opaque,
1286            Opaqueness::Transparent(value) => Opaqueness::Transparent(value),
1287        }
1288    }
1289
1290    pub fn as_deref(&self) -> Opaqueness<&T::Target>
1291    where
1292        T: std::ops::Deref,
1293    {
1294        match self {
1295            Opaqueness::Opaque => Opaqueness::Opaque,
1296            Opaqueness::Transparent(value) => Opaqueness::Transparent(value.deref()),
1297        }
1298    }
1299
1300    pub fn ok_or_else<E>(self, err: impl FnOnce() -> E) -> Result<T, E> {
1301        match self {
1302            Opaqueness::Transparent(v) => Ok(v),
1303            Opaqueness::Opaque => Err(err()),
1304        }
1305    }
1306
1307    #[track_caller]
1308    pub fn expect(self, msg: &str) -> T {
1309        match self {
1310            Opaqueness::Transparent(val) => val,
1311            Opaqueness::Opaque => bug!("{}", msg),
1312        }
1313    }
1314
1315    pub fn ok_or_query_err(self, struct_id: DefId) -> Result<T, QueryErr> {
1316        self.ok_or_else(|| QueryErr::OpaqueStruct { struct_id })
1317    }
1318}
1319
1320impl<T, E> Opaqueness<Result<T, E>> {
1321    pub fn transpose(self) -> Result<Opaqueness<T>, E> {
1322        match self {
1323            Opaqueness::Transparent(Ok(x)) => Ok(Opaqueness::Transparent(x)),
1324            Opaqueness::Transparent(Err(e)) => Err(e),
1325            Opaqueness::Opaque => Ok(Opaqueness::Opaque),
1326        }
1327    }
1328}
1329
1330pub static INT_TYS: [IntTy; 6] =
1331    [IntTy::Isize, IntTy::I8, IntTy::I16, IntTy::I32, IntTy::I64, IntTy::I128];
1332pub static UINT_TYS: [UintTy; 6] =
1333    [UintTy::Usize, UintTy::U8, UintTy::U16, UintTy::U32, UintTy::U64, UintTy::U128];
1334
1335#[derive(
1336    Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable,
1337)]
1338pub struct Invariant {
1339    // This predicate may have sort variables, but we don't explicitly mark it like in `PolyFuncSort`.
1340    // See comment on `apply` for details.
1341    pred: Binder<Expr>,
1342}
1343
1344impl Invariant {
1345    pub fn new(pred: Binder<Expr>) -> Self {
1346        Self { pred }
1347    }
1348
1349    pub fn apply(&self, idx: &Expr) -> Expr {
1350        // The predicate may have sort variables but we don't explicitly instantiate them. This
1351        // works because within an expression, sort variables can only appear inside the sort
1352        // annotation for a lambda and invariants cannot have lambdas. It remains to instantiate
1353        // variables in the sort of the binder itself, but since we are removing it, we can avoid
1354        // the explicit instantiation. Ultimately, this works because the expression we generate in
1355        // fixpoint doesn't need sort annotations (sorts are re-inferred).
1356        self.pred.replace_bound_reft(idx)
1357    }
1358}
1359
1360pub type PolyVariants = List<Binder<VariantSig>>;
1361pub type PolyVariant = Binder<VariantSig>;
1362
1363#[derive(Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1364pub struct VariantSig {
1365    pub adt_def: AdtDef,
1366    pub args: GenericArgs,
1367    pub fields: List<Ty>,
1368    pub idx: Expr,
1369    pub requires: List<Expr>,
1370}
1371
1372pub type PolyFnSig = Binder<FnSig>;
1373
1374#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
1375pub struct FnSig {
1376    pub safety: Safety,
1377    pub abi: rustc_abi::ExternAbi,
1378    pub requires: List<Expr>,
1379    pub inputs: List<Ty>,
1380    pub output: Binder<FnOutput>,
1381}
1382
1383#[derive(
1384    Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
1385)]
1386pub struct FnOutput {
1387    pub ret: Ty,
1388    pub ensures: List<Ensures>,
1389}
1390
1391#[derive(Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1392pub enum Ensures {
1393    Type(Path, Ty),
1394    Pred(Expr),
1395}
1396
1397#[derive(Debug, TypeVisitable, TypeFoldable)]
1398pub struct Qualifier {
1399    pub def_id: FluxLocalDefId,
1400    pub body: Binder<Expr>,
1401    pub global: bool,
1402}
1403
1404/// A `PrimOpProp` is a single property for a primitive operation which
1405/// can be conjoined to get the definition of the [`PrimRel`] for that
1406/// primitive operation.
1407#[derive(Debug, TypeVisitable, TypeFoldable)]
1408pub struct PrimOpProp {
1409    pub def_id: FluxLocalDefId,
1410    pub op: BinOp,
1411    pub body: Binder<Expr>,
1412}
1413
1414#[derive(Debug, TypeVisitable, TypeFoldable)]
1415pub struct PrimRel {
1416    pub body: Binder<Expr>,
1417}
1418
1419pub type TyCtor = Binder<Ty>;
1420
1421impl TyCtor {
1422    pub fn to_ty(&self) -> Ty {
1423        match &self.vars()[..] {
1424            [] => {
1425                return self.skip_binder_ref().shift_out_escaping(1);
1426            }
1427            [BoundVariableKind::Refine(sort, ..)] => {
1428                if sort.is_unit() {
1429                    return self.replace_bound_reft(&Expr::unit());
1430                }
1431                if let Some(def_id) = sort.is_unit_adt() {
1432                    return self.replace_bound_reft(&Expr::unit_struct(def_id));
1433                }
1434            }
1435            _ => {}
1436        }
1437        Ty::exists(self.clone())
1438    }
1439}
1440
1441#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1442pub struct Ty(Interned<TyKind>);
1443
1444impl Ty {
1445    pub fn kind(&self) -> &TyKind {
1446        &self.0
1447    }
1448
1449    /// Dummy type used for the `Self` of a `TraitRef` created when converting a trait object, and
1450    /// which gets removed in `ExistentialTraitRef`. This type must not appear anywhere in other
1451    /// converted types and must be a valid `rustc` type (i.e., we must be able to call `to_rustc`
1452    /// on it). `TyKind::Infer(TyVid(0))` does the job, with the caveat that we must skip 0 when
1453    /// generating `TyKind::Infer` for "type holes".
1454    pub fn trait_object_dummy_self() -> Ty {
1455        Ty::infer(TyVid::from_u32(0))
1456    }
1457
1458    pub fn dynamic(preds: impl Into<List<Binder<ExistentialPredicate>>>, region: Region) -> Ty {
1459        BaseTy::Dynamic(preds.into(), region).to_ty()
1460    }
1461
1462    pub fn strg_ref(re: Region, path: Path, ty: Ty) -> Ty {
1463        TyKind::StrgRef(re, path, ty).intern()
1464    }
1465
1466    pub fn ptr(pk: impl Into<PtrKind>, path: impl Into<Path>) -> Ty {
1467        TyKind::Ptr(pk.into(), path.into()).intern()
1468    }
1469
1470    pub fn constr(p: impl Into<Expr>, ty: Ty) -> Ty {
1471        TyKind::Constr(p.into(), ty).intern()
1472    }
1473
1474    pub fn uninit() -> Ty {
1475        TyKind::Uninit.intern()
1476    }
1477
1478    pub fn indexed(bty: BaseTy, idx: impl Into<Expr>) -> Ty {
1479        TyKind::Indexed(bty, idx.into()).intern()
1480    }
1481
1482    pub fn exists(ty: Binder<Ty>) -> Ty {
1483        TyKind::Exists(ty).intern()
1484    }
1485
1486    pub fn exists_with_constr(bty: BaseTy, pred: Expr) -> Ty {
1487        let sort = bty.sort();
1488        let ty = Ty::indexed(bty, Expr::nu());
1489        Ty::exists(Binder::bind_with_sort(Ty::constr(pred, ty), sort))
1490    }
1491
1492    pub fn discr(adt_def: AdtDef, place: Place) -> Ty {
1493        TyKind::Discr(adt_def, place).intern()
1494    }
1495
1496    pub fn unit() -> Ty {
1497        Ty::tuple(vec![])
1498    }
1499
1500    pub fn bool() -> Ty {
1501        BaseTy::Bool.to_ty()
1502    }
1503
1504    pub fn int(int_ty: IntTy) -> Ty {
1505        BaseTy::Int(int_ty).to_ty()
1506    }
1507
1508    pub fn uint(uint_ty: UintTy) -> Ty {
1509        BaseTy::Uint(uint_ty).to_ty()
1510    }
1511
1512    pub fn param(param_ty: ParamTy) -> Ty {
1513        TyKind::Param(param_ty).intern()
1514    }
1515
1516    pub fn downcast(
1517        adt: AdtDef,
1518        args: GenericArgs,
1519        ty: Ty,
1520        variant: VariantIdx,
1521        fields: List<Ty>,
1522    ) -> Ty {
1523        TyKind::Downcast(adt, args, ty, variant, fields).intern()
1524    }
1525
1526    pub fn blocked(ty: Ty) -> Ty {
1527        TyKind::Blocked(ty).intern()
1528    }
1529
1530    pub fn str() -> Ty {
1531        BaseTy::Str.to_ty()
1532    }
1533
1534    pub fn char() -> Ty {
1535        BaseTy::Char.to_ty()
1536    }
1537
1538    pub fn float(float_ty: FloatTy) -> Ty {
1539        BaseTy::Float(float_ty).to_ty()
1540    }
1541
1542    pub fn mk_ref(region: Region, ty: Ty, mutbl: Mutability) -> Ty {
1543        BaseTy::Ref(region, ty, mutbl).to_ty()
1544    }
1545
1546    pub fn mk_slice(ty: Ty) -> Ty {
1547        BaseTy::Slice(ty).to_ty()
1548    }
1549
1550    pub fn mk_box(genv: GlobalEnv, deref_ty: Ty, alloc_ty: Ty) -> QueryResult<Ty> {
1551        let def_id = genv.tcx().require_lang_item(LangItem::OwnedBox, DUMMY_SP);
1552        let adt_def = genv.adt_def(def_id)?;
1553
1554        let args = List::from_arr([GenericArg::Ty(deref_ty), GenericArg::Ty(alloc_ty)]);
1555
1556        let bty = BaseTy::adt(adt_def, args);
1557        Ok(Ty::indexed(bty, Expr::unit_struct(def_id)))
1558    }
1559
1560    pub fn mk_box_with_default_alloc(genv: GlobalEnv, deref_ty: Ty) -> QueryResult<Ty> {
1561        let def_id = genv.tcx().require_lang_item(LangItem::OwnedBox, DUMMY_SP);
1562
1563        let generics = genv.generics_of(def_id)?;
1564        let alloc_ty = genv
1565            .lower_type_of(generics.own_params[1].def_id)?
1566            .skip_binder()
1567            .refine(&Refiner::default_for_item(genv, def_id)?)?;
1568
1569        Ty::mk_box(genv, deref_ty, alloc_ty)
1570    }
1571
1572    pub fn tuple(tys: impl Into<List<Ty>>) -> Ty {
1573        BaseTy::Tuple(tys.into()).to_ty()
1574    }
1575
1576    pub fn array(ty: Ty, c: Const) -> Ty {
1577        BaseTy::Array(ty, c).to_ty()
1578    }
1579
1580    pub fn closure(
1581        did: DefId,
1582        tys: impl Into<List<Ty>>,
1583        args: &flux_rustc_bridge::ty::GenericArgs,
1584    ) -> Ty {
1585        BaseTy::Closure(did, tys.into(), args.clone()).to_ty()
1586    }
1587
1588    pub fn coroutine(did: DefId, resume_ty: Ty, upvar_tys: List<Ty>) -> Ty {
1589        BaseTy::Coroutine(did, resume_ty, upvar_tys).to_ty()
1590    }
1591
1592    pub fn never() -> Ty {
1593        BaseTy::Never.to_ty()
1594    }
1595
1596    pub fn infer(vid: TyVid) -> Ty {
1597        TyKind::Infer(vid).intern()
1598    }
1599
1600    pub fn unconstr(&self) -> (Ty, Expr) {
1601        fn go(this: &Ty, preds: &mut Vec<Expr>) -> Ty {
1602            if let TyKind::Constr(pred, ty) = this.kind() {
1603                preds.push(pred.clone());
1604                go(ty, preds)
1605            } else {
1606                this.clone()
1607            }
1608        }
1609        let mut preds = vec![];
1610        (go(self, &mut preds), Expr::and_from_iter(preds))
1611    }
1612
1613    pub fn unblocked(&self) -> Ty {
1614        match self.kind() {
1615            TyKind::Blocked(ty) => ty.clone(),
1616            _ => self.clone(),
1617        }
1618    }
1619
1620    /// Whether the type is an `int` or a `uint`
1621    pub fn is_integral(&self) -> bool {
1622        self.as_bty_skipping_existentials()
1623            .map(BaseTy::is_integral)
1624            .unwrap_or_default()
1625    }
1626
1627    /// Whether the type is a `bool`
1628    pub fn is_bool(&self) -> bool {
1629        self.as_bty_skipping_existentials()
1630            .map(BaseTy::is_bool)
1631            .unwrap_or_default()
1632    }
1633
1634    /// Whether the type is a `char`
1635    pub fn is_char(&self) -> bool {
1636        self.as_bty_skipping_existentials()
1637            .map(BaseTy::is_char)
1638            .unwrap_or_default()
1639    }
1640
1641    pub fn is_uninit(&self) -> bool {
1642        matches!(self.kind(), TyKind::Uninit)
1643    }
1644
1645    pub fn is_box(&self) -> bool {
1646        self.as_bty_skipping_existentials()
1647            .map(BaseTy::is_box)
1648            .unwrap_or_default()
1649    }
1650
1651    pub fn is_struct(&self) -> bool {
1652        self.as_bty_skipping_existentials()
1653            .map(BaseTy::is_struct)
1654            .unwrap_or_default()
1655    }
1656
1657    pub fn is_array(&self) -> bool {
1658        self.as_bty_skipping_existentials()
1659            .map(BaseTy::is_array)
1660            .unwrap_or_default()
1661    }
1662
1663    pub fn is_slice(&self) -> bool {
1664        self.as_bty_skipping_existentials()
1665            .map(BaseTy::is_slice)
1666            .unwrap_or_default()
1667    }
1668
1669    pub fn as_bty_skipping_existentials(&self) -> Option<&BaseTy> {
1670        match self.kind() {
1671            TyKind::Indexed(bty, _) => Some(bty),
1672            TyKind::Exists(ty) => Some(ty.skip_binder_ref().as_bty_skipping_existentials()?),
1673            TyKind::Constr(_, ty) => ty.as_bty_skipping_existentials(),
1674            _ => None,
1675        }
1676    }
1677
1678    #[track_caller]
1679    pub fn expect_discr(&self) -> (&AdtDef, &Place) {
1680        if let TyKind::Discr(adt_def, place) = self.kind() {
1681            (adt_def, place)
1682        } else {
1683            tracked_span_bug!("expected discr")
1684        }
1685    }
1686
1687    #[track_caller]
1688    pub fn expect_adt(&self) -> (&AdtDef, &[GenericArg], &Expr) {
1689        if let TyKind::Indexed(BaseTy::Adt(adt_def, args), idx) = self.kind() {
1690            (adt_def, args, idx)
1691        } else {
1692            tracked_span_bug!("expected adt `{self:?}`")
1693        }
1694    }
1695
1696    #[track_caller]
1697    pub fn expect_tuple(&self) -> &[Ty] {
1698        if let TyKind::Indexed(BaseTy::Tuple(tys), _) = self.kind() {
1699            tys
1700        } else {
1701            tracked_span_bug!("expected tuple found `{self:?}` (kind: `{:?}`)", self.kind())
1702        }
1703    }
1704
1705    pub fn simplify_type(&self) -> Option<SimplifiedType> {
1706        self.as_bty_skipping_existentials()
1707            .and_then(BaseTy::simplify_type)
1708    }
1709}
1710
1711impl<'tcx> ToRustc<'tcx> for Ty {
1712    type T = rustc_middle::ty::Ty<'tcx>;
1713
1714    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
1715        match self.kind() {
1716            TyKind::Indexed(bty, _) => bty.to_rustc(tcx),
1717            TyKind::Exists(ty) => ty.skip_binder_ref().to_rustc(tcx),
1718            TyKind::Constr(_, ty) => ty.to_rustc(tcx),
1719            TyKind::Param(pty) => pty.to_ty(tcx),
1720            TyKind::StrgRef(re, _, ty) => {
1721                rustc_middle::ty::Ty::new_ref(
1722                    tcx,
1723                    re.to_rustc(tcx),
1724                    ty.to_rustc(tcx),
1725                    Mutability::Mut,
1726                )
1727            }
1728            TyKind::Infer(vid) => rustc_middle::ty::Ty::new_var(tcx, *vid),
1729            TyKind::Uninit
1730            | TyKind::Ptr(_, _)
1731            | TyKind::Discr(..)
1732            | TyKind::Downcast(..)
1733            | TyKind::Blocked(_) => bug!("TODO: to_rustc for `{self:?}`"),
1734        }
1735    }
1736}
1737
1738#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)]
1739pub enum TyKind {
1740    Indexed(BaseTy, Expr),
1741    Exists(Binder<Ty>),
1742    Constr(Expr, Ty),
1743    Uninit,
1744    StrgRef(Region, Path, Ty),
1745    Ptr(PtrKind, Path),
1746    /// This is a bit of a hack. We use this type internally to represent the result of
1747    /// [`Rvalue::Discriminant`] in a way that we can recover the necessary control information
1748    /// when checking a [`match`]. The hack is that we assume the dicriminant remains the same from
1749    /// the creation of this type until we use it in a [`match`].
1750    ///
1751    ///
1752    /// [`Rvalue::Discriminant`]: flux_rustc_bridge::mir::Rvalue::Discriminant
1753    /// [`match`]: flux_rustc_bridge::mir::TerminatorKind::SwitchInt
1754    Discr(AdtDef, Place),
1755    Param(ParamTy),
1756    Downcast(AdtDef, GenericArgs, Ty, VariantIdx, List<Ty>),
1757    Blocked(Ty),
1758    /// A type that needs to be inferred by matching the signature against a rust signature.
1759    /// [`TyKind::Infer`] appear as an intermediate step during `conv` and should not be present in
1760    /// the final signature.
1761    Infer(TyVid),
1762}
1763
1764#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1765pub enum PtrKind {
1766    Mut(Region),
1767    Box,
1768}
1769
1770#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1771pub enum BaseTy {
1772    Int(IntTy),
1773    Uint(UintTy),
1774    Bool,
1775    Str,
1776    Char,
1777    Slice(Ty),
1778    Adt(AdtDef, GenericArgs),
1779    Float(FloatTy),
1780    RawPtr(Ty, Mutability),
1781    RawPtrMetadata(Ty),
1782    Ref(Region, Ty, Mutability),
1783    FnPtr(PolyFnSig),
1784    FnDef(DefId, GenericArgs),
1785    Tuple(List<Ty>),
1786    Alias(AliasKind, AliasTy),
1787    Array(Ty, Const),
1788    Never,
1789    Closure(DefId, /* upvar_tys */ List<Ty>, flux_rustc_bridge::ty::GenericArgs),
1790    Coroutine(DefId, /*resume_ty: */ Ty, /* upvar_tys: */ List<Ty>),
1791    Dynamic(List<Binder<ExistentialPredicate>>, Region),
1792    Param(ParamTy),
1793    Infer(TyVid),
1794    Foreign(DefId),
1795}
1796
1797impl BaseTy {
1798    pub fn opaque(alias_ty: AliasTy) -> BaseTy {
1799        BaseTy::Alias(AliasKind::Opaque, alias_ty)
1800    }
1801
1802    pub fn projection(alias_ty: AliasTy) -> BaseTy {
1803        BaseTy::Alias(AliasKind::Projection, alias_ty)
1804    }
1805
1806    pub fn adt(adt_def: AdtDef, args: GenericArgs) -> BaseTy {
1807        BaseTy::Adt(adt_def, args)
1808    }
1809
1810    pub fn fn_def(def_id: DefId, args: impl Into<GenericArgs>) -> BaseTy {
1811        BaseTy::FnDef(def_id, args.into())
1812    }
1813
1814    pub fn from_primitive_str(s: &str) -> Option<BaseTy> {
1815        match s {
1816            "i8" => Some(BaseTy::Int(IntTy::I8)),
1817            "i16" => Some(BaseTy::Int(IntTy::I16)),
1818            "i32" => Some(BaseTy::Int(IntTy::I32)),
1819            "i64" => Some(BaseTy::Int(IntTy::I64)),
1820            "i128" => Some(BaseTy::Int(IntTy::I128)),
1821            "u8" => Some(BaseTy::Uint(UintTy::U8)),
1822            "u16" => Some(BaseTy::Uint(UintTy::U16)),
1823            "u32" => Some(BaseTy::Uint(UintTy::U32)),
1824            "u64" => Some(BaseTy::Uint(UintTy::U64)),
1825            "u128" => Some(BaseTy::Uint(UintTy::U128)),
1826            "f16" => Some(BaseTy::Float(FloatTy::F16)),
1827            "f32" => Some(BaseTy::Float(FloatTy::F32)),
1828            "f64" => Some(BaseTy::Float(FloatTy::F64)),
1829            "f128" => Some(BaseTy::Float(FloatTy::F128)),
1830            "isize" => Some(BaseTy::Int(IntTy::Isize)),
1831            "usize" => Some(BaseTy::Uint(UintTy::Usize)),
1832            "bool" => Some(BaseTy::Bool),
1833            "char" => Some(BaseTy::Char),
1834            "str" => Some(BaseTy::Str),
1835            _ => None,
1836        }
1837    }
1838
1839    /// If `self` is a primitive, return its [`Symbol`].
1840    pub fn primitive_symbol(&self) -> Option<Symbol> {
1841        match self {
1842            BaseTy::Bool => Some(sym::bool),
1843            BaseTy::Char => Some(sym::char),
1844            BaseTy::Float(f) => {
1845                match f {
1846                    FloatTy::F16 => Some(sym::f16),
1847                    FloatTy::F32 => Some(sym::f32),
1848                    FloatTy::F64 => Some(sym::f64),
1849                    FloatTy::F128 => Some(sym::f128),
1850                }
1851            }
1852            BaseTy::Int(f) => {
1853                match f {
1854                    IntTy::Isize => Some(sym::isize),
1855                    IntTy::I8 => Some(sym::i8),
1856                    IntTy::I16 => Some(sym::i16),
1857                    IntTy::I32 => Some(sym::i32),
1858                    IntTy::I64 => Some(sym::i64),
1859                    IntTy::I128 => Some(sym::i128),
1860                }
1861            }
1862            BaseTy::Uint(f) => {
1863                match f {
1864                    UintTy::Usize => Some(sym::usize),
1865                    UintTy::U8 => Some(sym::u8),
1866                    UintTy::U16 => Some(sym::u16),
1867                    UintTy::U32 => Some(sym::u32),
1868                    UintTy::U64 => Some(sym::u64),
1869                    UintTy::U128 => Some(sym::u128),
1870                }
1871            }
1872            BaseTy::Str => Some(sym::str),
1873            _ => None,
1874        }
1875    }
1876
1877    pub fn is_integral(&self) -> bool {
1878        matches!(self, BaseTy::Int(_) | BaseTy::Uint(_))
1879    }
1880
1881    pub fn is_signed(&self) -> bool {
1882        matches!(self, BaseTy::Int(_))
1883    }
1884
1885    pub fn is_unsigned(&self) -> bool {
1886        matches!(self, BaseTy::Uint(_))
1887    }
1888
1889    pub fn is_float(&self) -> bool {
1890        matches!(self, BaseTy::Float(_))
1891    }
1892
1893    pub fn is_bool(&self) -> bool {
1894        matches!(self, BaseTy::Bool)
1895    }
1896
1897    fn is_struct(&self) -> bool {
1898        matches!(self, BaseTy::Adt(adt_def, _) if adt_def.is_struct())
1899    }
1900
1901    fn is_array(&self) -> bool {
1902        matches!(self, BaseTy::Array(..))
1903    }
1904
1905    fn is_slice(&self) -> bool {
1906        matches!(self, BaseTy::Slice(..))
1907    }
1908
1909    pub fn is_box(&self) -> bool {
1910        matches!(self, BaseTy::Adt(adt_def, _) if adt_def.is_box())
1911    }
1912
1913    pub fn is_char(&self) -> bool {
1914        matches!(self, BaseTy::Char)
1915    }
1916
1917    pub fn is_str(&self) -> bool {
1918        matches!(self, BaseTy::Str)
1919    }
1920
1921    pub fn invariants(
1922        &self,
1923        tcx: TyCtxt,
1924        overflow_mode: OverflowMode,
1925    ) -> impl Iterator<Item = Invariant> {
1926        let (invariants, args) = match self {
1927            BaseTy::Adt(adt_def, args) => (adt_def.invariants().skip_binder(), &args[..]),
1928            BaseTy::Uint(uint_ty) => (uint_invariants(*uint_ty, overflow_mode), &[][..]),
1929            BaseTy::Int(int_ty) => (int_invariants(*int_ty, overflow_mode), &[][..]),
1930            BaseTy::Char => (char_invariants(), &[][..]),
1931            BaseTy::Slice(_) => (slice_invariants(overflow_mode), &[][..]),
1932            _ => (&[][..], &[][..]),
1933        };
1934        invariants
1935            .iter()
1936            .map(move |inv| EarlyBinder(inv).instantiate_ref(tcx, args, &[]))
1937    }
1938
1939    pub fn to_ty(&self) -> Ty {
1940        let sort = self.sort();
1941        if sort.is_unit() {
1942            Ty::indexed(self.clone(), Expr::unit())
1943        } else {
1944            Ty::exists(Binder::bind_with_sort(
1945                Ty::indexed(self.shift_in_escaping(1), Expr::nu()),
1946                sort,
1947            ))
1948        }
1949    }
1950
1951    pub fn to_subset_ty_ctor(&self) -> SubsetTyCtor {
1952        let sort = self.sort();
1953        Binder::bind_with_sort(SubsetTy::trivial(self.clone(), Expr::nu()), sort)
1954    }
1955
1956    #[track_caller]
1957    pub fn expect_adt(&self) -> (&AdtDef, &[GenericArg]) {
1958        if let BaseTy::Adt(adt_def, args) = self {
1959            (adt_def, args)
1960        } else {
1961            tracked_span_bug!("expected adt `{self:?}`")
1962        }
1963    }
1964
1965    /// A type is an *atom* if it is "self-delimiting", i.e., it has a clear boundary
1966    /// when printed. This is used to avoid unnecessary parenthesis when pretty printing.
1967    pub fn is_atom(&self) -> bool {
1968        // (nilehmann) I'm not sure about this list, please adjust if you get any odd behavior
1969        matches!(
1970            self,
1971            BaseTy::Int(_)
1972                | BaseTy::Uint(_)
1973                | BaseTy::Slice(_)
1974                | BaseTy::Bool
1975                | BaseTy::Char
1976                | BaseTy::Str
1977                | BaseTy::Adt(..)
1978                | BaseTy::Tuple(..)
1979                | BaseTy::Param(_)
1980                | BaseTy::Array(..)
1981                | BaseTy::Never
1982                | BaseTy::Closure(..)
1983                | BaseTy::Coroutine(..)
1984                // opaque alias are atoms the way we print them now, but they won't
1985                // be if we print them as `impl Trait`
1986                | BaseTy::Alias(..)
1987        )
1988    }
1989
1990    /// Similar to [`rustc_infer::infer::canonical::ir::fast_reject::simplify_type`].
1991    ///
1992    /// This implementation is currently incomplete, so it should only be used in contexts
1993    /// where completeness is not required. Currently, it's used to find incoherent
1994    /// implementations when resolving associated constants. In this context, incompleteness
1995    /// is acceptable since the worst case outcome is simply failing to resolve a type-relative
1996    /// constant.
1997    fn simplify_type(&self) -> Option<SimplifiedType> {
1998        match self {
1999            BaseTy::Bool => Some(SimplifiedType::Bool),
2000            BaseTy::Char => Some(SimplifiedType::Char),
2001            BaseTy::Int(int_type) => Some(SimplifiedType::Int(*int_type)),
2002            BaseTy::Uint(uint_type) => Some(SimplifiedType::Uint(*uint_type)),
2003            BaseTy::Float(float_type) => Some(SimplifiedType::Float(*float_type)),
2004            BaseTy::Adt(def, _) => Some(SimplifiedType::Adt(def.did())),
2005            BaseTy::Str => Some(SimplifiedType::Str),
2006            BaseTy::Array(..) => Some(SimplifiedType::Array),
2007            BaseTy::Slice(..) => Some(SimplifiedType::Slice),
2008            BaseTy::RawPtr(_, mutbl) => Some(SimplifiedType::Ptr(*mutbl)),
2009            BaseTy::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(*mutbl)),
2010            BaseTy::FnDef(def_id, _) | BaseTy::Closure(def_id, ..) => {
2011                Some(SimplifiedType::Closure(*def_id))
2012            }
2013            BaseTy::Coroutine(def_id, ..) => Some(SimplifiedType::Coroutine(*def_id)),
2014            BaseTy::Never => Some(SimplifiedType::Never),
2015            BaseTy::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())),
2016            BaseTy::FnPtr(poly_fn_sig) => {
2017                Some(SimplifiedType::Function(poly_fn_sig.skip_binder_ref().inputs().len()))
2018            }
2019            BaseTy::Foreign(def_id) => Some(SimplifiedType::Foreign(*def_id)),
2020            BaseTy::RawPtrMetadata(_)
2021            | BaseTy::Alias(..)
2022            | BaseTy::Param(_)
2023            | BaseTy::Dynamic(..)
2024            | BaseTy::Infer(_) => None,
2025        }
2026    }
2027}
2028
2029impl<'tcx> ToRustc<'tcx> for BaseTy {
2030    type T = rustc_middle::ty::Ty<'tcx>;
2031
2032    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2033        use rustc_middle::ty;
2034        match self {
2035            BaseTy::Int(i) => ty::Ty::new_int(tcx, *i),
2036            BaseTy::Uint(i) => ty::Ty::new_uint(tcx, *i),
2037            BaseTy::Param(pty) => pty.to_ty(tcx),
2038            BaseTy::Slice(ty) => ty::Ty::new_slice(tcx, ty.to_rustc(tcx)),
2039            BaseTy::Bool => tcx.types.bool,
2040            BaseTy::Char => tcx.types.char,
2041            BaseTy::Str => tcx.types.str_,
2042            BaseTy::Adt(adt_def, args) => {
2043                let did = adt_def.did();
2044                let adt_def = tcx.adt_def(did);
2045                let args = args.to_rustc(tcx);
2046                ty::Ty::new_adt(tcx, adt_def, args)
2047            }
2048            BaseTy::FnDef(def_id, args) => {
2049                let args = args.to_rustc(tcx);
2050                ty::Ty::new_fn_def(tcx, *def_id, args)
2051            }
2052            BaseTy::Float(f) => ty::Ty::new_float(tcx, *f),
2053            BaseTy::RawPtr(ty, mutbl) => ty::Ty::new_ptr(tcx, ty.to_rustc(tcx), *mutbl),
2054            BaseTy::Ref(re, ty, mutbl) => {
2055                ty::Ty::new_ref(tcx, re.to_rustc(tcx), ty.to_rustc(tcx), *mutbl)
2056            }
2057            BaseTy::FnPtr(poly_sig) => ty::Ty::new_fn_ptr(tcx, poly_sig.to_rustc(tcx)),
2058            BaseTy::Tuple(tys) => {
2059                let ts = tys.iter().map(|ty| ty.to_rustc(tcx)).collect_vec();
2060                ty::Ty::new_tup(tcx, &ts)
2061            }
2062            BaseTy::Alias(kind, alias_ty) => {
2063                ty::Ty::new_alias(tcx, kind.to_rustc(tcx), alias_ty.to_rustc(tcx))
2064            }
2065            BaseTy::Array(ty, n) => {
2066                let ty = ty.to_rustc(tcx);
2067                let n = n.to_rustc(tcx);
2068                ty::Ty::new_array_with_const_len(tcx, ty, n)
2069            }
2070            BaseTy::Never => tcx.types.never,
2071            BaseTy::Closure(did, _, args) => ty::Ty::new_closure(tcx, *did, args.to_rustc(tcx)),
2072            BaseTy::Dynamic(exi_preds, re) => {
2073                let preds: Vec<_> = exi_preds
2074                    .iter()
2075                    .map(|pred| pred.to_rustc(tcx))
2076                    .collect_vec();
2077                let preds = tcx.mk_poly_existential_predicates(&preds);
2078                ty::Ty::new_dynamic(tcx, preds, re.to_rustc(tcx))
2079            }
2080            BaseTy::Coroutine(def_id, resume_ty, upvars) => {
2081                bug!("TODO: Generator {def_id:?} {resume_ty:?} {upvars:?}")
2082                // let args = args.iter().map(|arg| into_rustc_generic_arg(tcx, arg));
2083                // let args = tcx.mk_args_from_iter(args);
2084                // ty::Ty::new_generator(*tcx, *def_id, args, mov)
2085            }
2086            BaseTy::Infer(ty_vid) => ty::Ty::new_var(tcx, *ty_vid),
2087            BaseTy::Foreign(def_id) => ty::Ty::new_foreign(tcx, *def_id),
2088            BaseTy::RawPtrMetadata(ty) => {
2089                ty::Ty::new_ptr(
2090                    tcx,
2091                    ty.to_rustc(tcx),
2092                    RawPtrKind::FakeForPtrMetadata.to_mutbl_lossy(),
2093                )
2094            }
2095        }
2096    }
2097}
2098
2099#[derive(
2100    Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
2101)]
2102pub struct AliasTy {
2103    pub def_id: DefId,
2104    pub args: GenericArgs,
2105    /// Holds the refinement-arguments for opaque-types; empty for projections
2106    pub refine_args: RefineArgs,
2107}
2108
2109impl AliasTy {
2110    pub fn new(def_id: DefId, args: GenericArgs, refine_args: RefineArgs) -> Self {
2111        AliasTy { args, refine_args, def_id }
2112    }
2113}
2114
2115/// This methods work only with associated type projections (i.e., no opaque types)
2116impl AliasTy {
2117    pub fn self_ty(&self) -> SubsetTyCtor {
2118        self.args[0].expect_base().clone()
2119    }
2120
2121    pub fn with_self_ty(&self, self_ty: SubsetTyCtor) -> Self {
2122        Self {
2123            def_id: self.def_id,
2124            args: [GenericArg::Base(self_ty)]
2125                .into_iter()
2126                .chain(self.args.iter().skip(1).cloned())
2127                .collect(),
2128            refine_args: self.refine_args.clone(),
2129        }
2130    }
2131}
2132
2133impl<'tcx> ToRustc<'tcx> for AliasTy {
2134    type T = rustc_middle::ty::AliasTy<'tcx>;
2135
2136    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2137        rustc_middle::ty::AliasTy::new(tcx, self.def_id, self.args.to_rustc(tcx))
2138    }
2139}
2140
2141pub type RefineArgs = List<Expr>;
2142
2143#[extension(pub trait RefineArgsExt)]
2144impl RefineArgs {
2145    fn identity_for_item(genv: GlobalEnv, def_id: DefId) -> QueryResult<RefineArgs> {
2146        Self::for_item(genv, def_id, |param, index| {
2147            Ok(Expr::var(Var::EarlyParam(EarlyReftParam {
2148                index: index as u32,
2149                name: param.name(),
2150            })))
2151        })
2152    }
2153
2154    fn for_item<F>(genv: GlobalEnv, def_id: DefId, mut mk: F) -> QueryResult<RefineArgs>
2155    where
2156        F: FnMut(EarlyBinder<RefineParam>, usize) -> QueryResult<Expr>,
2157    {
2158        let reft_generics = genv.refinement_generics_of(def_id)?;
2159        let count = reft_generics.count();
2160        let mut args = Vec::with_capacity(count);
2161        reft_generics.fill_item(genv, &mut args, &mut mk)?;
2162        Ok(List::from_vec(args))
2163    }
2164}
2165
2166/// A type constructor meant to be used as generic a argument of [kind base]. This is just an alias
2167/// to [`Binder<SubsetTy>`], but we expect the binder to have a single bound variable of the sort of
2168/// the underlying [base type].
2169///
2170/// [kind base]: GenericParamDefKind::Base
2171/// [base type]: SubsetTy::bty
2172pub type SubsetTyCtor = Binder<SubsetTy>;
2173
2174impl SubsetTyCtor {
2175    pub fn as_bty_skipping_binder(&self) -> &BaseTy {
2176        &self.as_ref().skip_binder().bty
2177    }
2178
2179    pub fn to_ty(&self) -> Ty {
2180        let sort = self.sort();
2181        if sort.is_unit() {
2182            self.replace_bound_reft(&Expr::unit()).to_ty()
2183        } else if let Some(def_id) = sort.is_unit_adt() {
2184            self.replace_bound_reft(&Expr::unit_struct(def_id)).to_ty()
2185        } else {
2186            Ty::exists(self.as_ref().map(SubsetTy::to_ty))
2187        }
2188    }
2189
2190    pub fn to_ty_ctor(&self) -> TyCtor {
2191        self.as_ref().map(SubsetTy::to_ty)
2192    }
2193}
2194
2195/// A subset type is a simplified version of a type that has the form `{b[e] | p}` where `b` is a
2196/// [`BaseTy`], `e` a refinement index, and `p` a predicate.
2197///
2198/// These are mainly found under a [`Binder`] with a single variable of the base type's sort. This
2199/// can be interpreted as a type constructor or an existential type. For example, under a binder with a
2200/// variable `v` of sort `int`, we can interpret `{i32[v] | v > 0}` as:
2201/// - A lambda `λv:int. {i32[v] | v > 0}` that "constructs" types when applied to ints, or
2202/// - An existential type `∃v:int. {i32[v] | v > 0}`.
2203///
2204/// This second interpretation is the reason we call this a subset type, i.e., the type `∃v. {b[v] | p}`
2205/// corresponds to the subset of values of  type `b` whose index satisfies `p`. These are the types
2206/// written as `B{v: p}` in the surface syntax and correspond to the types supported in other
2207/// refinement type systems like Liquid Haskell (with the difference that we are explicit
2208/// about separating refinements from program values via an index).
2209///
2210/// The main purpose for subset types is to be used as generic arguments of [kind base] when
2211/// interpreted as type constructors. They have two key properties that makes them suitable
2212/// for this:
2213///
2214/// 1. **Syntactic Restriction**: Subset types are syntactically restricted, making it easier to
2215///    relate them structurally (e.g., for subtyping). For instance, given two types `S<λv. T1>` and
2216///    `S<λ. T2>`, if `T1` and `T2` are subset types, we know they match structurally (at least
2217///    shallowly). In particularly, the syntactic restriction rules out complex types like
2218///    `S<λv. (i32[v], i32[v])>` simplifying some operations.
2219///
2220/// 2. **Eager Canonicalization**: Subset types can be eagerly canonicalized via [*strengthening*]
2221///    during substitution. For example, suppose we have a function:
2222///    ```text
2223///    fn foo<T>(x: T[@a], y: { T[@b] | b == a }) { }
2224///    ```
2225///    If we instantiate `T` with `λv. { i32[v] | v > 0}`, after substitution and applying the
2226///    lambda (the indexing syntax `T[a]` corresponds to an application of the lambda), we get:
2227///    ```text
2228///    fn foo(x: {i32[@a] | a > 0}, y: { { i32[@b] | b > 0 } | b == a }) { }
2229///    ```
2230///    Via *strengthening* we can canonicalize this to
2231///    ```text
2232///    fn foo(x: {i32[@a] | a > 0}, y: { i32[@b] | b == a && b > 0 }) { }
2233///    ```
2234///    As a result, we can guarantee the syntactic restriction through substitution.
2235///
2236/// [kind base]: GenericParamDefKind::Base
2237/// [*strengthening*]: https://arxiv.org/pdf/2010.07763.pdf
2238#[derive(PartialEq, Clone, Eq, Hash, TyEncodable, TyDecodable)]
2239pub struct SubsetTy {
2240    /// The base type `b` in the subset type `{b[e] | p}`.
2241    ///
2242    /// **NOTE:** This is mostly going to be under a [`Binder`]. It is not yet clear to me whether
2243    /// this [`BaseTy`] should be able to mention variables in the binder. In general, in a type
2244    /// `∃v. {b[e] | p}`, it's fine to mention `v` inside `b`, but since [`SubsetTy`] is meant to
2245    /// facilitate syntactic manipulation we may want to restrict this.
2246    pub bty: BaseTy,
2247    /// The refinement index `e` in the subset type `{b[e] | p}`. This can be an arbitrary expression,
2248    /// which makes manipulation easier. However, since this is mostly found under a binder, we expect
2249    /// it to be [`Expr::nu()`].
2250    pub idx: Expr,
2251    /// The predicate `p` in the subset type `{b[e] | p}`.
2252    pub pred: Expr,
2253}
2254
2255impl SubsetTy {
2256    pub fn new(bty: BaseTy, idx: impl Into<Expr>, pred: impl Into<Expr>) -> Self {
2257        Self { bty, idx: idx.into(), pred: pred.into() }
2258    }
2259
2260    pub fn trivial(bty: BaseTy, idx: impl Into<Expr>) -> Self {
2261        Self::new(bty, idx, Expr::tt())
2262    }
2263
2264    pub fn strengthen(&self, pred: impl Into<Expr>) -> Self {
2265        let this = self.clone();
2266        let pred = Expr::and(this.pred, pred).simplify(&SnapshotMap::default());
2267        Self { bty: this.bty, idx: this.idx, pred }
2268    }
2269
2270    pub fn to_ty(&self) -> Ty {
2271        let bty = self.bty.clone();
2272        if self.pred.is_trivially_true() {
2273            Ty::indexed(bty, &self.idx)
2274        } else {
2275            Ty::constr(&self.pred, Ty::indexed(bty, &self.idx))
2276        }
2277    }
2278}
2279
2280impl<'tcx> ToRustc<'tcx> for SubsetTy {
2281    type T = rustc_middle::ty::Ty<'tcx>;
2282
2283    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::Ty<'tcx> {
2284        self.bty.to_rustc(tcx)
2285    }
2286}
2287
2288#[derive(PartialEq, Clone, Eq, Hash, TyEncodable, TyDecodable)]
2289pub enum GenericArg {
2290    Ty(Ty),
2291    Base(SubsetTyCtor),
2292    Lifetime(Region),
2293    Const(Const),
2294}
2295
2296impl GenericArg {
2297    #[track_caller]
2298    pub fn expect_type(&self) -> &Ty {
2299        if let GenericArg::Ty(ty) = self {
2300            ty
2301        } else {
2302            bug!("expected `rty::GenericArg::Ty`, found `{self:?}`")
2303        }
2304    }
2305
2306    #[track_caller]
2307    pub fn expect_base(&self) -> &SubsetTyCtor {
2308        if let GenericArg::Base(ctor) = self {
2309            ctor
2310        } else {
2311            bug!("expected `rty::GenericArg::Base`, found `{self:?}`")
2312        }
2313    }
2314
2315    pub fn from_param_def(param: &GenericParamDef) -> Self {
2316        match param.kind {
2317            GenericParamDefKind::Type { .. } => {
2318                let param_ty = ParamTy { index: param.index, name: param.name };
2319                GenericArg::Ty(Ty::param(param_ty))
2320            }
2321            GenericParamDefKind::Base { .. } => {
2322                // λv. T[v]
2323                let param_ty = ParamTy { index: param.index, name: param.name };
2324                GenericArg::Base(Binder::bind_with_sort(
2325                    SubsetTy::trivial(BaseTy::Param(param_ty), Expr::nu()),
2326                    Sort::Param(param_ty),
2327                ))
2328            }
2329            GenericParamDefKind::Lifetime => {
2330                let region = EarlyParamRegion { index: param.index, name: param.name };
2331                GenericArg::Lifetime(Region::ReEarlyParam(region))
2332            }
2333            GenericParamDefKind::Const { .. } => {
2334                let param_const = ParamConst { index: param.index, name: param.name };
2335                let kind = ConstKind::Param(param_const);
2336                GenericArg::Const(Const { kind })
2337            }
2338        }
2339    }
2340
2341    /// Creates a `GenericArgs` from the definition of generic parameters, by calling a closure to
2342    /// obtain arg. The closures get to observe the `GenericArgs` as they're being built, which can
2343    /// be used to correctly replace defaults of generic parameters.
2344    pub fn for_item<F>(genv: GlobalEnv, def_id: DefId, mut mk_kind: F) -> QueryResult<GenericArgs>
2345    where
2346        F: FnMut(&GenericParamDef, &[GenericArg]) -> GenericArg,
2347    {
2348        let defs = genv.generics_of(def_id)?;
2349        let count = defs.count();
2350        let mut args = Vec::with_capacity(count);
2351        Self::fill_item(genv, &mut args, &defs, &mut mk_kind)?;
2352        Ok(List::from_vec(args))
2353    }
2354
2355    pub fn identity_for_item(genv: GlobalEnv, def_id: DefId) -> QueryResult<GenericArgs> {
2356        Self::for_item(genv, def_id, |param, _| GenericArg::from_param_def(param))
2357    }
2358
2359    fn fill_item<F>(
2360        genv: GlobalEnv,
2361        args: &mut Vec<GenericArg>,
2362        generics: &Generics,
2363        mk_kind: &mut F,
2364    ) -> QueryResult<()>
2365    where
2366        F: FnMut(&GenericParamDef, &[GenericArg]) -> GenericArg,
2367    {
2368        if let Some(def_id) = generics.parent {
2369            let parent_generics = genv.generics_of(def_id)?;
2370            Self::fill_item(genv, args, &parent_generics, mk_kind)?;
2371        }
2372        for param in &generics.own_params {
2373            let kind = mk_kind(param, args);
2374            tracked_span_assert_eq!(param.index as usize, args.len());
2375            args.push(kind);
2376        }
2377        Ok(())
2378    }
2379}
2380
2381impl From<TyOrBase> for GenericArg {
2382    fn from(v: TyOrBase) -> Self {
2383        match v {
2384            TyOrBase::Ty(ty) => GenericArg::Ty(ty),
2385            TyOrBase::Base(ctor) => GenericArg::Base(ctor),
2386        }
2387    }
2388}
2389
2390impl<'tcx> ToRustc<'tcx> for GenericArg {
2391    type T = rustc_middle::ty::GenericArg<'tcx>;
2392
2393    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2394        use rustc_middle::ty;
2395        match self {
2396            GenericArg::Ty(ty) => ty::GenericArg::from(ty.to_rustc(tcx)),
2397            GenericArg::Base(ctor) => ty::GenericArg::from(ctor.skip_binder_ref().to_rustc(tcx)),
2398            GenericArg::Lifetime(re) => ty::GenericArg::from(re.to_rustc(tcx)),
2399            GenericArg::Const(c) => ty::GenericArg::from(c.to_rustc(tcx)),
2400        }
2401    }
2402}
2403
2404pub type GenericArgs = List<GenericArg>;
2405
2406#[extension(pub trait GenericArgsExt)]
2407impl GenericArgs {
2408    #[track_caller]
2409    fn box_args(&self) -> (&Ty, &Ty) {
2410        if let [GenericArg::Ty(deref), GenericArg::Ty(alloc)] = &self[..] {
2411            (deref, alloc)
2412        } else {
2413            bug!("invalid generic arguments for box");
2414        }
2415    }
2416
2417    // We can't implement [`ToRustc`] because of coherence so we add it here
2418    fn to_rustc<'tcx>(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::GenericArgsRef<'tcx> {
2419        tcx.mk_args_from_iter(self.iter().map(|arg| arg.to_rustc(tcx)))
2420    }
2421
2422    fn rebase_onto(
2423        &self,
2424        tcx: &TyCtxt,
2425        source_ancestor: DefId,
2426        target_args: &GenericArgs,
2427    ) -> List<GenericArg> {
2428        let defs = tcx.generics_of(source_ancestor);
2429        target_args
2430            .iter()
2431            .chain(self.iter().skip(defs.count()))
2432            .cloned()
2433            .collect()
2434    }
2435}
2436
2437#[derive(Debug)]
2438pub enum TyOrBase {
2439    Ty(Ty),
2440    Base(SubsetTyCtor),
2441}
2442
2443impl TyOrBase {
2444    pub fn into_ty(self) -> Ty {
2445        match self {
2446            TyOrBase::Ty(ty) => ty,
2447            TyOrBase::Base(ctor) => ctor.to_ty(),
2448        }
2449    }
2450
2451    #[track_caller]
2452    pub fn expect_base(self) -> SubsetTyCtor {
2453        match self {
2454            TyOrBase::Base(ctor) => ctor,
2455            TyOrBase::Ty(_) => tracked_span_bug!("expected `TyOrBase::Base`"),
2456        }
2457    }
2458
2459    pub fn as_base(self) -> Option<SubsetTyCtor> {
2460        match self {
2461            TyOrBase::Base(ctor) => Some(ctor),
2462            TyOrBase::Ty(_) => None,
2463        }
2464    }
2465}
2466
2467#[derive(Debug, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
2468pub enum TyOrCtor {
2469    Ty(Ty),
2470    Ctor(TyCtor),
2471}
2472
2473impl TyOrCtor {
2474    #[track_caller]
2475    pub fn expect_ctor(self) -> TyCtor {
2476        match self {
2477            TyOrCtor::Ctor(ctor) => ctor,
2478            TyOrCtor::Ty(_) => tracked_span_bug!("expected `TyOrCtor::Ctor`"),
2479        }
2480    }
2481
2482    pub fn expect_subset_ty_ctor(self) -> SubsetTyCtor {
2483        self.expect_ctor().map(|ty| {
2484            if let canonicalize::CanonicalTy::Constr(constr_ty) = ty.shallow_canonicalize()
2485                && let TyKind::Indexed(bty, idx) = constr_ty.ty().kind()
2486                && idx.is_nu()
2487            {
2488                SubsetTy::new(bty.clone(), Expr::nu(), constr_ty.pred())
2489            } else {
2490                tracked_span_bug!()
2491            }
2492        })
2493    }
2494
2495    pub fn to_ty(&self) -> Ty {
2496        match self {
2497            TyOrCtor::Ctor(ctor) => ctor.to_ty(),
2498            TyOrCtor::Ty(ty) => ty.clone(),
2499        }
2500    }
2501}
2502
2503impl From<TyOrBase> for TyOrCtor {
2504    fn from(v: TyOrBase) -> Self {
2505        match v {
2506            TyOrBase::Ty(ty) => TyOrCtor::Ty(ty),
2507            TyOrBase::Base(ctor) => TyOrCtor::Ctor(ctor.to_ty_ctor()),
2508        }
2509    }
2510}
2511
2512impl CoroutineObligPredicate {
2513    pub fn to_poly_fn_sig(&self) -> PolyFnSig {
2514        let vars = vec![];
2515
2516        let resume_ty = &self.resume_ty;
2517        let env_ty = Ty::coroutine(self.def_id, resume_ty.clone(), self.upvar_tys.clone());
2518
2519        let inputs = List::from_arr([env_ty, resume_ty.clone()]);
2520        let output =
2521            Binder::bind_with_vars(FnOutput::new(self.output.clone(), vec![]), List::empty());
2522
2523        PolyFnSig::bind_with_vars(
2524            FnSig::new(Safety::Safe, rustc_abi::ExternAbi::RustCall, List::empty(), inputs, output),
2525            List::from(vars),
2526        )
2527    }
2528}
2529
2530impl RefinementGenerics {
2531    pub fn count(&self) -> usize {
2532        self.parent_count + self.own_params.len()
2533    }
2534
2535    pub fn own_count(&self) -> usize {
2536        self.own_params.len()
2537    }
2538}
2539
2540impl EarlyBinder<RefinementGenerics> {
2541    pub fn parent(&self) -> Option<DefId> {
2542        self.skip_binder_ref().parent
2543    }
2544
2545    pub fn parent_count(&self) -> usize {
2546        self.skip_binder_ref().parent_count
2547    }
2548
2549    pub fn count(&self) -> usize {
2550        self.skip_binder_ref().count()
2551    }
2552
2553    pub fn own_count(&self) -> usize {
2554        self.skip_binder_ref().own_count()
2555    }
2556
2557    pub fn own_param_at(&self, index: usize) -> EarlyBinder<RefineParam> {
2558        self.as_ref().map(|this| this.own_params[index].clone())
2559    }
2560
2561    pub fn param_at(
2562        &self,
2563        param_index: usize,
2564        genv: GlobalEnv,
2565    ) -> QueryResult<EarlyBinder<RefineParam>> {
2566        if let Some(index) = param_index.checked_sub(self.parent_count()) {
2567            Ok(self.own_param_at(index))
2568        } else {
2569            let parent = self.parent().expect("parent_count > 0 but no parent?");
2570            genv.refinement_generics_of(parent)?
2571                .param_at(param_index, genv)
2572        }
2573    }
2574
2575    pub fn iter_own_params(&self) -> impl Iterator<Item = EarlyBinder<RefineParam>> + use<'_> {
2576        self.skip_binder_ref()
2577            .own_params
2578            .iter()
2579            .cloned()
2580            .map(EarlyBinder)
2581    }
2582
2583    pub fn fill_item<F, R>(&self, genv: GlobalEnv, vec: &mut Vec<R>, mk: &mut F) -> QueryResult
2584    where
2585        F: FnMut(EarlyBinder<RefineParam>, usize) -> QueryResult<R>,
2586    {
2587        if let Some(def_id) = self.parent() {
2588            genv.refinement_generics_of(def_id)?
2589                .fill_item(genv, vec, mk)?;
2590        }
2591        for param in self.iter_own_params() {
2592            vec.push(mk(param, vec.len())?);
2593        }
2594        Ok(())
2595    }
2596}
2597
2598impl EarlyBinder<GenericPredicates> {
2599    pub fn predicates(&self) -> EarlyBinder<List<Clause>> {
2600        EarlyBinder(self.0.predicates.clone())
2601    }
2602}
2603
2604impl EarlyBinder<FuncSort> {
2605    /// See [`subst::GenericsSubstForSort`]
2606    pub fn instantiate_func_sort<E>(
2607        self,
2608        sort_for_param: impl FnMut(ParamTy) -> Result<Sort, E>,
2609    ) -> Result<FuncSort, E> {
2610        self.0.try_fold_with(&mut subst::GenericsSubstFolder::new(
2611            subst::GenericsSubstForSort { sort_for_param },
2612            &[],
2613        ))
2614    }
2615}
2616
2617impl VariantSig {
2618    pub fn new(
2619        adt_def: AdtDef,
2620        args: GenericArgs,
2621        fields: List<Ty>,
2622        idx: Expr,
2623        requires: List<Expr>,
2624    ) -> Self {
2625        VariantSig { adt_def, args, fields, idx, requires }
2626    }
2627
2628    pub fn fields(&self) -> &[Ty] {
2629        &self.fields
2630    }
2631
2632    pub fn ret(&self) -> Ty {
2633        let bty = BaseTy::Adt(self.adt_def.clone(), self.args.clone());
2634        let idx = self.idx.clone();
2635        Ty::indexed(bty, idx)
2636    }
2637}
2638
2639impl FnSig {
2640    pub fn new(
2641        safety: Safety,
2642        abi: rustc_abi::ExternAbi,
2643        requires: List<Expr>,
2644        inputs: List<Ty>,
2645        output: Binder<FnOutput>,
2646    ) -> Self {
2647        FnSig { safety, abi, requires, inputs, output }
2648    }
2649
2650    pub fn requires(&self) -> &[Expr] {
2651        &self.requires
2652    }
2653
2654    pub fn inputs(&self) -> &[Ty] {
2655        &self.inputs
2656    }
2657
2658    pub fn output(&self) -> Binder<FnOutput> {
2659        self.output.clone()
2660    }
2661}
2662
2663impl<'tcx> ToRustc<'tcx> for FnSig {
2664    type T = rustc_middle::ty::FnSig<'tcx>;
2665
2666    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2667        tcx.mk_fn_sig(
2668            self.inputs().iter().map(|ty| ty.to_rustc(tcx)),
2669            self.output().as_ref().skip_binder().to_rustc(tcx),
2670            false,
2671            self.safety,
2672            self.abi,
2673        )
2674    }
2675}
2676
2677impl FnOutput {
2678    pub fn new(ret: Ty, ensures: impl Into<List<Ensures>>) -> Self {
2679        Self { ret, ensures: ensures.into() }
2680    }
2681}
2682
2683impl<'tcx> ToRustc<'tcx> for FnOutput {
2684    type T = rustc_middle::ty::Ty<'tcx>;
2685
2686    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2687        self.ret.to_rustc(tcx)
2688    }
2689}
2690
2691impl AdtDef {
2692    pub fn new(
2693        rustc: ty::AdtDef,
2694        sort_def: AdtSortDef,
2695        invariants: Vec<Invariant>,
2696        opaque: bool,
2697    ) -> Self {
2698        AdtDef(Interned::new(AdtDefData { invariants, sort_def, opaque, rustc }))
2699    }
2700
2701    pub fn did(&self) -> DefId {
2702        self.0.rustc.did()
2703    }
2704
2705    pub fn sort_def(&self) -> &AdtSortDef {
2706        &self.0.sort_def
2707    }
2708
2709    pub fn sort(&self, args: &[GenericArg]) -> Sort {
2710        self.sort_def().to_sort(args)
2711    }
2712
2713    pub fn is_box(&self) -> bool {
2714        self.0.rustc.is_box()
2715    }
2716
2717    pub fn is_enum(&self) -> bool {
2718        self.0.rustc.is_enum()
2719    }
2720
2721    pub fn is_struct(&self) -> bool {
2722        self.0.rustc.is_struct()
2723    }
2724
2725    pub fn is_union(&self) -> bool {
2726        self.0.rustc.is_union()
2727    }
2728
2729    pub fn variants(&self) -> &IndexSlice<VariantIdx, VariantDef> {
2730        self.0.rustc.variants()
2731    }
2732
2733    pub fn variant(&self, idx: VariantIdx) -> &VariantDef {
2734        self.0.rustc.variant(idx)
2735    }
2736
2737    pub fn invariants(&self) -> EarlyBinder<&[Invariant]> {
2738        EarlyBinder(&self.0.invariants)
2739    }
2740
2741    pub fn discriminants(&self) -> impl Iterator<Item = (VariantIdx, u128)> + '_ {
2742        self.0.rustc.discriminants()
2743    }
2744
2745    pub fn is_opaque(&self) -> bool {
2746        self.0.opaque
2747    }
2748}
2749
2750impl EarlyBinder<PolyVariant> {
2751    // The field_idx is `Some(i)` when we have the `i`-th field of a `union`, in which case,
2752    // the `inputs` are _just_ the `i`-th type (and not all the types...)
2753    pub fn to_poly_fn_sig(&self, field_idx: Option<crate::FieldIdx>) -> EarlyBinder<PolyFnSig> {
2754        self.as_ref().map(|poly_variant| {
2755            poly_variant.as_ref().map(|variant| {
2756                let ret = variant.ret().shift_in_escaping(1);
2757                let output = Binder::bind_with_vars(FnOutput::new(ret, vec![]), List::empty());
2758                let inputs = match field_idx {
2759                    None => variant.fields.clone(),
2760                    Some(i) => List::singleton(variant.fields[i.index()].clone()),
2761                };
2762                FnSig::new(
2763                    Safety::Safe,
2764                    rustc_abi::ExternAbi::Rust,
2765                    variant.requires.clone(),
2766                    inputs,
2767                    output,
2768                )
2769            })
2770        })
2771    }
2772}
2773
2774impl TyKind {
2775    fn intern(self) -> Ty {
2776        Ty(Interned::new(self))
2777    }
2778}
2779
2780/// returns the same invariants as for `usize` which is the length of a slice
2781fn slice_invariants(overflow_mode: OverflowMode) -> &'static [Invariant] {
2782    static DEFAULT: LazyLock<[Invariant; 1]> = LazyLock::new(|| {
2783        [Invariant { pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int) }]
2784    });
2785    static OVERFLOW: LazyLock<[Invariant; 2]> = LazyLock::new(|| {
2786        [
2787            Invariant {
2788                pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int),
2789            },
2790            Invariant {
2791                pred: Binder::bind_with_sort(
2792                    Expr::le(Expr::nu(), Expr::uint_max(UintTy::Usize)),
2793                    Sort::Int,
2794                ),
2795            },
2796        ]
2797    });
2798    if matches!(overflow_mode, OverflowMode::Strict | OverflowMode::Lazy) {
2799        &*OVERFLOW
2800    } else {
2801        &*DEFAULT
2802    }
2803}
2804
2805fn uint_invariants(uint_ty: UintTy, overflow_mode: OverflowMode) -> &'static [Invariant] {
2806    static DEFAULT: LazyLock<[Invariant; 1]> = LazyLock::new(|| {
2807        [Invariant { pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int) }]
2808    });
2809
2810    static OVERFLOW: LazyLock<UnordMap<UintTy, [Invariant; 2]>> = LazyLock::new(|| {
2811        UINT_TYS
2812            .into_iter()
2813            .map(|uint_ty| {
2814                let invariants = [
2815                    Invariant {
2816                        pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int),
2817                    },
2818                    Invariant {
2819                        pred: Binder::bind_with_sort(
2820                            Expr::le(Expr::nu(), Expr::uint_max(uint_ty)),
2821                            Sort::Int,
2822                        ),
2823                    },
2824                ];
2825                (uint_ty, invariants)
2826            })
2827            .collect()
2828    });
2829    if matches!(overflow_mode, OverflowMode::Strict | OverflowMode::Lazy) {
2830        &OVERFLOW[&uint_ty]
2831    } else {
2832        &*DEFAULT
2833    }
2834}
2835
2836fn char_invariants() -> &'static [Invariant] {
2837    static INVARIANTS: LazyLock<[Invariant; 2]> = LazyLock::new(|| {
2838        [
2839            Invariant {
2840                pred: Binder::bind_with_sort(
2841                    Expr::le(
2842                        Expr::cast(Sort::Char, Sort::Int, Expr::nu()),
2843                        Expr::constant((char::MAX as u32).into()),
2844                    ),
2845                    Sort::Int,
2846                ),
2847            },
2848            Invariant {
2849                pred: Binder::bind_with_sort(
2850                    Expr::le(Expr::zero(), Expr::cast(Sort::Char, Sort::Int, Expr::nu())),
2851                    Sort::Int,
2852                ),
2853            },
2854        ]
2855    });
2856    &*INVARIANTS
2857}
2858
2859fn int_invariants(int_ty: IntTy, overflow_mode: OverflowMode) -> &'static [Invariant] {
2860    static DEFAULT: [Invariant; 0] = [];
2861
2862    static OVERFLOW: LazyLock<UnordMap<IntTy, [Invariant; 2]>> = LazyLock::new(|| {
2863        INT_TYS
2864            .into_iter()
2865            .map(|int_ty| {
2866                let invariants = [
2867                    Invariant {
2868                        pred: Binder::bind_with_sort(
2869                            Expr::ge(Expr::nu(), Expr::int_min(int_ty)),
2870                            Sort::Int,
2871                        ),
2872                    },
2873                    Invariant {
2874                        pred: Binder::bind_with_sort(
2875                            Expr::le(Expr::nu(), Expr::int_max(int_ty)),
2876                            Sort::Int,
2877                        ),
2878                    },
2879                ];
2880                (int_ty, invariants)
2881            })
2882            .collect()
2883    });
2884    if matches!(overflow_mode, OverflowMode::Strict | OverflowMode::Lazy) {
2885        &OVERFLOW[&int_ty]
2886    } else {
2887        &DEFAULT
2888    }
2889}
2890
2891impl_internable!(AdtDefData, AdtSortDefData, TyKind);
2892impl_slice_internable!(
2893    Ty,
2894    GenericArg,
2895    Ensures,
2896    InferMode,
2897    Sort,
2898    SortArg,
2899    GenericParamDef,
2900    TraitRef,
2901    Binder<ExistentialPredicate>,
2902    Clause,
2903    PolyVariant,
2904    Invariant,
2905    RefineParam,
2906    FluxDefId,
2907    SortParamKind,
2908    AssocReft
2909);
2910
2911#[macro_export]
2912macro_rules! _Int {
2913    ($int_ty:pat, $idxs:pat) => {
2914        TyKind::Indexed(BaseTy::Int($int_ty), $idxs)
2915    };
2916}
2917pub use crate::_Int as Int;
2918
2919#[macro_export]
2920macro_rules! _Uint {
2921    ($uint_ty:pat, $idxs:pat) => {
2922        TyKind::Indexed(BaseTy::Uint($uint_ty), $idxs)
2923    };
2924}
2925pub use crate::_Uint as Uint;
2926
2927#[macro_export]
2928macro_rules! _Bool {
2929    ($idxs:pat) => {
2930        TyKind::Indexed(BaseTy::Bool, $idxs)
2931    };
2932}
2933pub use crate::_Bool as Bool;
2934
2935#[macro_export]
2936macro_rules! _Char {
2937    ($idxs:pat) => {
2938        TyKind::Indexed(BaseTy::Char, $idxs)
2939    };
2940}
2941pub use crate::_Char as Char;
2942
2943#[macro_export]
2944macro_rules! _Ref {
2945    ($($pats:pat),+ $(,)?) => {
2946        $crate::rty::TyKind::Indexed($crate::rty::BaseTy::Ref($($pats),+), _)
2947    };
2948}
2949pub use crate::_Ref as Ref;
2950
2951pub struct WfckResults {
2952    pub owner: FluxOwnerId,
2953    param_sorts: UnordMap<fhir::ParamId, Sort>,
2954    bin_op_sorts: ItemLocalMap<Sort>,
2955    fn_app_sorts: ItemLocalMap<List<SortArg>>,
2956    coercions: ItemLocalMap<Vec<Coercion>>,
2957    field_projs: ItemLocalMap<FieldProj>,
2958    node_sorts: ItemLocalMap<Sort>,
2959    record_ctors: ItemLocalMap<DefId>,
2960}
2961
2962#[derive(Clone, Copy, Debug)]
2963pub enum Coercion {
2964    Inject(DefId),
2965    Project(DefId),
2966}
2967
2968pub type ItemLocalMap<T> = UnordMap<fhir::ItemLocalId, T>;
2969
2970#[derive(Debug)]
2971pub struct LocalTableInContext<'a, T> {
2972    owner: FluxOwnerId,
2973    data: &'a ItemLocalMap<T>,
2974}
2975
2976pub struct LocalTableInContextMut<'a, T> {
2977    owner: FluxOwnerId,
2978    data: &'a mut ItemLocalMap<T>,
2979}
2980
2981impl WfckResults {
2982    pub fn new(owner: impl Into<FluxOwnerId>) -> Self {
2983        Self {
2984            owner: owner.into(),
2985            param_sorts: UnordMap::default(),
2986            bin_op_sorts: ItemLocalMap::default(),
2987            coercions: ItemLocalMap::default(),
2988            field_projs: ItemLocalMap::default(),
2989            node_sorts: ItemLocalMap::default(),
2990            record_ctors: ItemLocalMap::default(),
2991            fn_app_sorts: ItemLocalMap::default(),
2992        }
2993    }
2994
2995    pub fn param_sorts_mut(&mut self) -> &mut UnordMap<fhir::ParamId, Sort> {
2996        &mut self.param_sorts
2997    }
2998
2999    pub fn param_sorts(&self) -> &UnordMap<fhir::ParamId, Sort> {
3000        &self.param_sorts
3001    }
3002
3003    pub fn bin_op_sorts_mut(&mut self) -> LocalTableInContextMut<'_, Sort> {
3004        LocalTableInContextMut { owner: self.owner, data: &mut self.bin_op_sorts }
3005    }
3006
3007    pub fn fn_app_sorts_mut(&mut self) -> LocalTableInContextMut<'_, List<SortArg>> {
3008        LocalTableInContextMut { owner: self.owner, data: &mut self.fn_app_sorts }
3009    }
3010
3011    pub fn fn_app_sorts(&self) -> LocalTableInContext<'_, List<SortArg>> {
3012        LocalTableInContext { owner: self.owner, data: &self.fn_app_sorts }
3013    }
3014
3015    pub fn bin_op_sorts(&self) -> LocalTableInContext<'_, Sort> {
3016        LocalTableInContext { owner: self.owner, data: &self.bin_op_sorts }
3017    }
3018
3019    pub fn coercions_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Coercion>> {
3020        LocalTableInContextMut { owner: self.owner, data: &mut self.coercions }
3021    }
3022
3023    pub fn coercions(&self) -> LocalTableInContext<'_, Vec<Coercion>> {
3024        LocalTableInContext { owner: self.owner, data: &self.coercions }
3025    }
3026
3027    pub fn field_projs_mut(&mut self) -> LocalTableInContextMut<'_, FieldProj> {
3028        LocalTableInContextMut { owner: self.owner, data: &mut self.field_projs }
3029    }
3030
3031    pub fn field_projs(&self) -> LocalTableInContext<'_, FieldProj> {
3032        LocalTableInContext { owner: self.owner, data: &self.field_projs }
3033    }
3034
3035    pub fn node_sorts_mut(&mut self) -> LocalTableInContextMut<'_, Sort> {
3036        LocalTableInContextMut { owner: self.owner, data: &mut self.node_sorts }
3037    }
3038
3039    pub fn node_sorts(&self) -> LocalTableInContext<'_, Sort> {
3040        LocalTableInContext { owner: self.owner, data: &self.node_sorts }
3041    }
3042
3043    pub fn record_ctors_mut(&mut self) -> LocalTableInContextMut<'_, DefId> {
3044        LocalTableInContextMut { owner: self.owner, data: &mut self.record_ctors }
3045    }
3046
3047    pub fn record_ctors(&self) -> LocalTableInContext<'_, DefId> {
3048        LocalTableInContext { owner: self.owner, data: &self.record_ctors }
3049    }
3050}
3051
3052impl<T> LocalTableInContextMut<'_, T> {
3053    pub fn insert(&mut self, fhir_id: FhirId, value: T) {
3054        tracked_span_assert_eq!(self.owner, fhir_id.owner);
3055        self.data.insert(fhir_id.local_id, value);
3056    }
3057}
3058
3059impl<'a, T> LocalTableInContext<'a, T> {
3060    pub fn get(&self, fhir_id: FhirId) -> Option<&'a T> {
3061        tracked_span_assert_eq!(self.owner, fhir_id.owner);
3062        self.data.get(&fhir_id.local_id)
3063    }
3064}