flux_fhir_analysis/conv/
mod.rs

1//! Conversion from types in [`fhir`] to types in [`rty`]
2//!
3//! Conversion assumes well-formedness and will panic if type are not well-formed. Among other things,
4//! well-formedness implies:
5//! 1. Names are bound correctly.
6//! 2. Refinement parameters appear in allowed positions. This is particularly important for
7//!    refinement predicates, aka abstract refinements, since the syntax in [`rty`] has
8//!    syntactic restrictions on predicates.
9//! 3. Refinements are well-sorted.
10
11pub mod struct_compat;
12use std::{borrow::Borrow, iter};
13
14use flux_common::{bug, iter::IterExt, span_bug};
15use flux_middle::{
16    def_id::MaybeExternId,
17    fhir::{self, ExprRes, FhirId, FluxOwnerId},
18    global_env::GlobalEnv,
19    queries::{QueryErr, QueryResult},
20    query_bug,
21    rty::{
22        self, BoundReftKind, ESpan, INNERMOST, List, RefineArgsExt, WfckResults,
23        fold::TypeFoldable,
24        refining::{self, Refine, Refiner},
25    },
26};
27use flux_rustc_bridge::{
28    ToRustc,
29    lowering::{Lower, UnsupportedErr},
30};
31use itertools::Itertools;
32use rustc_data_structures::{fx::FxIndexMap, unord::UnordMap};
33use rustc_errors::Diagnostic;
34use rustc_hash::FxHashSet;
35use rustc_hir::{self as hir, BodyId, OwnerId, Safety, def::DefKind, def_id::DefId};
36use rustc_index::IndexVec;
37use rustc_middle::{
38    middle::resolve_bound_vars::ResolvedArg,
39    ty::{self, AssocItem, AssocTag, BoundVar, TyCtxt},
40};
41use rustc_span::{
42    DUMMY_SP, ErrorGuaranteed, Span, Symbol,
43    symbol::{Ident, kw},
44};
45use rustc_trait_selection::traits;
46use rustc_type_ir::DebruijnIndex;
47
48/// Wrapper over a type implementing [`ConvPhase`]. We have this to implement most functionality as
49/// inherent methods instead of defining them as default implementation in the trait definition.
50#[repr(transparent)]
51pub struct ConvCtxt<P>(P);
52
53pub(crate) struct AfterSortck<'a, 'genv, 'tcx> {
54    genv: GlobalEnv<'genv, 'tcx>,
55    wfckresults: &'a WfckResults,
56    next_sort_index: u32,
57    next_type_index: u32,
58    next_region_index: u32,
59    next_const_index: u32,
60}
61
62/// We do conversion twice: once before sort checking when we don't have elaborated information
63/// and then again after sort checking after all information has been elaborated. This is the
64/// interface to configure conversion for both *phases*.
65pub trait ConvPhase<'genv, 'tcx>: Sized {
66    /// Whether to expand type aliases or to generate a *weak* [`rty::AliasTy`].
67    const EXPAND_TYPE_ALIASES: bool;
68
69    /// Whether we have elaborated information or not (in the first phase we will not, but in the
70    /// second we will).
71    const HAS_ELABORATED_INFORMATION: bool;
72
73    type Results: WfckResultsProvider;
74
75    fn genv(&self) -> GlobalEnv<'genv, 'tcx>;
76
77    fn owner(&self) -> FluxOwnerId;
78
79    fn next_sort_vid(&mut self) -> rty::SortVid;
80
81    fn next_type_vid(&mut self) -> rty::TyVid;
82
83    fn next_region_vid(&mut self) -> rty::RegionVid;
84
85    fn next_const_vid(&mut self) -> rty::ConstVid;
86
87    fn results(&self) -> &Self::Results;
88
89    /// Called after converting an indexed type `b[e]` with the `fhir_id` and sort of `b`. Used
90    /// during the first phase to collect the sort of base types.
91    fn insert_bty_sort(&mut self, fhir_id: FhirId, sort: rty::Sort);
92
93    /// Called after converting a path with the generic arguments. Using during the first phase
94    /// to instantiate sort of generic refinements.
95    fn insert_path_args(&mut self, fhir_id: FhirId, args: rty::GenericArgs);
96
97    /// Called after converting an [`fhir::ExprKind::Alias`] with the sort of the resulting
98    /// [`rty::AliasReft`]. Used during the first phase to collect the sorts of refinement aliases.
99    fn insert_alias_reft_sort(&mut self, fhir_id: FhirId, fsort: rty::FuncSort);
100
101    fn into_conv_ctxt(self) -> ConvCtxt<Self> {
102        ConvCtxt(self)
103    }
104
105    fn as_conv_ctxt(&mut self) -> &mut ConvCtxt<Self> {
106        // SAFETY: `ConvCtxt` is `repr(transparent)` and it doesn't have any safety invariants.
107        unsafe { std::mem::transmute(self) }
108    }
109}
110
111/// An interface to the information elaborated during sort checking. We mock these results in
112/// the first conversion phase during sort checking.
113pub trait WfckResultsProvider: Sized {
114    fn bin_op_sort(&self, fhir_id: FhirId) -> rty::Sort;
115
116    fn coercions_for(&self, fhir_id: FhirId) -> &[rty::Coercion];
117
118    fn field_proj(&self, fhir_id: FhirId) -> rty::FieldProj;
119
120    fn record_ctor(&self, fhir_id: FhirId) -> DefId;
121
122    fn param_sort(&self, param: &fhir::RefineParam) -> rty::Sort;
123
124    fn node_sort(&self, fhir_id: FhirId) -> rty::Sort;
125}
126
127impl<'genv, 'tcx> ConvPhase<'genv, 'tcx> for AfterSortck<'_, 'genv, 'tcx> {
128    const EXPAND_TYPE_ALIASES: bool = true;
129    const HAS_ELABORATED_INFORMATION: bool = true;
130
131    type Results = WfckResults;
132
133    fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
134        self.genv
135    }
136
137    fn owner(&self) -> FluxOwnerId {
138        self.wfckresults.owner
139    }
140
141    fn next_sort_vid(&mut self) -> rty::SortVid {
142        self.next_sort_index = self.next_sort_index.checked_add(1).unwrap();
143        rty::SortVid::from_u32(self.next_sort_index - 1)
144    }
145
146    fn next_type_vid(&mut self) -> rty::TyVid {
147        self.next_type_index = self.next_type_index.checked_add(1).unwrap();
148        rty::TyVid::from_u32(self.next_type_index - 1)
149    }
150
151    fn next_region_vid(&mut self) -> rty::RegionVid {
152        self.next_region_index = self.next_region_index.checked_add(1).unwrap();
153        rty::RegionVid::from_u32(self.next_region_index - 1)
154    }
155
156    fn next_const_vid(&mut self) -> rty::ConstVid {
157        self.next_const_index = self.next_const_index.checked_add(1).unwrap();
158        rty::ConstVid::from_u32(self.next_const_index - 1)
159    }
160
161    fn results(&self) -> &Self::Results {
162        self.wfckresults
163    }
164
165    fn insert_bty_sort(&mut self, _: FhirId, _: rty::Sort) {}
166
167    fn insert_path_args(&mut self, _: FhirId, _: rty::GenericArgs) {}
168
169    fn insert_alias_reft_sort(&mut self, _: FhirId, _: rty::FuncSort) {}
170}
171
172impl WfckResultsProvider for WfckResults {
173    fn bin_op_sort(&self, fhir_id: FhirId) -> rty::Sort {
174        self.bin_op_sorts()
175            .get(fhir_id)
176            .cloned()
177            .unwrap_or_else(|| bug!("binary relation without elaborated sort `{fhir_id:?}`"))
178    }
179
180    fn coercions_for(&self, fhir_id: FhirId) -> &[rty::Coercion] {
181        self.coercions().get(fhir_id).map_or(&[][..], Vec::as_slice)
182    }
183
184    fn field_proj(&self, fhir_id: FhirId) -> rty::FieldProj {
185        *self
186            .field_projs()
187            .get(fhir_id)
188            .unwrap_or_else(|| bug!("field projection without elaboration `{fhir_id:?}`"))
189    }
190
191    fn record_ctor(&self, fhir_id: FhirId) -> DefId {
192        *self
193            .record_ctors()
194            .get(fhir_id)
195            .unwrap_or_else(|| bug!("unelaborated record constructor `{fhir_id:?}`"))
196    }
197
198    fn param_sort(&self, param: &fhir::RefineParam) -> rty::Sort {
199        self.node_sorts()
200            .get(param.fhir_id)
201            .unwrap_or_else(|| bug!("unresolved sort for param `{param:?}`"))
202            .clone()
203    }
204
205    fn node_sort(&self, fhir_id: FhirId) -> rty::Sort {
206        self.node_sorts()
207            .get(fhir_id)
208            .unwrap_or_else(|| bug!("node without elaborated sort for `{fhir_id:?}`"))
209            .clone()
210    }
211}
212
213#[derive(Debug)]
214pub(crate) struct Env {
215    layers: Vec<Layer>,
216    early_params: FxIndexMap<fhir::ParamId, Symbol>,
217}
218
219#[derive(Debug, Clone)]
220struct Layer {
221    map: FxIndexMap<fhir::ParamId, ParamEntry>,
222    kind: LayerKind,
223}
224
225/// Whether the list of parameters in a layer is converted into a list of bound variables or
226/// coalesced into a single parameter of [adt] sort.
227///
228/// [adt]: rty::SortCtor::Adt
229#[derive(Debug, Clone, Copy)]
230enum LayerKind {
231    List {
232        /// The number of regions bound in this layer. Since regions and refinements are both
233        /// bound with a [`rty::Binder`] we need to keep track of the number of bound regions
234        /// to skip them when assigning an index to refinement parameters.
235        bound_regions: u32,
236    },
237    Coalesce(DefId),
238}
239
240#[derive(Debug, Clone)]
241struct ParamEntry {
242    name: Symbol,
243    sort: rty::Sort,
244    mode: rty::InferMode,
245}
246
247#[derive(Debug)]
248struct LookupResult<'a> {
249    kind: LookupResultKind<'a>,
250    /// The span of the variable that originated the lookup.
251    var_span: Span,
252}
253
254#[derive(Debug)]
255enum LookupResultKind<'a> {
256    Bound {
257        debruijn: DebruijnIndex,
258        entry: &'a ParamEntry,
259        kind: LayerKind,
260        /// The index of the parameter in the layer.
261        index: u32,
262    },
263    EarlyParam {
264        name: Symbol,
265        /// The index of the parameter.
266        index: u32,
267    },
268}
269
270pub(crate) fn conv_adt_sort_def(
271    genv: GlobalEnv,
272    def_id: MaybeExternId,
273    kind: &fhir::RefinementKind,
274) -> QueryResult<rty::AdtSortDef> {
275    let wfckresults = &WfckResults::new(OwnerId { def_id: def_id.local_id() });
276    let mut cx = AfterSortck::new(genv, wfckresults).into_conv_ctxt();
277    match kind {
278        fhir::RefinementKind::Refined(refined_by) => {
279            let params = refined_by
280                .sort_params
281                .iter()
282                .map(|def_id| def_id_to_param_ty(genv, *def_id))
283                .collect();
284            let fields = refined_by
285                .fields
286                .iter()
287                .map(|(name, sort)| -> QueryResult<_> { Ok((*name, cx.conv_sort(sort)?)) })
288                .try_collect_vec()?;
289            let variants = IndexVec::from([rty::AdtSortVariant::new(fields)]);
290            let def_id = def_id.resolved_id();
291            Ok(rty::AdtSortDef::new(def_id, params, variants, false, true))
292        }
293        fhir::RefinementKind::Reflected => {
294            let enum_def_id = def_id.resolved_id();
295            let mut variants = IndexVec::new();
296            for variant in genv.tcx().adt_def(enum_def_id).variants() {
297                if let Some(field) = variant.fields.iter().next() {
298                    let span = genv.tcx().def_span(field.did);
299                    let err = genv
300                        .sess()
301                        .emit_err(errors::FieldsOnReflectedEnumVariant::new(span));
302                    Err(err)?;
303                }
304                variants.push(rty::AdtSortVariant::new(vec![]));
305            }
306            Ok(rty::AdtSortDef::new(enum_def_id, vec![], variants, true, false))
307        }
308    }
309}
310
311pub(crate) fn conv_generics(
312    genv: GlobalEnv,
313    generics: &fhir::Generics,
314    def_id: MaybeExternId,
315    is_trait: bool,
316) -> rty::Generics {
317    let opt_self = is_trait.then(|| {
318        let kind = rty::GenericParamDefKind::Base { has_default: false };
319        rty::GenericParamDef { index: 0, name: kw::SelfUpper, def_id: def_id.resolved_id(), kind }
320    });
321    let rust_generics = genv.tcx().generics_of(def_id.resolved_id());
322    let params = {
323        opt_self
324            .into_iter()
325            .chain(rust_generics.own_params.iter().flat_map(|rust_param| {
326                // We have to filter out late bound parameters
327                let param = generics
328                    .params
329                    .iter()
330                    .find(|param| param.def_id.resolved_id() == rust_param.def_id)?;
331                Some(rty::GenericParamDef {
332                    kind: conv_generic_param_kind(&param.kind),
333                    def_id: param.def_id.resolved_id(),
334                    index: rust_param.index,
335                    name: rust_param.name,
336                })
337            }))
338            .collect_vec()
339    };
340
341    let rust_generics = genv.tcx().generics_of(def_id.resolved_id());
342    rty::Generics {
343        own_params: List::from_vec(params),
344        parent: rust_generics.parent,
345        parent_count: rust_generics.parent_count,
346        has_self: rust_generics.has_self,
347    }
348}
349
350pub(crate) fn conv_refinement_generics(
351    params: &[fhir::RefineParam],
352    wfckresults: &WfckResults,
353) -> QueryResult<List<rty::RefineParam>> {
354    params
355        .iter()
356        .map(|param| {
357            let sort = wfckresults.param_sort(param);
358            let mode = rty::InferMode::from_param_kind(param.kind);
359            Ok(rty::RefineParam { sort, name: param.name, mode })
360        })
361        .try_collect()
362}
363
364fn conv_generic_param_kind(kind: &fhir::GenericParamKind) -> rty::GenericParamDefKind {
365    match kind {
366        fhir::GenericParamKind::Type { default } => {
367            rty::GenericParamDefKind::Base { has_default: default.is_some() }
368        }
369        fhir::GenericParamKind::Lifetime => rty::GenericParamDefKind::Lifetime,
370        fhir::GenericParamKind::Const { .. } => {
371            rty::GenericParamDefKind::Const { has_default: false }
372        }
373    }
374}
375
376pub(crate) fn conv_constant(genv: GlobalEnv, def_id: DefId) -> QueryResult<rty::ConstantInfo> {
377    let ty = genv.tcx().type_of(def_id).no_bound_vars().unwrap();
378    if ty.is_integral() {
379        let val = genv.tcx().const_eval_poly(def_id).ok().and_then(|val| {
380            let val = val.try_to_scalar_int()?;
381            rty::Constant::from_scalar_int(genv.tcx(), val, &ty)
382        });
383        if let Some(constant_) = val {
384            return Ok(rty::ConstantInfo::Interpreted(
385                rty::Expr::constant(constant_),
386                rty::Sort::Int,
387            ));
388        }
389        // FIXME(nilehmann) we should probably report an error in case const evaluation
390        // fails instead of silently ignore it.
391    }
392    Ok(rty::ConstantInfo::Uninterpreted)
393}
394
395pub(crate) fn conv_constant_expr(
396    genv: GlobalEnv,
397    _def_id: DefId,
398    expr: &fhir::Expr,
399    sort: rty::Sort,
400    wfckresults: &WfckResults,
401) -> QueryResult<rty::ConstantInfo> {
402    let mut cx = AfterSortck::new(genv, wfckresults).into_conv_ctxt();
403    let mut env = Env::new(&[]);
404    Ok(rty::ConstantInfo::Interpreted(cx.conv_expr(&mut env, expr)?, sort))
405}
406
407pub(crate) fn conv_defn(
408    genv: GlobalEnv,
409    func: &fhir::SpecFunc,
410    wfckresults: &WfckResults,
411) -> QueryResult<Option<rty::Binder<rty::Expr>>> {
412    if let Some(body) = &func.body {
413        let mut cx = AfterSortck::new(genv, wfckresults).into_conv_ctxt();
414        let mut env = Env::new(&[]);
415        env.push_layer(Layer::list(wfckresults, 0, func.args));
416        let expr = cx.conv_expr(&mut env, body)?;
417        let body = rty::Binder::bind_with_vars(expr, env.pop_layer().into_bound_vars(genv)?);
418        Ok(Some(body))
419    } else {
420        Ok(None)
421    }
422}
423
424pub(crate) fn conv_prim_prop(
425    genv: GlobalEnv,
426    prim_prop: &fhir::PrimProp,
427    wfckresults: &WfckResults,
428) -> QueryResult<rty::PrimProp> {
429    let mut cx = AfterSortck::new(genv, wfckresults).into_conv_ctxt();
430    let mut env = Env::new(&[]);
431    env.push_layer(Layer::list(wfckresults, 0, prim_prop.args));
432    let body = cx.conv_expr(&mut env, &prim_prop.body)?;
433    let body = rty::Binder::bind_with_vars(body, env.pop_layer().into_bound_vars(genv)?);
434    let op = match prim_prop.op {
435        fhir::BinOp::BitAnd => rty::BinOp::BitAnd,
436        fhir::BinOp::BitOr => rty::BinOp::BitOr,
437        fhir::BinOp::BitShl => rty::BinOp::BitShl,
438        fhir::BinOp::BitShr => rty::BinOp::BitShr,
439        _ => {
440            span_bug!(
441                prim_prop.span,
442                "unexpected binary operator in primitive property: {:?}",
443                prim_prop.op
444            )
445        }
446    };
447    Ok(rty::PrimProp { def_id: prim_prop.def_id, op, body })
448}
449
450pub(crate) fn conv_qualifier(
451    genv: GlobalEnv,
452    qualifier: &fhir::Qualifier,
453    wfckresults: &WfckResults,
454) -> QueryResult<rty::Qualifier> {
455    let mut cx = AfterSortck::new(genv, wfckresults).into_conv_ctxt();
456    let mut env = Env::new(&[]);
457    env.push_layer(Layer::list(wfckresults, 0, qualifier.args));
458    let body = cx.conv_expr(&mut env, &qualifier.expr)?;
459    let body = rty::Binder::bind_with_vars(body, env.pop_layer().into_bound_vars(genv)?);
460    Ok(rty::Qualifier { def_id: qualifier.def_id, body, global: qualifier.global })
461}
462
463pub(crate) fn conv_default_type_parameter(
464    genv: GlobalEnv,
465    def_id: MaybeExternId,
466    ty: &fhir::Ty,
467    wfckresults: &WfckResults,
468) -> QueryResult<rty::TyOrBase> {
469    let mut env = Env::new(&[]);
470    let idx = genv.def_id_to_param_index(def_id.resolved_id());
471    let owner = ty_param_owner(genv, def_id.resolved_id());
472    let param = genv.generics_of(owner)?.param_at(idx as usize, genv)?;
473    let mut cx = AfterSortck::new(genv, wfckresults).into_conv_ctxt();
474    let rty_ty = cx.conv_ty(&mut env, ty)?;
475    cx.try_to_ty_or_base(param.kind, ty.span, &rty_ty)
476}
477
478impl<'a, 'genv, 'tcx> AfterSortck<'a, 'genv, 'tcx> {
479    pub(crate) fn new(genv: GlobalEnv<'genv, 'tcx>, wfckresults: &'a WfckResults) -> Self {
480        Self {
481            genv,
482            wfckresults,
483            // We start sorts and types from 1 to skip the trait object dummy self type.
484            // See [`rty::Ty::trait_object_dummy_self`]
485            next_sort_index: 1,
486            next_type_index: 1,
487            next_region_index: 0,
488            next_const_index: 0,
489        }
490    }
491}
492
493/// Delegate methods to P
494impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
495    fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
496        self.0.genv()
497    }
498
499    fn tcx(&self) -> TyCtxt<'tcx> {
500        self.0.genv().tcx()
501    }
502
503    fn owner(&self) -> FluxOwnerId {
504        self.0.owner()
505    }
506
507    fn results(&self) -> &P::Results {
508        self.0.results()
509    }
510
511    fn next_sort_vid(&mut self) -> rty::SortVid {
512        self.0.next_sort_vid()
513    }
514
515    fn next_type_vid(&mut self) -> rty::TyVid {
516        self.0.next_type_vid()
517    }
518
519    fn next_region_vid(&mut self) -> rty::RegionVid {
520        self.0.next_region_vid()
521    }
522
523    fn next_const_vid(&mut self) -> rty::ConstVid {
524        self.0.next_const_vid()
525    }
526}
527
528fn variant_idx(tcx: TyCtxt, variant_def_id: DefId) -> rty::VariantIdx {
529    let enum_def_id = tcx.parent(variant_def_id);
530    tcx.adt_def(enum_def_id)
531        .variant_index_with_id(variant_def_id)
532}
533
534/// Conversion of definitions
535impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
536    pub(crate) fn conv_enum_variants(
537        &mut self,
538        enum_id: MaybeExternId,
539        enum_def: &fhir::EnumDef,
540    ) -> QueryResult<Vec<rty::PolyVariant>> {
541        let reflected = enum_def.refinement.is_reflected();
542        enum_def
543            .variants
544            .iter()
545            .map(|variant| self.conv_enum_variant(enum_id, variant, reflected))
546            .try_collect_vec()
547    }
548
549    fn conv_enum_variant(
550        &mut self,
551        enum_id: MaybeExternId,
552        variant: &fhir::VariantDef,
553        reflected: bool,
554    ) -> QueryResult<rty::PolyVariant> {
555        let mut env = Env::new(&[]);
556        env.push_layer(Layer::list(self.results(), 0, variant.params));
557
558        // TODO(RJ): just "lift" the fields, ignore any `variant` signatures if reflected?
559        let fields = variant
560            .fields
561            .iter()
562            .map(|field| self.conv_ty(&mut env, &field.ty))
563            .try_collect()?;
564
565        let adt_def = self.genv().adt_def(enum_id)?;
566        let idxs = if reflected {
567            let enum_def_id = enum_id.resolved_id();
568            let idx = variant_idx(self.tcx(), variant.def_id.to_def_id());
569            rty::Expr::ctor_enum(enum_def_id, idx)
570        } else {
571            self.conv_expr(&mut env, &variant.ret.idx)?
572        };
573        let variant = rty::VariantSig::new(
574            adt_def,
575            rty::GenericArg::identity_for_item(self.genv(), enum_id.resolved_id())?,
576            fields,
577            idxs,
578            List::empty(),
579        );
580
581        Ok(rty::Binder::bind_with_vars(variant, env.pop_layer().into_bound_vars(self.genv())?))
582    }
583
584    pub(crate) fn conv_struct_variant(
585        &mut self,
586        struct_id: MaybeExternId,
587        struct_def: &fhir::StructDef,
588    ) -> QueryResult<rty::Opaqueness<rty::PolyVariant>> {
589        let mut env = Env::new(&[]);
590        env.push_layer(Layer::list(self.results(), 0, struct_def.params));
591
592        if let fhir::StructKind::Transparent { fields } = &struct_def.kind {
593            let adt_def = self.genv().adt_def(struct_id)?;
594
595            let fields = fields
596                .iter()
597                .map(|field_def| self.conv_ty(&mut env, &field_def.ty))
598                .try_collect()?;
599
600            let vars = env.pop_layer().into_bound_vars(self.genv())?;
601            let idx = rty::Expr::ctor_struct(
602                struct_id.resolved_id(),
603                (0..vars.len())
604                    .map(|idx| {
605                        rty::Expr::bvar(
606                            INNERMOST,
607                            BoundVar::from_usize(idx),
608                            rty::BoundReftKind::Annon,
609                        )
610                    })
611                    .collect(),
612            );
613
614            let requires = adt_def
615                .invariants()
616                .iter_identity()
617                .map(|inv| inv.apply(&idx))
618                .collect();
619
620            let variant = rty::VariantSig::new(
621                adt_def,
622                rty::GenericArg::identity_for_item(self.genv(), struct_id.resolved_id())?,
623                fields,
624                idx,
625                requires,
626            );
627            let variant = rty::Binder::bind_with_vars(variant, vars);
628            Ok(rty::Opaqueness::Transparent(variant))
629        } else {
630            Ok(rty::Opaqueness::Opaque)
631        }
632    }
633
634    pub(crate) fn conv_type_alias(
635        &mut self,
636        ty_alias_id: MaybeExternId,
637        ty_alias: &fhir::TyAlias,
638    ) -> QueryResult<rty::TyCtor> {
639        let generics = self
640            .genv()
641            .map()
642            .get_generics(ty_alias_id.local_id())?
643            .unwrap();
644
645        let mut env = Env::new(generics.refinement_params);
646
647        if let Some(index) = &ty_alias.index {
648            env.push_layer(Layer::list(self.results(), 0, std::slice::from_ref(index)));
649            let ty = self.conv_ty(&mut env, &ty_alias.ty)?;
650
651            Ok(rty::Binder::bind_with_vars(ty, env.pop_layer().into_bound_vars(self.genv())?))
652        } else {
653            let ctor = self
654                .conv_ty(&mut env, &ty_alias.ty)?
655                .shallow_canonicalize()
656                .as_ty_or_base()
657                .as_base()
658                .ok_or_else(|| self.emit(errors::InvalidBaseInstance::new(ty_alias.span)))?;
659            Ok(ctor.to_ty_ctor())
660        }
661    }
662
663    pub(crate) fn conv_fn_sig(
664        &mut self,
665        fn_id: MaybeExternId,
666        fn_sig: &fhir::FnSig,
667    ) -> QueryResult<rty::PolyFnSig> {
668        let decl = &fn_sig.decl;
669        let header = fn_sig.header;
670
671        let late_bound_regions =
672            refining::refine_bound_variables(&self.genv().lower_late_bound_vars(fn_id.local_id())?);
673
674        let generics = self.genv().map().get_generics(fn_id.local_id())?.unwrap();
675        let mut env = Env::new(generics.refinement_params);
676        env.push_layer(Layer::list(self.results(), late_bound_regions.len() as u32, &[]));
677
678        let body_id = self.tcx().hir_node_by_def_id(fn_id.local_id()).body_id();
679        let fn_sig = self.conv_fn_decl(&mut env, header.safety(), header.abi, decl, body_id)?;
680
681        let vars = late_bound_regions
682            .iter()
683            .chain(env.pop_layer().into_bound_vars(self.genv())?.iter())
684            .cloned()
685            .collect();
686
687        Ok(rty::PolyFnSig::bind_with_vars(fn_sig, vars))
688    }
689
690    pub(crate) fn conv_generic_predicates(
691        &mut self,
692        def_id: MaybeExternId,
693        generics: &fhir::Generics,
694    ) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
695        let env = &mut Env::new(generics.refinement_params);
696
697        let predicates = if let Some(fhir_predicates) = generics.predicates {
698            let mut clauses = vec![];
699            for pred in fhir_predicates {
700                let span = pred.bounded_ty.span;
701                let bounded_ty = self.conv_ty(env, &pred.bounded_ty)?;
702                for clause in self.conv_generic_bounds(env, span, bounded_ty, pred.bounds)? {
703                    clauses.push(clause);
704                }
705            }
706            self.match_clauses(def_id, &clauses)?
707        } else {
708            self.genv()
709                .lower_predicates_of(def_id)?
710                .refine(&Refiner::default_for_item(self.genv(), def_id.resolved_id())?)?
711        };
712        Ok(rty::EarlyBinder(predicates))
713    }
714
715    fn match_clauses(
716        &self,
717        def_id: MaybeExternId,
718        refined_clauses: &[rty::Clause],
719    ) -> QueryResult<rty::GenericPredicates> {
720        let tcx = self.genv().tcx();
721        let predicates = tcx.predicates_of(def_id);
722        let unrefined_clauses = predicates.predicates;
723
724        // For each *refined clause* at index `j` find a corresponding *unrefined clause* at index
725        // `i` and save a mapping `i -> j`.
726        let mut map = UnordMap::default();
727        for (j, clause) in refined_clauses.iter().enumerate() {
728            let clause = clause.to_rustc(tcx);
729            let Some((i, _)) = unrefined_clauses.iter().find_position(|it| it.0 == clause) else {
730                self.emit_fail_to_match_predicates(def_id)?;
731            };
732            if map.insert(i, j).is_some() {
733                self.emit_fail_to_match_predicates(def_id)?;
734            }
735        }
736
737        // For each unrefined clause, create a default refined clause or use corresponding refined
738        // clause if one was found.
739        let refiner = Refiner::default_for_item(self.genv(), def_id.resolved_id())?;
740        let mut clauses = vec![];
741        for (i, (clause, span)) in unrefined_clauses.iter().enumerate() {
742            let clause = if let Some(j) = map.get(&i) {
743                refined_clauses[*j].clone()
744            } else {
745                clause
746                    .lower(tcx)
747                    .map_err(|reason| {
748                        let err = UnsupportedErr::new(reason).with_span(*span);
749                        QueryErr::unsupported(def_id.resolved_id(), err)
750                    })?
751                    .refine(&refiner)?
752            };
753            clauses.push(clause);
754        }
755
756        Ok(rty::GenericPredicates {
757            parent: predicates.parent,
758            predicates: List::from_vec(clauses),
759        })
760    }
761
762    fn emit_fail_to_match_predicates(&self, def_id: MaybeExternId) -> Result<!, ErrorGuaranteed> {
763        let span = self.tcx().def_span(def_id.resolved_id());
764        Err(self.emit(errors::FailToMatchPredicates { span }))
765    }
766
767    pub(crate) fn conv_opaque_ty(
768        &mut self,
769        opaque_ty: &fhir::OpaqueTy,
770    ) -> QueryResult<rty::Clauses> {
771        let def_id = opaque_ty.def_id;
772        let parent = self.tcx().local_parent(def_id.local_id());
773        let refparams = &self
774            .genv()
775            .map()
776            .get_generics(parent)?
777            .unwrap()
778            .refinement_params;
779
780        let env = &mut Env::new(refparams);
781
782        let args = rty::GenericArg::identity_for_item(self.genv(), def_id.resolved_id())?;
783        let alias_ty = rty::AliasTy::new(def_id.resolved_id(), args, env.to_early_param_args());
784        let self_ty = rty::BaseTy::opaque(alias_ty).to_ty();
785        // FIXME(nilehmann) use a good span here
786        Ok(self
787            .conv_generic_bounds(env, DUMMY_SP, self_ty, opaque_ty.bounds)?
788            .into_iter()
789            .collect())
790    }
791
792    pub(crate) fn conv_assoc_reft_body(
793        &mut self,
794        params: &[fhir::RefineParam],
795        body: &fhir::Expr,
796        output: &fhir::Sort,
797    ) -> QueryResult<rty::Lambda> {
798        let mut env = Env::new(&[]);
799        env.push_layer(Layer::list(self.results(), 0, params));
800        let expr = self.conv_expr(&mut env, body)?;
801        let output = self.conv_sort(output)?;
802        let inputs = env.pop_layer().into_bound_vars(self.genv())?;
803        Ok(rty::Lambda::bind_with_vars(expr, inputs, output))
804    }
805}
806
807/// Conversion of sorts
808impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
809    pub(crate) fn conv_sort(&mut self, sort: &fhir::Sort) -> QueryResult<rty::Sort> {
810        let sort = match sort {
811            fhir::Sort::Path(path) => self.conv_sort_path(path)?,
812            fhir::Sort::BitVec(size) => rty::Sort::BitVec(rty::BvSize::Fixed(*size)),
813            fhir::Sort::Loc => rty::Sort::Loc,
814            fhir::Sort::Func(fsort) => rty::Sort::Func(self.conv_poly_func_sort(fsort)?),
815            fhir::Sort::SortOf(bty) => {
816                let rty::TyOrCtor::Ctor(ty_ctor) = self.conv_bty(&mut Env::empty(), bty, None)?
817                else {
818                    // FIXME: maybe we should have a dedicated error for this
819                    return Err(self.emit(errors::RefinedUnrefinableType::new(bty.span)))?;
820                };
821                ty_ctor.sort()
822            }
823            fhir::Sort::Infer => rty::Sort::Infer(rty::SortVar(self.next_sort_vid())),
824            fhir::Sort::Err(_) => rty::Sort::Err,
825        };
826        Ok(sort)
827    }
828
829    fn conv_poly_func_sort(&mut self, sort: &fhir::PolyFuncSort) -> QueryResult<rty::PolyFuncSort> {
830        let params = iter::repeat_n(rty::SortParamKind::Sort, sort.params).collect();
831        Ok(rty::PolyFuncSort::new(params, self.conv_func_sort(&sort.fsort)?))
832    }
833
834    fn conv_func_sort(&mut self, fsort: &fhir::FuncSort) -> QueryResult<rty::FuncSort> {
835        let inputs = fsort
836            .inputs()
837            .iter()
838            .map(|sort| self.conv_sort(sort))
839            .try_collect()?;
840        Ok(rty::FuncSort::new(inputs, self.conv_sort(fsort.output())?))
841    }
842
843    fn conv_sort_path(&mut self, path: &fhir::SortPath) -> QueryResult<rty::Sort> {
844        let ctor = match path.res {
845            fhir::SortRes::PrimSort(fhir::PrimSort::Int) => {
846                self.check_prim_sort_generics(path, fhir::PrimSort::Int)?;
847                return Ok(rty::Sort::Int);
848            }
849            fhir::SortRes::PrimSort(fhir::PrimSort::Bool) => {
850                self.check_prim_sort_generics(path, fhir::PrimSort::Bool)?;
851                return Ok(rty::Sort::Bool);
852            }
853            fhir::SortRes::PrimSort(fhir::PrimSort::Real) => {
854                self.check_prim_sort_generics(path, fhir::PrimSort::Real)?;
855                return Ok(rty::Sort::Real);
856            }
857            fhir::SortRes::PrimSort(fhir::PrimSort::Char) => {
858                self.check_prim_sort_generics(path, fhir::PrimSort::Char)?;
859                return Ok(rty::Sort::Char);
860            }
861            fhir::SortRes::SortParam(n) => return Ok(rty::Sort::Var(rty::ParamSort::from(n))),
862            fhir::SortRes::TyParam(def_id) => {
863                if !path.args.is_empty() {
864                    let err = errors::GenericsOnSortTyParam::new(
865                        path.segments.last().unwrap().span,
866                        path.args.len(),
867                    );
868                    Err(self.emit(err))?;
869                }
870                return Ok(rty::Sort::Param(def_id_to_param_ty(self.genv(), def_id)));
871            }
872            fhir::SortRes::SelfParam { .. } => {
873                if !path.args.is_empty() {
874                    let err = errors::GenericsOnSelf::new(
875                        path.segments.last().unwrap().span,
876                        path.args.len(),
877                    );
878                    Err(self.emit(err))?;
879                }
880                return Ok(rty::Sort::Param(rty::SELF_PARAM_TY));
881            }
882            fhir::SortRes::SelfAlias { alias_to } => {
883                if !path.args.is_empty() {
884                    let err = errors::GenericsOnSelf::new(
885                        path.segments.last().unwrap().span,
886                        path.args.len(),
887                    );
888                    Err(self.emit(err))?;
889                }
890                return Ok(self
891                    .genv()
892                    .sort_of_self_ty_alias(alias_to)?
893                    .unwrap_or(rty::Sort::Err));
894            }
895            fhir::SortRes::SelfParamAssoc { trait_id, ident } => {
896                let res = fhir::Res::SelfTyParam { trait_: trait_id };
897                let assoc_segment =
898                    fhir::PathSegment { args: &[], constraints: &[], ident, res: fhir::Res::Err };
899                let mut env = Env::empty();
900                let alias_ty =
901                    self.conv_type_relative_path(&mut env, ident.span, res, &assoc_segment)?;
902                return Ok(rty::Sort::Alias(rty::AliasKind::Projection, alias_ty));
903            }
904            fhir::SortRes::PrimSort(fhir::PrimSort::Set) => {
905                self.check_prim_sort_generics(path, fhir::PrimSort::Set)?;
906                rty::SortCtor::Set
907            }
908            fhir::SortRes::PrimSort(fhir::PrimSort::Map) => {
909                self.check_prim_sort_generics(path, fhir::PrimSort::Map)?;
910                rty::SortCtor::Map
911            }
912            fhir::SortRes::User { name } => {
913                if !path.args.is_empty() {
914                    let err = errors::GenericsOnUserDefinedOpaqueSort::new(
915                        path.segments.last().unwrap().span,
916                        path.args.len(),
917                    );
918                    Err(self.emit(err))?;
919                }
920                rty::SortCtor::User { name }
921            }
922            fhir::SortRes::Adt(def_id) => {
923                let sort_def = self.genv().adt_sort_def_of(def_id)?;
924                if path.args.len() > sort_def.param_count() {
925                    let err = errors::IncorrectGenericsOnSort::new(
926                        self.genv(),
927                        def_id,
928                        path.segments.last().unwrap().span,
929                        path.args.len(),
930                        sort_def.param_count(),
931                    );
932                    Err(self.emit(err))?;
933                }
934                rty::SortCtor::Adt(sort_def)
935            }
936        };
937        let args = path.args.iter().map(|t| self.conv_sort(t)).try_collect()?;
938
939        Ok(rty::Sort::app(ctor, args))
940    }
941
942    fn check_prim_sort_generics(
943        &mut self,
944        path: &fhir::SortPath<'_>,
945        prim_sort: fhir::PrimSort,
946    ) -> QueryResult {
947        if path.args.len() != prim_sort.generics() {
948            let err = errors::GenericsOnPrimitiveSort::new(
949                path.segments.last().unwrap().span,
950                prim_sort.name_str(),
951                path.args.len(),
952                prim_sort.generics(),
953            );
954            Err(self.emit(err))?;
955        }
956        Ok(())
957    }
958}
959
960/// Conversion of types
961impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
962    fn conv_fn_decl(
963        &mut self,
964        env: &mut Env,
965        safety: Safety,
966        abi: rustc_abi::ExternAbi,
967        decl: &fhir::FnDecl,
968        body_id: Option<BodyId>,
969    ) -> QueryResult<rty::FnSig> {
970        let mut requires = vec![];
971        for req in decl.requires {
972            requires.push(self.conv_requires(env, req)?);
973        }
974
975        let mut inputs = vec![];
976        let params =
977            if let Some(body_id) = body_id { self.tcx().hir_body(body_id).params } else { &[] };
978        for (i, ty) in decl.inputs.iter().enumerate() {
979            let ty = if let Some(param) = params.get(i)
980                && let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind
981            {
982                self.conv_ty_with_name(env, ty, ident.name)?
983            } else {
984                self.conv_ty(env, ty)?
985            };
986            inputs.push(ty);
987        }
988
989        let output = self.conv_fn_output(env, &decl.output)?;
990
991        Ok(rty::FnSig::new(safety, abi, requires.into(), inputs.into(), output))
992    }
993
994    fn conv_requires(
995        &mut self,
996        env: &mut Env,
997        requires: &fhir::Requires,
998    ) -> QueryResult<rty::Expr> {
999        if requires.params.is_empty() {
1000            self.conv_expr(env, &requires.pred)
1001        } else {
1002            env.push_layer(Layer::list(self.results(), 0, requires.params));
1003            let pred = self.conv_expr(env, &requires.pred)?;
1004            let sorts = env.pop_layer().into_bound_vars(self.genv())?;
1005            Ok(rty::Expr::forall(rty::Binder::bind_with_vars(pred, sorts)))
1006        }
1007    }
1008
1009    fn conv_ensures(
1010        &mut self,
1011        env: &mut Env,
1012        ensures: &fhir::Ensures,
1013    ) -> QueryResult<rty::Ensures> {
1014        match ensures {
1015            fhir::Ensures::Type(loc, ty) => {
1016                Ok(rty::Ensures::Type(env.lookup(loc).to_path(), self.conv_ty(env, ty)?))
1017            }
1018            fhir::Ensures::Pred(pred) => Ok(rty::Ensures::Pred(self.conv_expr(env, pred)?)),
1019        }
1020    }
1021
1022    fn conv_fn_output(
1023        &mut self,
1024        env: &mut Env,
1025        output: &fhir::FnOutput,
1026    ) -> QueryResult<rty::Binder<rty::FnOutput>> {
1027        env.push_layer(Layer::list(self.results(), 0, output.params));
1028
1029        let ret = self.conv_ty(env, &output.ret)?;
1030
1031        let ensures: List<rty::Ensures> = output
1032            .ensures
1033            .iter()
1034            .map(|ens| self.conv_ensures(env, ens))
1035            .try_collect()?;
1036        let output = rty::FnOutput::new(ret, ensures);
1037
1038        let vars = env.pop_layer().into_bound_vars(self.genv())?;
1039        Ok(rty::Binder::bind_with_vars(output, vars))
1040    }
1041
1042    fn conv_generic_bounds(
1043        &mut self,
1044        env: &mut Env,
1045        bounded_ty_span: Span,
1046        bounded_ty: rty::Ty,
1047        bounds: fhir::GenericBounds,
1048    ) -> QueryResult<Vec<rty::Clause>> {
1049        let mut clauses = vec![];
1050        for bound in bounds {
1051            match bound {
1052                fhir::GenericBound::Trait(poly_trait_ref) => {
1053                    match poly_trait_ref.modifiers {
1054                        fhir::TraitBoundModifier::None => {
1055                            self.conv_poly_trait_ref(
1056                                env,
1057                                bounded_ty_span,
1058                                &bounded_ty,
1059                                poly_trait_ref,
1060                                &mut clauses,
1061                            )?;
1062                        }
1063                        fhir::TraitBoundModifier::Maybe => {
1064                            // Maybe bounds are only supported for `?Sized`. The effect of the maybe
1065                            // bound is to relax the default which is `Sized` to not have the `Sized`
1066                            // bound, so we just skip it here.
1067                        }
1068                    }
1069                }
1070                fhir::GenericBound::Outlives(lft) => {
1071                    let re = self.conv_lifetime(env, *lft, bounded_ty_span);
1072                    clauses.push(rty::Clause::new(
1073                        List::empty(),
1074                        rty::ClauseKind::TypeOutlives(rty::OutlivesPredicate(
1075                            bounded_ty.clone(),
1076                            re,
1077                        )),
1078                    ));
1079                }
1080            }
1081        }
1082        Ok(clauses)
1083    }
1084
1085    /// Converts a `T: Trait<T0, ..., A0 = S0, ...>` bound
1086    fn conv_poly_trait_ref(
1087        &mut self,
1088        env: &mut Env,
1089        span: Span,
1090        bounded_ty: &rty::Ty,
1091        poly_trait_ref: &fhir::PolyTraitRef,
1092        clauses: &mut Vec<rty::Clause>,
1093    ) -> QueryResult {
1094        let generic_params = &poly_trait_ref.bound_generic_params;
1095        let layer =
1096            Layer::list(self.results(), generic_params.len() as u32, poly_trait_ref.refine_params);
1097        env.push_layer(layer);
1098
1099        let trait_id = poly_trait_ref.trait_def_id();
1100        let generics = self.genv().generics_of(trait_id)?;
1101        let trait_segment = poly_trait_ref.trait_ref.last_segment();
1102
1103        let self_param = generics.param_at(0, self.genv())?;
1104        let mut args = vec![
1105            self.try_to_ty_or_base(self_param.kind, span, bounded_ty)?
1106                .into(),
1107        ];
1108        self.conv_generic_args_into(env, trait_id, trait_segment, &mut args)?;
1109
1110        let vars = env.top_layer().to_bound_vars(self.genv())?;
1111        let poly_trait_ref = rty::Binder::bind_with_vars(
1112            rty::TraitRef { def_id: trait_id, args: args.into() },
1113            vars,
1114        );
1115
1116        clauses.push(
1117            poly_trait_ref
1118                .clone()
1119                .map(|trait_ref| {
1120                    rty::ClauseKind::Trait(rty::TraitPredicate { trait_ref: trait_ref.clone() })
1121                })
1122                .into(),
1123        );
1124
1125        for cstr in trait_segment.constraints {
1126            self.conv_assoc_item_constraint(env, &poly_trait_ref, cstr, clauses)?;
1127        }
1128
1129        env.pop_layer();
1130
1131        Ok(())
1132    }
1133
1134    fn conv_assoc_item_constraint(
1135        &mut self,
1136        env: &mut Env,
1137        poly_trait_ref: &rty::PolyTraitRef,
1138        constraint: &fhir::AssocItemConstraint,
1139        clauses: &mut Vec<rty::Clause>,
1140    ) -> QueryResult {
1141        let tcx = self.tcx();
1142
1143        let candidate = self.probe_single_bound_for_assoc_item(
1144            || traits::supertraits(tcx, poly_trait_ref.to_rustc(tcx)),
1145            constraint.ident,
1146        )?;
1147        let assoc_item_id = self
1148            .trait_defines_associated_item_named(
1149                candidate.def_id(),
1150                AssocTag::Type,
1151                constraint.ident,
1152            )
1153            .unwrap()
1154            .def_id;
1155
1156        let fhir::AssocItemConstraintKind::Equality { term } = &constraint.kind;
1157        let span = term.span;
1158        let term = self.conv_ty(env, term)?;
1159        let term = self.ty_to_subset_ty_ctor(span, &term)?;
1160
1161        let clause = poly_trait_ref
1162            .clone()
1163            .map(|trait_ref| {
1164                // TODO: when we support generic associated types, we need to also attach the associated generics here
1165                let args = trait_ref.args;
1166                let refine_args = List::empty();
1167                let projection_ty = rty::AliasTy { def_id: assoc_item_id, args, refine_args };
1168
1169                rty::ClauseKind::Projection(rty::ProjectionPredicate { projection_ty, term })
1170            })
1171            .into();
1172
1173        clauses.push(clause);
1174        Ok(())
1175    }
1176
1177    fn trait_defines_associated_item_named(
1178        &self,
1179        trait_def_id: DefId,
1180        assoc_tag: AssocTag,
1181        assoc_name: Ident,
1182    ) -> Option<&'tcx AssocItem> {
1183        self.tcx()
1184            .associated_items(trait_def_id)
1185            .find_by_ident_and_kind(self.tcx(), assoc_name, assoc_tag, trait_def_id)
1186    }
1187
1188    fn conv_ty_with_name(
1189        &mut self,
1190        env: &mut Env,
1191        ty: &fhir::Ty,
1192        name: Symbol,
1193    ) -> QueryResult<rty::Ty> {
1194        if let fhir::TyKind::BaseTy(bty) = &ty.kind {
1195            Ok(self.conv_bty(env, bty, Some(name))?.to_ty())
1196        } else {
1197            self.conv_ty(env, ty)
1198        }
1199    }
1200
1201    fn conv_ty(&mut self, env: &mut Env, ty: &fhir::Ty) -> QueryResult<rty::Ty> {
1202        match &ty.kind {
1203            fhir::TyKind::BaseTy(bty) => Ok(self.conv_bty(env, bty, None)?.to_ty()),
1204            fhir::TyKind::Indexed(bty, idx) => {
1205                let fhir_id = bty.fhir_id;
1206                let rty::TyOrCtor::Ctor(ty_ctor) = self.conv_bty(env, bty, None)? else {
1207                    return Err(self.emit(errors::RefinedUnrefinableType::new(bty.span)))?;
1208                };
1209                let idx = self.conv_expr(env, idx)?;
1210                self.0.insert_bty_sort(fhir_id, ty_ctor.sort());
1211                Ok(ty_ctor.replace_bound_reft(&idx))
1212            }
1213            fhir::TyKind::Exists(params, ty) => {
1214                let layer = Layer::list(self.results(), 0, params);
1215                env.push_layer(layer);
1216                let ty = self.conv_ty(env, ty)?;
1217                let sorts = env.pop_layer().into_bound_vars(self.genv())?;
1218                if sorts.is_empty() {
1219                    Ok(ty.shift_out_escaping(1))
1220                } else {
1221                    Ok(rty::Ty::exists(rty::Binder::bind_with_vars(ty, sorts)))
1222                }
1223            }
1224            fhir::TyKind::StrgRef(lft, loc, ty) => {
1225                let re = self.conv_lifetime(env, *lft, ty.span);
1226                let ty = self.conv_ty(env, ty)?;
1227                Ok(rty::Ty::strg_ref(re, env.lookup(loc).to_path(), ty))
1228            }
1229            fhir::TyKind::Ref(lft, fhir::MutTy { ty, mutbl }) => {
1230                let region = self.conv_lifetime(env, *lft, ty.span);
1231                Ok(rty::Ty::mk_ref(region, self.conv_ty(env, ty)?, *mutbl))
1232            }
1233            fhir::TyKind::BareFn(bare_fn) => {
1234                let mut env = Env::empty();
1235                env.push_layer(Layer::list(
1236                    self.results(),
1237                    bare_fn.generic_params.len() as u32,
1238                    &[],
1239                ));
1240                let fn_sig =
1241                    self.conv_fn_decl(&mut env, bare_fn.safety, bare_fn.abi, bare_fn.decl, None)?;
1242                let vars = bare_fn
1243                    .generic_params
1244                    .iter()
1245                    .map(|param| self.param_as_bound_var(param))
1246                    .try_collect()?;
1247                let poly_fn_sig = rty::Binder::bind_with_vars(fn_sig, vars);
1248                Ok(rty::BaseTy::FnPtr(poly_fn_sig).to_ty())
1249            }
1250            fhir::TyKind::Tuple(tys) => {
1251                let tys: List<rty::Ty> =
1252                    tys.iter().map(|ty| self.conv_ty(env, ty)).try_collect()?;
1253                Ok(rty::Ty::tuple(tys))
1254            }
1255            fhir::TyKind::Array(ty, len) => {
1256                Ok(rty::Ty::array(self.conv_ty(env, ty)?, self.conv_const_arg(*len)))
1257            }
1258            fhir::TyKind::Never => Ok(rty::Ty::never()),
1259            fhir::TyKind::Constr(pred, ty) => {
1260                let pred = self.conv_expr(env, pred)?;
1261                Ok(rty::Ty::constr(pred, self.conv_ty(env, ty)?))
1262            }
1263            fhir::TyKind::RawPtr(ty, mutability) => {
1264                Ok(rty::Ty::indexed(
1265                    rty::BaseTy::RawPtr(self.conv_ty(env, ty)?, *mutability),
1266                    rty::Expr::unit(),
1267                ))
1268            }
1269            fhir::TyKind::OpaqueDef(opaque_ty) => self.conv_opaque_def(env, opaque_ty, ty.span),
1270            fhir::TyKind::TraitObject(trait_bounds, lft, syn) => {
1271                if matches!(syn, rustc_ast::TraitObjectSyntax::Dyn) {
1272                    self.conv_trait_object(env, trait_bounds, *lft, ty.span)
1273                } else {
1274                    span_bug!(ty.span, "dyn* traits not supported yet")
1275                }
1276            }
1277            fhir::TyKind::Infer => Ok(rty::Ty::infer(self.next_type_vid())),
1278            fhir::TyKind::Err(err) => Err(QueryErr::Emitted(*err)),
1279        }
1280    }
1281
1282    /// Code adapted from <https://github.com/rust-lang/rust/blob/b5723af3457b9cd3795eeb97e9af2d34964854f2/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs#L2099>
1283    fn conv_opaque_def(
1284        &mut self,
1285        env: &mut Env,
1286        opaque_ty: &fhir::OpaqueTy,
1287        span: Span,
1288    ) -> QueryResult<rty::Ty> {
1289        let def_id = opaque_ty.def_id;
1290
1291        if P::HAS_ELABORATED_INFORMATION {
1292            let lifetimes = self.tcx().opaque_captured_lifetimes(def_id.local_id());
1293
1294            let generics = self.tcx().generics_of(opaque_ty.def_id);
1295
1296            let offset = generics.parent_count;
1297
1298            let args = rty::GenericArg::for_item(self.genv(), def_id.resolved_id(), |param, _| {
1299                if let Some(i) = (param.index as usize).checked_sub(offset) {
1300                    let (lifetime, _) = lifetimes[i];
1301                    rty::GenericArg::Lifetime(self.conv_resolved_lifetime(env, lifetime, span))
1302                } else {
1303                    rty::GenericArg::from_param_def(param)
1304                }
1305            })?;
1306            let reft_args = rty::RefineArgs::identity_for_item(self.genv(), def_id.resolved_id())?;
1307            let alias_ty = rty::AliasTy::new(def_id.resolved_id(), args, reft_args);
1308            Ok(rty::BaseTy::opaque(alias_ty).to_ty())
1309        } else {
1310            // During sortck we need to run conv on the opaque type to collect sorts for base types
1311            // in the opaque type's bounds. After sortck, we don't need to because opaque types are
1312            // converted as part of `genv.item_bounds`.
1313            self.conv_opaque_ty(opaque_ty)?;
1314
1315            // `RefineArgs::identity_for_item` uses `genv.refinement_generics_of` which in turn
1316            // requires `genv.check_wf`, so we simply return all empty here to avoid the circularity
1317            let alias_ty = rty::AliasTy::new(def_id.resolved_id(), List::empty(), List::empty());
1318            Ok(rty::BaseTy::opaque(alias_ty).to_ty())
1319        }
1320    }
1321
1322    fn conv_trait_object(
1323        &mut self,
1324        env: &mut Env,
1325        trait_bounds: &[fhir::PolyTraitRef],
1326        lifetime: fhir::Lifetime,
1327        span: Span,
1328    ) -> QueryResult<rty::Ty> {
1329        // We convert all the trait bounds into existential predicates. Some combinations won't yield
1330        // valid rust types (e.g., only one regular (non-auto) trait is allowed). We don't detect those
1331        // errors here, but that's fine because we should catch them when we check structural
1332        // compatibility with the unrefined rust type. We must be careful with producing predicates
1333        // in the same order that rustc does.
1334
1335        let mut bounds = vec![];
1336        let dummy_self = rty::Ty::trait_object_dummy_self();
1337        for trait_bound in trait_bounds.iter().rev() {
1338            self.conv_poly_trait_ref(env, trait_bound.span, &dummy_self, trait_bound, &mut bounds)?;
1339        }
1340
1341        // Separate trait bounds and projections bounds
1342        let mut trait_bounds = vec![];
1343        let mut projection_bounds = vec![];
1344        for pred in bounds {
1345            let bound_pred = pred.kind();
1346            let vars = bound_pred.vars().clone();
1347            match bound_pred.skip_binder() {
1348                rty::ClauseKind::Trait(trait_pred) => {
1349                    trait_bounds.push(rty::Binder::bind_with_vars(trait_pred.trait_ref, vars));
1350                }
1351                rty::ClauseKind::Projection(proj) => {
1352                    projection_bounds.push(rty::Binder::bind_with_vars(proj, vars));
1353                }
1354                rty::ClauseKind::RegionOutlives(_) => {}
1355                rty::ClauseKind::TypeOutlives(_) => {}
1356                rty::ClauseKind::ConstArgHasType(..) => {
1357                    bug!("did not expect {pred:?} clause in object bounds");
1358                }
1359            }
1360        }
1361
1362        // Separate between regular from auto traits
1363        let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = trait_bounds
1364            .into_iter()
1365            .partition(|trait_ref| self.tcx().trait_is_auto(trait_ref.def_id()));
1366
1367        // De-duplicate auto traits preserving order
1368        {
1369            let mut duplicates = FxHashSet::default();
1370            auto_traits.retain(|trait_ref| duplicates.insert(trait_ref.def_id()));
1371        }
1372
1373        let regular_trait_predicates = regular_traits.into_iter().map(|poly_trait_ref| {
1374            poly_trait_ref.map(|trait_ref| {
1375                // Remove dummy self
1376                let args = trait_ref.args.iter().skip(1).cloned().collect();
1377                rty::ExistentialPredicate::Trait(rty::ExistentialTraitRef {
1378                    def_id: trait_ref.def_id,
1379                    args,
1380                })
1381            })
1382        });
1383
1384        let auto_trait_predicates = auto_traits.into_iter().map(|trait_def| {
1385            rty::Binder::dummy(rty::ExistentialPredicate::AutoTrait(trait_def.def_id()))
1386        });
1387
1388        let existential_projections = projection_bounds.into_iter().map(|bound| {
1389            bound.map(|proj| {
1390                // Remove dummy self
1391                let args = proj.projection_ty.args.iter().skip(1).cloned().collect();
1392                rty::ExistentialPredicate::Projection(rty::ExistentialProjection {
1393                    def_id: proj.projection_ty.def_id,
1394                    args,
1395                    term: proj.term.clone(),
1396                })
1397            })
1398        });
1399
1400        let existential_predicates = {
1401            let mut v = regular_trait_predicates
1402                .chain(existential_projections)
1403                .chain(auto_trait_predicates)
1404                .collect_vec();
1405            v.sort_by(|a, b| {
1406                a.as_ref()
1407                    .skip_binder()
1408                    .stable_cmp(self.tcx(), b.as_ref().skip_binder())
1409            });
1410            List::from_vec(v)
1411        };
1412
1413        let region = self.conv_lifetime(env, lifetime, span);
1414        Ok(rty::Ty::dynamic(existential_predicates, region))
1415    }
1416
1417    pub(crate) fn conv_bty(
1418        &mut self,
1419        env: &mut Env,
1420        bty: &fhir::BaseTy,
1421        name: Option<Symbol>,
1422    ) -> QueryResult<rty::TyOrCtor> {
1423        match &bty.kind {
1424            fhir::BaseTyKind::Path(fhir::QPath::Resolved(qself, path)) => {
1425                self.conv_qpath(env, *qself, path, name)
1426            }
1427            fhir::BaseTyKind::Path(fhir::QPath::TypeRelative(qself, segment)) => {
1428                let qself_res =
1429                    if let Some(path) = qself.as_path() { path.res } else { fhir::Res::Err };
1430                let alias_ty = self
1431                    .conv_type_relative_path(env, qself.span, qself_res, segment)?
1432                    .shift_in_escaping(1);
1433                let bty = rty::BaseTy::Alias(rty::AliasKind::Projection, alias_ty);
1434                let sort = bty.sort();
1435                let ty = rty::Ty::indexed(bty, rty::Expr::nu());
1436                Ok(rty::TyOrCtor::Ctor(rty::Binder::bind_with_sort(ty, sort)))
1437            }
1438            fhir::BaseTyKind::Slice(ty) => {
1439                let bty = rty::BaseTy::Slice(self.conv_ty(env, ty)?).shift_in_escaping(1);
1440                let sort = bty.sort();
1441                let ty = rty::Ty::indexed(bty, rty::Expr::nu());
1442                Ok(rty::TyOrCtor::Ctor(rty::Binder::bind_with_sort(ty, sort)))
1443            }
1444            fhir::BaseTyKind::Err(err) => Err(QueryErr::Emitted(*err)),
1445        }
1446    }
1447
1448    fn conv_type_relative_path(
1449        &mut self,
1450        env: &mut Env,
1451        qself_span: Span,
1452        qself_res: fhir::Res,
1453        assoc_segment: &fhir::PathSegment,
1454    ) -> QueryResult<rty::AliasTy> {
1455        let tcx = self.tcx();
1456        let assoc_ident = assoc_segment.ident;
1457
1458        let bound = match qself_res {
1459            fhir::Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true } => {
1460                let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
1461                    // A cycle error occurred most likely (comment copied from rustc)
1462                    span_bug!(qself_span, "expected cycle error");
1463                };
1464
1465                self.probe_single_bound_for_assoc_item(
1466                    || {
1467                        traits::supertraits(
1468                            tcx,
1469                            ty::Binder::dummy(trait_ref.instantiate_identity()),
1470                        )
1471                    },
1472                    assoc_ident,
1473                )?
1474            }
1475            fhir::Res::Def(DefKind::TyParam, param_id)
1476            | fhir::Res::SelfTyParam { trait_: param_id } => {
1477                let predicates = self.probe_type_param_bounds(param_id, assoc_ident);
1478                self.probe_single_bound_for_assoc_item(
1479                    || {
1480                        traits::transitive_bounds_that_define_assoc_item(
1481                            tcx,
1482                            predicates.iter_identity_copied().filter_map(|(p, _)| {
1483                                Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))
1484                            }),
1485                            assoc_ident,
1486                        )
1487                    },
1488                    assoc_ident,
1489                )?
1490            }
1491            _ => Err(self.emit(errors::AssocTypeNotFound::new(assoc_ident)))?,
1492        };
1493
1494        let Some(trait_ref) = bound.no_bound_vars() else {
1495            // This is a programmer error and we should gracefully report it. It's triggered
1496            // by code like this
1497            // ```
1498            // trait Super<'a> { type Assoc; }
1499            // trait Child: for<'a> Super<'a> {}
1500            // fn foo<T: Child>(x: T::Assoc) {}
1501            // ```
1502            Err(self.emit(
1503                query_bug!("associated path with uninferred generic parameters")
1504                    .at(assoc_ident.span),
1505            ))?
1506        };
1507
1508        let trait_ref = trait_ref
1509            .lower(tcx)
1510            .map_err(|err| QueryErr::unsupported(trait_ref.def_id, err.into_err()))?
1511            .refine(&self.refiner()?)?;
1512
1513        let assoc_item = self
1514            .trait_defines_associated_item_named(trait_ref.def_id, AssocTag::Type, assoc_ident)
1515            .unwrap();
1516
1517        let assoc_id = assoc_item.def_id;
1518        let mut args = trait_ref.args.to_vec();
1519        self.conv_generic_args_into(env, assoc_id, assoc_segment, &mut args)?;
1520
1521        let args = List::from_vec(args);
1522        let refine_args = List::empty();
1523        let alias_ty = rty::AliasTy { args, refine_args, def_id: assoc_id };
1524        Ok(alias_ty)
1525    }
1526
1527    /// Return the generics of the containing owner item
1528    fn refiner(&self) -> QueryResult<Refiner<'genv, 'tcx>> {
1529        match self.owner() {
1530            FluxOwnerId::Rust(owner_id) => {
1531                let def_id = self.genv().maybe_extern_id(owner_id.def_id);
1532                Refiner::default_for_item(self.genv(), def_id.resolved_id())
1533            }
1534            FluxOwnerId::Flux(_) => Err(query_bug!("cannot refine types insicde flux item")),
1535        }
1536    }
1537
1538    fn probe_type_param_bounds(
1539        &self,
1540        param_id: DefId,
1541        assoc_ident: Ident,
1542    ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
1543        // We would like to do this computation on the resolved id for it to work with extern specs
1544        // but the `type_param_predicates` query is only defined for `LocalDefId`. This is mostly
1545        // fine because the worst that can happen is that we fail to infer a trait when using the
1546        // `T::Assoc` syntax and the user has to manually annotate it as `<T as Trait>::Assoc`
1547        // (or add it as a bound to the extern spec so it's returned by the query).
1548        let param_id = self
1549            .genv()
1550            .resolve_id(param_id)
1551            .as_maybe_extern()
1552            .unwrap()
1553            .local_id();
1554        match self.owner() {
1555            FluxOwnerId::Rust(owner_id) => {
1556                self.tcx()
1557                    .type_param_predicates((owner_id.def_id, param_id, assoc_ident))
1558            }
1559            FluxOwnerId::Flux(_) => ty::EarlyBinder::bind(&[]),
1560        }
1561    }
1562
1563    fn probe_single_bound_for_assoc_item<I>(
1564        &self,
1565        all_candidates: impl Fn() -> I,
1566        assoc_name: rustc_span::symbol::Ident,
1567    ) -> QueryResult<ty::PolyTraitRef<'tcx>>
1568    where
1569        I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
1570    {
1571        let mut matching_candidates = all_candidates().filter(|r| {
1572            self.trait_defines_associated_item_named(r.def_id(), AssocTag::Type, assoc_name)
1573                .is_some()
1574        });
1575
1576        let Some(bound) = matching_candidates.next() else {
1577            return Err(self.emit(errors::AssocTypeNotFound::new(assoc_name)))?;
1578        };
1579
1580        if matching_candidates.next().is_some() {
1581            self.report_ambiguous_assoc_ty(assoc_name.span, assoc_name)?;
1582        }
1583
1584        Ok(bound)
1585    }
1586
1587    fn conv_lifetime(&mut self, env: &Env, lft: fhir::Lifetime, span: Span) -> rty::Region {
1588        let res = match lft {
1589            fhir::Lifetime::Hole(_) => return rty::Region::ReVar(self.next_region_vid()),
1590            fhir::Lifetime::Resolved(res) => res,
1591        };
1592        self.conv_resolved_lifetime(env, res, span)
1593    }
1594
1595    fn conv_resolved_lifetime(&mut self, env: &Env, res: ResolvedArg, span: Span) -> rty::Region {
1596        let tcx = self.tcx();
1597        let lifetime_name = |def_id| tcx.item_name(def_id);
1598        match res {
1599            ResolvedArg::StaticLifetime => rty::ReStatic,
1600            ResolvedArg::EarlyBound(def_id) => {
1601                let index = self.genv().def_id_to_param_index(def_id.to_def_id());
1602                let name = lifetime_name(def_id.to_def_id());
1603                rty::ReEarlyParam(rty::EarlyParamRegion { index, name })
1604            }
1605            ResolvedArg::LateBound(_, index, def_id) => {
1606                let Some(depth) = env.depth().checked_sub(1) else {
1607                    span_bug!(span, "late-bound variable at depth 0")
1608                };
1609                let name = lifetime_name(def_id.to_def_id());
1610                let kind = rty::BoundRegionKind::Named(def_id.to_def_id(), name);
1611                let var = BoundVar::from_u32(index);
1612                let bound_region = rty::BoundRegion { var, kind };
1613                rty::ReBound(rty::DebruijnIndex::from_usize(depth), bound_region)
1614            }
1615            ResolvedArg::Free(scope, id) => {
1616                let name = lifetime_name(id.to_def_id());
1617                let kind = rty::LateParamRegionKind::Named(id.to_def_id(), name);
1618                rty::ReLateParam(rty::LateParamRegion { scope: scope.to_def_id(), kind })
1619            }
1620            ResolvedArg::Error(_) => bug!("lifetime resolved to an error"),
1621        }
1622    }
1623
1624    fn conv_const_arg(&mut self, cst: fhir::ConstArg) -> rty::Const {
1625        match cst.kind {
1626            fhir::ConstArgKind::Lit(lit) => rty::Const::from_usize(self.tcx(), lit),
1627            fhir::ConstArgKind::Param(def_id) => {
1628                rty::Const {
1629                    kind: rty::ConstKind::Param(def_id_to_param_const(self.genv(), def_id)),
1630                }
1631            }
1632            fhir::ConstArgKind::Infer => {
1633                rty::Const {
1634                    kind: rty::ConstKind::Infer(ty::InferConst::Var(self.next_const_vid())),
1635                }
1636            }
1637        }
1638    }
1639
1640    fn conv_qpath(
1641        &mut self,
1642        env: &mut Env,
1643        qself: Option<&fhir::Ty>,
1644        path: &fhir::Path,
1645        name: Option<Symbol>,
1646    ) -> QueryResult<rty::TyOrCtor> {
1647        let bty = match path.res {
1648            fhir::Res::PrimTy(prim_ty) => {
1649                self.check_prim_ty_generics(path, prim_ty)?;
1650                prim_ty_to_bty(prim_ty)
1651            }
1652            fhir::Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, did) => {
1653                let adt_def = self.genv().adt_def(did)?;
1654                let args = self.conv_generic_args(env, did, path.last_segment())?;
1655                rty::BaseTy::adt(adt_def, args)
1656            }
1657            fhir::Res::Def(DefKind::TyParam, def_id) => {
1658                let owner_id = ty_param_owner(self.genv(), def_id);
1659                let param_ty = def_id_to_param_ty(self.genv(), def_id);
1660                self.check_ty_param_generics(path, param_ty)?;
1661                let param = self
1662                    .genv()
1663                    .generics_of(owner_id)?
1664                    .param_at(param_ty.index as usize, self.genv())?;
1665                match param.kind {
1666                    rty::GenericParamDefKind::Type { .. } => {
1667                        return Ok(rty::TyOrCtor::Ty(rty::Ty::param(param_ty)));
1668                    }
1669                    rty::GenericParamDefKind::Base { .. } => rty::BaseTy::Param(param_ty),
1670                    _ => return Err(query_bug!("unexpected param kind")),
1671                }
1672            }
1673            fhir::Res::SelfTyParam { trait_ } => {
1674                self.check_self_ty_generics(path)?;
1675                let param = &self.genv().generics_of(trait_)?.own_params[0];
1676                match param.kind {
1677                    rty::GenericParamDefKind::Type { .. } => {
1678                        return Ok(rty::TyOrCtor::Ty(rty::Ty::param(rty::SELF_PARAM_TY)));
1679                    }
1680                    rty::GenericParamDefKind::Base { .. } => rty::BaseTy::Param(rty::SELF_PARAM_TY),
1681                    _ => return Err(query_bug!("unexpected param kind")),
1682                }
1683            }
1684            fhir::Res::SelfTyAlias { alias_to, .. } => {
1685                self.check_self_ty_generics(path)?;
1686                if P::EXPAND_TYPE_ALIASES {
1687                    return Ok(self.genv().type_of(alias_to)?.instantiate_identity());
1688                } else {
1689                    rty::BaseTy::Alias(
1690                        rty::AliasKind::Free,
1691                        rty::AliasTy {
1692                            def_id: alias_to,
1693                            args: List::empty(),
1694                            refine_args: List::empty(),
1695                        },
1696                    )
1697                }
1698            }
1699            fhir::Res::Def(DefKind::AssocTy, assoc_id) => {
1700                let trait_id = self.tcx().trait_of_item(assoc_id).unwrap();
1701
1702                let [.., trait_segment, assoc_segment] = path.segments else {
1703                    span_bug!(path.span, "expected at least two segments");
1704                };
1705
1706                let Some(qself) = qself else {
1707                    self.report_ambiguous_assoc_ty(path.span, assoc_segment.ident)?
1708                };
1709
1710                let trait_generics = self.genv().generics_of(trait_id)?;
1711                let qself =
1712                    self.conv_ty_to_generic_arg(env, &trait_generics.own_params[0], qself)?;
1713                let mut args = vec![qself];
1714                self.conv_generic_args_into(env, trait_id, trait_segment, &mut args)?;
1715                self.conv_generic_args_into(env, assoc_id, assoc_segment, &mut args)?;
1716                let args = List::from_vec(args);
1717
1718                let refine_args = List::empty();
1719                let alias_ty = rty::AliasTy { args, refine_args, def_id: assoc_id };
1720                rty::BaseTy::Alias(rty::AliasKind::Projection, alias_ty)
1721            }
1722            fhir::Res::Def(DefKind::TyAlias, def_id) => {
1723                self.check_refinement_generics(path, def_id)?;
1724                let args = self.conv_generic_args(env, def_id, path.last_segment())?;
1725                self.0.insert_path_args(path.fhir_id, args.clone());
1726                let refine_args = path
1727                    .refine
1728                    .iter()
1729                    .map(|expr| self.conv_expr(env, expr))
1730                    .try_collect_vec()?;
1731
1732                if P::EXPAND_TYPE_ALIASES {
1733                    let tcx = self.tcx();
1734                    return Ok(self
1735                        .genv()
1736                        .type_of(def_id)?
1737                        .instantiate(tcx, &args, &refine_args));
1738                } else {
1739                    rty::BaseTy::Alias(
1740                        rty::AliasKind::Free,
1741                        rty::AliasTy { def_id, args, refine_args: List::from(refine_args) },
1742                    )
1743                }
1744            }
1745            fhir::Res::Def(DefKind::ForeignTy, def_id) => {
1746                self.check_foreign_ty_generics(path)?;
1747                rty::BaseTy::Foreign(def_id)
1748            }
1749            fhir::Res::Def(kind, def_id) => self.report_expected_type(path.span, kind, def_id)?,
1750            fhir::Res::Err => {
1751                span_bug!(path.span, "unexpected resolution in conv_ty_ctor: {:?}", path.res)
1752            }
1753        };
1754        let sort = bty.sort();
1755        let bty = bty.shift_in_escaping(1);
1756        let kind = match name {
1757            Some(name) => BoundReftKind::Named(name),
1758            None => BoundReftKind::Annon,
1759        };
1760        let var = rty::BoundVariableKind::Refine(sort, rty::InferMode::EVar, kind);
1761        let ctor = rty::Binder::bind_with_vars(
1762            rty::Ty::indexed(bty, rty::Expr::nu()),
1763            List::singleton(var),
1764        );
1765        Ok(rty::TyOrCtor::Ctor(ctor))
1766    }
1767
1768    fn param_as_bound_var(
1769        &mut self,
1770        param: &fhir::GenericParam,
1771    ) -> QueryResult<rty::BoundVariableKind> {
1772        let def_id = param.def_id.resolved_id();
1773        let name = self.tcx().item_name(def_id);
1774        match param.kind {
1775            fhir::GenericParamKind::Lifetime => {
1776                Ok(rty::BoundVariableKind::Region(rty::BoundRegionKind::Named(def_id, name)))
1777            }
1778            fhir::GenericParamKind::Const { .. } | fhir::GenericParamKind::Type { .. } => {
1779                Err(query_bug!(def_id, "unsupported param kind `{:?}`", param.kind))
1780            }
1781        }
1782    }
1783
1784    fn conv_generic_args(
1785        &mut self,
1786        env: &mut Env,
1787        def_id: DefId,
1788        segment: &fhir::PathSegment,
1789    ) -> QueryResult<List<rty::GenericArg>> {
1790        let mut into = vec![];
1791        self.conv_generic_args_into(env, def_id, segment, &mut into)?;
1792        Ok(List::from(into))
1793    }
1794
1795    fn conv_generic_args_into(
1796        &mut self,
1797        env: &mut Env,
1798        def_id: DefId,
1799        segment: &fhir::PathSegment,
1800        into: &mut Vec<rty::GenericArg>,
1801    ) -> QueryResult {
1802        let generics = self.genv().generics_of(def_id)?;
1803
1804        self.check_generic_arg_count(&generics, def_id, segment)?;
1805
1806        let len = into.len();
1807        for (idx, arg) in segment.args.iter().enumerate() {
1808            let param = generics.param_at(idx + len, self.genv())?;
1809            match arg {
1810                fhir::GenericArg::Lifetime(lft) => {
1811                    into.push(rty::GenericArg::Lifetime(self.conv_lifetime(
1812                        env,
1813                        *lft,
1814                        segment.ident.span,
1815                    )));
1816                }
1817                fhir::GenericArg::Type(ty) => {
1818                    into.push(self.conv_ty_to_generic_arg(env, &param, ty)?);
1819                }
1820                fhir::GenericArg::Const(cst) => {
1821                    into.push(rty::GenericArg::Const(self.conv_const_arg(*cst)));
1822                }
1823                fhir::GenericArg::Infer => {
1824                    into.push(self.conv_generic_arg_hole(env, param, segment.ident.span)?);
1825                }
1826            }
1827        }
1828        self.fill_generic_args_defaults(def_id, into)
1829    }
1830
1831    fn conv_generic_arg_hole(
1832        &mut self,
1833        env: &mut Env,
1834        param: rty::GenericParamDef,
1835        span: Span,
1836    ) -> QueryResult<rty::GenericArg> {
1837        match param.kind {
1838            rty::GenericParamDefKind::Type { .. } | rty::GenericParamDefKind::Base { .. } => {
1839                let ty = fhir::Ty { kind: fhir::TyKind::Infer, span };
1840                Ok(self.conv_ty_to_generic_arg(env, &param, &ty)?)
1841            }
1842            rty::GenericParamDefKind::Const { .. } => {
1843                let cst = fhir::ConstArg { kind: fhir::ConstArgKind::Infer, span };
1844                Ok(rty::GenericArg::Const(self.conv_const_arg(cst)))
1845            }
1846            rty::GenericParamDefKind::Lifetime => {
1847                let re = rty::Region::ReVar(self.next_region_vid());
1848                Ok(rty::GenericArg::Lifetime(re))
1849            }
1850        }
1851    }
1852
1853    fn check_generic_arg_count(
1854        &mut self,
1855        generics: &rty::Generics,
1856        def_id: DefId,
1857        segment: &fhir::PathSegment,
1858    ) -> QueryResult {
1859        let found = segment.args.len();
1860        let mut param_count = generics.own_params.len();
1861
1862        // The self parameter is not provided explicitly in the path so we skip it
1863        if let DefKind::Trait = self.genv().def_kind(def_id) {
1864            param_count -= 1;
1865        }
1866
1867        let min = param_count - generics.own_default_count();
1868        let max = param_count;
1869        if min == max && found != min {
1870            Err(self.emit(errors::GenericArgCountMismatch::new(
1871                self.genv(),
1872                def_id,
1873                segment,
1874                min,
1875            )))?;
1876        }
1877        if found < min {
1878            Err(self.emit(errors::TooFewGenericArgs::new(self.genv(), def_id, segment, min)))?;
1879        }
1880        if found > max {
1881            Err(self.emit(errors::TooManyGenericArgs::new(self.genv(), def_id, segment, min)))?;
1882        }
1883        Ok(())
1884    }
1885
1886    fn fill_generic_args_defaults(
1887        &mut self,
1888        def_id: DefId,
1889        into: &mut Vec<rty::GenericArg>,
1890    ) -> QueryResult {
1891        let generics = self.genv().generics_of(def_id)?;
1892        for param in generics.own_params.iter().skip(into.len()) {
1893            debug_assert!(matches!(
1894                param.kind,
1895                rty::GenericParamDefKind::Type { has_default: true }
1896                    | rty::GenericParamDefKind::Base { has_default: true }
1897            ));
1898            let span = self.tcx().def_span(param.def_id);
1899            // FIXME(nilehmann) we already know whether this is a type or a constructor so we could
1900            // directly check if the constructor returns a subset type.
1901            let ty = self
1902                .genv()
1903                .type_of(param.def_id)?
1904                .instantiate(self.tcx(), into, &[])
1905                .to_ty();
1906            into.push(self.try_to_ty_or_base(param.kind, span, &ty)?.into());
1907        }
1908        Ok(())
1909    }
1910
1911    fn conv_ty_to_generic_arg(
1912        &mut self,
1913        env: &mut Env,
1914        param: &rty::GenericParamDef,
1915        ty: &fhir::Ty,
1916    ) -> QueryResult<rty::GenericArg> {
1917        let rty_ty = self.conv_ty(env, ty)?;
1918        Ok(self.try_to_ty_or_base(param.kind, ty.span, &rty_ty)?.into())
1919    }
1920
1921    fn try_to_ty_or_base(
1922        &mut self,
1923        kind: rty::GenericParamDefKind,
1924        span: Span,
1925        ty: &rty::Ty,
1926    ) -> QueryResult<rty::TyOrBase> {
1927        match kind {
1928            rty::GenericParamDefKind::Type { .. } => Ok(rty::TyOrBase::Ty(ty.clone())),
1929            rty::GenericParamDefKind::Base { .. } => {
1930                Ok(rty::TyOrBase::Base(self.ty_to_subset_ty_ctor(span, ty)?))
1931            }
1932            _ => span_bug!(span, "unexpected param kind `{kind:?}`"),
1933        }
1934    }
1935
1936    fn ty_to_subset_ty_ctor(&mut self, span: Span, ty: &rty::Ty) -> QueryResult<rty::SubsetTyCtor> {
1937        let ctor = if let rty::TyKind::Infer(vid) = ty.kind() {
1938            // do not generate sort holes for dummy self types
1939            let sort_vid =
1940                if vid.as_u32() == 0 { rty::SortVid::from_u32(0) } else { self.next_sort_vid() };
1941            rty::SubsetTyCtor::bind_with_sort(
1942                rty::SubsetTy::trivial(rty::BaseTy::Infer(*vid), rty::Expr::nu()),
1943                rty::Sort::Infer(rty::SortInfer::SortVar(sort_vid)),
1944            )
1945        } else {
1946            ty.shallow_canonicalize()
1947                .as_ty_or_base()
1948                .as_base()
1949                .ok_or_else(|| self.emit(errors::InvalidBaseInstance::new(span)))?
1950        };
1951        Ok(ctor)
1952    }
1953
1954    #[track_caller]
1955    fn emit(&self, err: impl Diagnostic<'genv>) -> ErrorGuaranteed {
1956        self.genv().sess().emit_err(err)
1957    }
1958
1959    fn report_ambiguous_assoc_ty(
1960        &self,
1961        span: Span,
1962        assoc_name: Ident,
1963    ) -> Result<!, ErrorGuaranteed> {
1964        Err(self.emit(errors::AmbiguousAssocType { span, name: assoc_name }))?
1965    }
1966
1967    fn report_expected_type(
1968        &self,
1969        span: Span,
1970        kind: DefKind,
1971        def_id: DefId,
1972    ) -> Result<!, ErrorGuaranteed> {
1973        Err(self.emit(errors::ExpectedType {
1974            span,
1975            def_descr: self.tcx().def_kind_descr(kind, def_id),
1976            name: self.tcx().def_path_str(def_id),
1977        }))?
1978    }
1979}
1980
1981/// Check generic params for types
1982impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
1983    fn check_refinement_generics(&mut self, path: &fhir::Path, def_id: DefId) -> QueryResult {
1984        let generics = self.genv().refinement_generics_of(def_id)?;
1985        if generics.count() != path.refine.len() {
1986            let err = errors::RefineArgMismatch {
1987                span: path.span,
1988                expected: generics.count(),
1989                found: path.refine.len(),
1990                kind: self.tcx().def_descr(def_id),
1991            };
1992            Err(self.emit(err))?;
1993        }
1994        Ok(())
1995    }
1996
1997    fn check_prim_ty_generics(
1998        &mut self,
1999        path: &fhir::Path<'_>,
2000        prim_ty: rustc_hir::PrimTy,
2001    ) -> QueryResult {
2002        if !path.last_segment().args.is_empty() {
2003            let err = errors::GenericsOnPrimTy { span: path.span, name: prim_ty.name_str() };
2004            Err(self.emit(err))?;
2005        }
2006        Ok(())
2007    }
2008
2009    fn check_ty_param_generics(
2010        &mut self,
2011        path: &fhir::Path<'_>,
2012        param_ty: rty::ParamTy,
2013    ) -> QueryResult {
2014        if !path.last_segment().args.is_empty() {
2015            let err = errors::GenericsOnTyParam { span: path.span, name: param_ty.name };
2016            Err(self.emit(err))?;
2017        }
2018        Ok(())
2019    }
2020
2021    fn check_self_ty_generics(&mut self, path: &fhir::Path<'_>) -> QueryResult {
2022        if !path.last_segment().args.is_empty() {
2023            let err = errors::GenericsOnSelfTy { span: path.span };
2024            Err(self.emit(err))?;
2025        }
2026        Ok(())
2027    }
2028
2029    fn check_foreign_ty_generics(&mut self, path: &fhir::Path<'_>) -> QueryResult {
2030        if !path.last_segment().args.is_empty() {
2031            let err = errors::GenericsOnForeignTy { span: path.span };
2032            Err(self.emit(err))?;
2033        }
2034        Ok(())
2035    }
2036}
2037
2038fn prim_ty_to_bty(prim_ty: rustc_hir::PrimTy) -> rty::BaseTy {
2039    match prim_ty {
2040        rustc_hir::PrimTy::Int(int_ty) => rty::BaseTy::Int(rustc_middle::ty::int_ty(int_ty)),
2041        rustc_hir::PrimTy::Uint(uint_ty) => rty::BaseTy::Uint(rustc_middle::ty::uint_ty(uint_ty)),
2042        rustc_hir::PrimTy::Float(float_ty) => {
2043            rty::BaseTy::Float(rustc_middle::ty::float_ty(float_ty))
2044        }
2045        rustc_hir::PrimTy::Str => rty::BaseTy::Str,
2046        rustc_hir::PrimTy::Bool => rty::BaseTy::Bool,
2047        rustc_hir::PrimTy::Char => rty::BaseTy::Char,
2048    }
2049}
2050
2051/// Conversion of expressions
2052impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
2053    fn conv_lit(&self, lit: fhir::Lit, fhir_id: FhirId, span: Span) -> QueryResult<rty::Constant> {
2054        match lit {
2055            fhir::Lit::Int(n) => {
2056                let sort = self.results().node_sort(fhir_id);
2057                if let rty::Sort::BitVec(bvsize) = sort {
2058                    if let rty::BvSize::Fixed(size) = bvsize
2059                        && (n == 0 || n.ilog2() < size)
2060                    {
2061                        Ok(rty::Constant::BitVec(n, size))
2062                    } else {
2063                        Err(self.emit(errors::InvalidBitVectorConstant::new(span, sort)))?
2064                    }
2065                } else {
2066                    Ok(rty::Constant::from(n))
2067                }
2068            }
2069            fhir::Lit::Real(r) => Ok(rty::Constant::Real(rty::Real(r))),
2070            fhir::Lit::Bool(b) => Ok(rty::Constant::from(b)),
2071            fhir::Lit::Str(s) => Ok(rty::Constant::from(s)),
2072            fhir::Lit::Char(c) => Ok(rty::Constant::from(c)),
2073        }
2074    }
2075
2076    fn conv_expr(&mut self, env: &mut Env, expr: &fhir::Expr) -> QueryResult<rty::Expr> {
2077        let fhir_id = expr.fhir_id;
2078        let espan = ESpan::new(expr.span);
2079        let expr = match expr.kind {
2080            fhir::ExprKind::Var(var, _) => {
2081                match var.res {
2082                    ExprRes::Param(..) => env.lookup(&var).to_expr(),
2083                    ExprRes::Const(def_id) => {
2084                        if P::HAS_ELABORATED_INFORMATION {
2085                            rty::Expr::const_def_id(def_id).at(espan)
2086                        } else {
2087                            let Some(sort) = self.genv().sort_of_def_id(def_id)? else {
2088                                span_bug!(expr.span, "missing sort for const {def_id:?}");
2089                            };
2090                            rty::Expr::hole(rty::HoleKind::Expr(sort)).at(espan)
2091                        }
2092                    }
2093                    ExprRes::Variant(variant_def_id) => {
2094                        let enum_def_id = self.tcx().parent(variant_def_id);
2095                        let idx = variant_idx(self.tcx(), variant_def_id);
2096                        rty::Expr::ctor_enum(enum_def_id, idx)
2097                    }
2098                    ExprRes::ConstGeneric(def_id) => {
2099                        rty::Expr::const_generic(def_id_to_param_const(self.genv(), def_id))
2100                            .at(espan)
2101                    }
2102                    ExprRes::NumConst(num) => {
2103                        rty::Expr::constant(rty::Constant::from(num)).at(espan)
2104                    }
2105                    ExprRes::GlobalFunc(..) => {
2106                        Err(self.emit(errors::InvalidPosition { span: expr.span }))?
2107                    }
2108                    ExprRes::Ctor(..) => {
2109                        span_bug!(var.span, "unexpected constructor in var position")
2110                    }
2111                }
2112            }
2113            fhir::ExprKind::Literal(lit) => {
2114                rty::Expr::constant(self.conv_lit(lit, fhir_id, expr.span)?).at(espan)
2115            }
2116            fhir::ExprKind::BinaryOp(op, e1, e2) => {
2117                rty::Expr::binary_op(
2118                    self.conv_bin_op(op, expr.fhir_id),
2119                    self.conv_expr(env, e1)?,
2120                    self.conv_expr(env, e2)?,
2121                )
2122                .at(espan)
2123            }
2124            fhir::ExprKind::UnaryOp(op, e) => {
2125                rty::Expr::unary_op(conv_un_op(op), self.conv_expr(env, e)?).at(espan)
2126            }
2127
2128            fhir::ExprKind::PrimApp(op, e1, e2) => {
2129                rty::Expr::prim_val(
2130                    self.conv_bin_op(op, expr.fhir_id),
2131                    self.conv_expr(env, e1)?,
2132                    self.conv_expr(env, e2)?,
2133                )
2134                .at(espan)
2135            }
2136            fhir::ExprKind::App(func, args) => {
2137                rty::Expr::app(self.conv_func(env, &func), self.conv_exprs(env, args)?).at(espan)
2138            }
2139            fhir::ExprKind::Alias(alias, args) => {
2140                let args = args
2141                    .iter()
2142                    .map(|arg| self.conv_expr(env, arg))
2143                    .try_collect()?;
2144                let alias = self.conv_alias_reft(env, expr.fhir_id, &alias)?;
2145                rty::Expr::alias(alias, args).at(espan)
2146            }
2147            fhir::ExprKind::IfThenElse(p, e1, e2) => {
2148                rty::Expr::ite(
2149                    self.conv_expr(env, p)?,
2150                    self.conv_expr(env, e1)?,
2151                    self.conv_expr(env, e2)?,
2152                )
2153                .at(espan)
2154            }
2155            fhir::ExprKind::Dot(base, _) => {
2156                let proj = self.results().field_proj(fhir_id);
2157                rty::Expr::field_proj(self.conv_expr(env, base)?, proj)
2158            }
2159            fhir::ExprKind::Abs(params, body) => {
2160                env.push_layer(Layer::list(self.results(), 0, params));
2161                let pred = self.conv_expr(env, body)?;
2162                let vars = env.pop_layer().into_bound_vars(self.genv())?;
2163                let output = self.results().node_sort(body.fhir_id);
2164                let lam = rty::Lambda::bind_with_vars(pred, vars, output);
2165                rty::Expr::abs(lam)
2166            }
2167            fhir::ExprKind::Block(decls, body) => {
2168                for decl in decls {
2169                    env.push_layer(Layer::list(self.results(), 0, &[decl.param]));
2170                }
2171                let mut body = self.conv_expr(env, body)?;
2172                for decl in decls.iter().rev() {
2173                    let vars = env.pop_layer().into_bound_vars(self.genv())?;
2174                    let init = self.conv_expr(env, &decl.init)?;
2175                    body = rty::Expr::let_(init, rty::Binder::bind_with_vars(body, vars));
2176                }
2177                body
2178            }
2179            fhir::ExprKind::BoundedQuant(kind, param, rng, body) => {
2180                env.push_layer(Layer::list(self.results(), 0, &[param]));
2181                let pred = self.conv_expr(env, body)?;
2182                let vars = env.pop_layer().into_bound_vars(self.genv())?;
2183                let body = rty::Binder::bind_with_vars(pred, vars);
2184                rty::Expr::bounded_quant(kind, rng, body)
2185            }
2186            fhir::ExprKind::Record(flds) => {
2187                let def_id = self.results().record_ctor(expr.fhir_id);
2188                let flds = flds
2189                    .iter()
2190                    .map(|expr| self.conv_expr(env, expr))
2191                    .try_collect()?;
2192                rty::Expr::ctor_struct(def_id, flds)
2193            }
2194            fhir::ExprKind::Constructor(path, exprs, spread) => {
2195                let def_id = if let Some(path) = path {
2196                    match path.res {
2197                        ExprRes::Ctor(def_id) => def_id,
2198                        _ => span_bug!(path.span, "unexpected path in constructor"),
2199                    }
2200                } else {
2201                    self.results().record_ctor(expr.fhir_id)
2202                };
2203                let assns = self.conv_constructor_exprs(def_id, env, exprs, &spread)?;
2204                rty::Expr::ctor_struct(def_id, assns)
2205            }
2206            fhir::ExprKind::Err(err) => Err(QueryErr::Emitted(err))?,
2207        };
2208        Ok(self.add_coercions(expr, fhir_id))
2209    }
2210
2211    fn conv_constructor_exprs(
2212        &mut self,
2213        struct_def_id: DefId,
2214        env: &mut Env,
2215        exprs: &[fhir::FieldExpr],
2216        spread: &Option<&fhir::Spread>,
2217    ) -> QueryResult<List<rty::Expr>> {
2218        if !P::HAS_ELABORATED_INFORMATION {
2219            return Ok(List::default());
2220        };
2221        let adt_def = self.genv().adt_sort_def_of(struct_def_id)?;
2222        let struct_variant = adt_def.struct_variant();
2223        let spread = spread
2224            .map(|spread| self.conv_expr(env, &spread.expr))
2225            .transpose()?;
2226        let field_exprs_by_name: FxIndexMap<Symbol, &fhir::FieldExpr> =
2227            exprs.iter().map(|e| (e.ident.name, e)).collect();
2228        let mut assns = Vec::new();
2229        for (idx, field_name) in struct_variant.field_names().iter().enumerate() {
2230            if let Some(field_expr) = field_exprs_by_name.get(field_name) {
2231                assns.push(self.conv_expr(env, &field_expr.expr)?);
2232            } else if let Some(spread) = &spread {
2233                let proj = rty::FieldProj::Adt { def_id: struct_def_id, field: idx as u32 };
2234                assns.push(rty::Expr::field_proj(spread, proj));
2235            }
2236        }
2237        Ok(List::from_vec(assns))
2238    }
2239
2240    fn conv_exprs(&mut self, env: &mut Env, exprs: &[fhir::Expr]) -> QueryResult<List<rty::Expr>> {
2241        exprs.iter().map(|e| self.conv_expr(env, e)).collect()
2242    }
2243
2244    fn conv_bin_op(&self, op: fhir::BinOp, fhir_id: FhirId) -> rty::BinOp {
2245        match op {
2246            fhir::BinOp::Iff => rty::BinOp::Iff,
2247            fhir::BinOp::Imp => rty::BinOp::Imp,
2248            fhir::BinOp::Or => rty::BinOp::Or,
2249            fhir::BinOp::And => rty::BinOp::And,
2250            fhir::BinOp::Eq => rty::BinOp::Eq,
2251            fhir::BinOp::Ne => rty::BinOp::Ne,
2252            fhir::BinOp::Gt => rty::BinOp::Gt(self.results().bin_op_sort(fhir_id)),
2253            fhir::BinOp::Ge => rty::BinOp::Ge(self.results().bin_op_sort(fhir_id)),
2254            fhir::BinOp::Lt => rty::BinOp::Lt(self.results().bin_op_sort(fhir_id)),
2255            fhir::BinOp::Le => rty::BinOp::Le(self.results().bin_op_sort(fhir_id)),
2256            fhir::BinOp::Add => rty::BinOp::Add(self.results().bin_op_sort(fhir_id)),
2257            fhir::BinOp::Sub => rty::BinOp::Sub(self.results().bin_op_sort(fhir_id)),
2258            fhir::BinOp::Mul => rty::BinOp::Mul(self.results().bin_op_sort(fhir_id)),
2259            fhir::BinOp::Mod => rty::BinOp::Mod(self.results().bin_op_sort(fhir_id)),
2260            fhir::BinOp::Div => rty::BinOp::Div(self.results().bin_op_sort(fhir_id)),
2261            fhir::BinOp::BitAnd => rty::BinOp::BitAnd,
2262            fhir::BinOp::BitOr => rty::BinOp::BitOr,
2263            fhir::BinOp::BitShl => rty::BinOp::BitShl,
2264            fhir::BinOp::BitShr => rty::BinOp::BitShr,
2265        }
2266    }
2267
2268    fn add_coercions(&self, mut expr: rty::Expr, fhir_id: FhirId) -> rty::Expr {
2269        let span = expr.span();
2270        for coercion in self.results().coercions_for(fhir_id) {
2271            expr = match *coercion {
2272                rty::Coercion::Inject(def_id) => {
2273                    rty::Expr::ctor_struct(def_id, List::singleton(expr)).at_opt(span)
2274                }
2275                rty::Coercion::Project(def_id) => {
2276                    rty::Expr::field_proj(expr, rty::FieldProj::Adt { def_id, field: 0 })
2277                        .at_opt(span)
2278                }
2279            };
2280        }
2281        expr
2282    }
2283
2284    fn conv_spec_func(
2285        func: &fhir::SpecFuncKind,
2286    ) -> Result<rty::SpecFuncKind, rty::InternalFuncKind> {
2287        match func {
2288            fhir::SpecFuncKind::Thy(thy_func) => Ok(rty::SpecFuncKind::Thy(*thy_func)),
2289            fhir::SpecFuncKind::Uif(flux_id) => Ok(rty::SpecFuncKind::Uif(*flux_id)),
2290            fhir::SpecFuncKind::Def(flux_id) => Ok(rty::SpecFuncKind::Def(*flux_id)),
2291            fhir::SpecFuncKind::CharToInt => Err(rty::InternalFuncKind::CharToInt),
2292        }
2293    }
2294
2295    fn conv_func(&self, env: &Env, func: &fhir::PathExpr) -> rty::Expr {
2296        let expr = match func.res {
2297            ExprRes::Param(..) => env.lookup(func).to_expr(),
2298            ExprRes::GlobalFunc(kind) => {
2299                match Self::conv_spec_func(&kind) {
2300                    Ok(func) => rty::Expr::global_func(func),
2301                    Err(func) => rty::Expr::internal_func(func),
2302                }
2303            }
2304            _ => span_bug!(func.span, "unexpected path in function position"),
2305        };
2306        self.add_coercions(expr, func.fhir_id)
2307    }
2308
2309    fn conv_alias_reft(
2310        &mut self,
2311        env: &mut Env,
2312        fhir_id: FhirId,
2313        alias: &fhir::AliasReft,
2314    ) -> QueryResult<rty::AliasReft> {
2315        let fhir::Res::Def(DefKind::Trait, trait_id) = alias.path.res else {
2316            span_bug!(alias.path.span, "expected trait")
2317        };
2318        let trait_segment = alias.path.last_segment();
2319
2320        let generics = self.genv().generics_of(trait_id)?;
2321        let self_ty =
2322            self.conv_ty_to_generic_arg(env, &generics.param_at(0, self.genv())?, alias.qself)?;
2323        let mut generic_args = vec![self_ty];
2324        self.conv_generic_args_into(env, trait_id, trait_segment, &mut generic_args)?;
2325
2326        let Some(assoc_id) = self.genv().assoc_refinements_of(trait_id)?.find(alias.name) else {
2327            return Err(self.emit(errors::InvalidAssocReft::new(
2328                alias.path.span,
2329                alias.name,
2330                format!("{:?}", alias.path),
2331            )))?;
2332        };
2333
2334        let alias_reft = rty::AliasReft { assoc_id, args: List::from_vec(generic_args) };
2335
2336        let fsort = alias_reft.fsort(self.genv())?;
2337        self.0.insert_alias_reft_sort(fhir_id, fsort);
2338        Ok(alias_reft)
2339    }
2340
2341    pub(crate) fn conv_invariants(
2342        &mut self,
2343        adt_id: MaybeExternId,
2344        params: &[fhir::RefineParam],
2345        invariants: &[fhir::Expr],
2346    ) -> QueryResult<Vec<rty::Invariant>> {
2347        let mut env = Env::new(&[]);
2348        env.push_layer(Layer::coalesce(self.results(), adt_id.resolved_id(), params));
2349        invariants
2350            .iter()
2351            .map(|invariant| self.conv_invariant(&mut env, invariant))
2352            .collect()
2353    }
2354
2355    fn conv_invariant(
2356        &mut self,
2357        env: &mut Env,
2358        invariant: &fhir::Expr,
2359    ) -> QueryResult<rty::Invariant> {
2360        Ok(rty::Invariant::new(rty::Binder::bind_with_vars(
2361            self.conv_expr(env, invariant)?,
2362            env.top_layer().to_bound_vars(self.genv())?,
2363        )))
2364    }
2365}
2366
2367impl Env {
2368    fn new(early_params: &[fhir::RefineParam]) -> Self {
2369        let early_params = early_params
2370            .iter()
2371            .map(|param| (param.id, param.name))
2372            .collect();
2373        Self { layers: vec![], early_params }
2374    }
2375
2376    pub(crate) fn empty() -> Self {
2377        Self { layers: vec![], early_params: Default::default() }
2378    }
2379
2380    fn depth(&self) -> usize {
2381        self.layers.len()
2382    }
2383
2384    fn push_layer(&mut self, layer: Layer) {
2385        self.layers.push(layer);
2386    }
2387
2388    fn pop_layer(&mut self) -> Layer {
2389        self.layers.pop().expect("bottom of layer stack")
2390    }
2391
2392    fn top_layer(&self) -> &Layer {
2393        self.layers.last().expect("bottom of layer stack")
2394    }
2395
2396    fn lookup(&self, var: &fhir::PathExpr) -> LookupResult<'_> {
2397        let (_, id) = var.res.expect_param();
2398        for (i, layer) in self.layers.iter().rev().enumerate() {
2399            if let Some((idx, entry)) = layer.get(id) {
2400                let debruijn = DebruijnIndex::from_usize(i);
2401                let kind = LookupResultKind::Bound {
2402                    debruijn,
2403                    entry,
2404                    index: idx as u32,
2405                    kind: layer.kind,
2406                };
2407                return LookupResult { var_span: var.span, kind };
2408            }
2409        }
2410        if let Some((idx, _, name)) = self.early_params.get_full(&id) {
2411            LookupResult {
2412                var_span: var.span,
2413                kind: LookupResultKind::EarlyParam { index: idx as u32, name: *name },
2414            }
2415        } else {
2416            span_bug!(var.span, "no entry found for key: `{:?}`", id);
2417        }
2418    }
2419
2420    fn to_early_param_args(&self) -> List<rty::Expr> {
2421        self.early_params
2422            .iter()
2423            .enumerate()
2424            .map(|(idx, (_, name))| rty::Expr::early_param(idx as u32, *name))
2425            .collect()
2426    }
2427}
2428
2429impl Layer {
2430    fn new<R: WfckResultsProvider>(
2431        results: &R,
2432        params: &[fhir::RefineParam],
2433        kind: LayerKind,
2434    ) -> Self {
2435        let map = params
2436            .iter()
2437            .map(|param| {
2438                let sort = results.param_sort(param);
2439                let infer_mode = rty::InferMode::from_param_kind(param.kind);
2440                let entry = ParamEntry::new(sort, infer_mode, param.name);
2441                (param.id, entry)
2442            })
2443            .collect();
2444        Self { map, kind }
2445    }
2446
2447    fn list<R: WfckResultsProvider>(
2448        results: &R,
2449        bound_regions: u32,
2450        params: &[fhir::RefineParam],
2451    ) -> Self {
2452        Self::new(results, params, LayerKind::List { bound_regions })
2453    }
2454
2455    fn coalesce<R: WfckResultsProvider>(
2456        results: &R,
2457        def_id: DefId,
2458        params: &[fhir::RefineParam],
2459    ) -> Self {
2460        Self::new(results, params, LayerKind::Coalesce(def_id))
2461    }
2462
2463    fn get(&self, name: impl Borrow<fhir::ParamId>) -> Option<(usize, &ParamEntry)> {
2464        let (idx, _, entry) = self.map.get_full(name.borrow())?;
2465        Some((idx, entry))
2466    }
2467
2468    fn into_bound_vars(self, genv: GlobalEnv) -> QueryResult<List<rty::BoundVariableKind>> {
2469        match self.kind {
2470            LayerKind::List { .. } => {
2471                Ok(self
2472                    .into_iter()
2473                    .map(|entry| {
2474                        let kind = rty::BoundReftKind::Named(entry.name);
2475                        rty::BoundVariableKind::Refine(entry.sort, entry.mode, kind)
2476                    })
2477                    .collect())
2478            }
2479            LayerKind::Coalesce(def_id) => {
2480                let sort_def = genv.adt_sort_def_of(def_id)?;
2481                let args = sort_def.identity_args();
2482                let ctor = rty::SortCtor::Adt(sort_def);
2483                Ok(List::singleton(rty::BoundVariableKind::Refine(
2484                    rty::Sort::App(ctor, args),
2485                    rty::InferMode::EVar,
2486                    rty::BoundReftKind::Annon,
2487                )))
2488            }
2489        }
2490    }
2491
2492    fn to_bound_vars(&self, genv: GlobalEnv) -> QueryResult<List<rty::BoundVariableKind>> {
2493        self.clone().into_bound_vars(genv)
2494    }
2495
2496    fn into_iter(self) -> impl Iterator<Item = ParamEntry> {
2497        self.map.into_values()
2498    }
2499}
2500
2501impl ParamEntry {
2502    fn new(sort: rty::Sort, mode: fhir::InferMode, name: Symbol) -> Self {
2503        ParamEntry { name, sort, mode }
2504    }
2505}
2506
2507impl LookupResult<'_> {
2508    fn to_expr(&self) -> rty::Expr {
2509        let espan = ESpan::new(self.var_span);
2510        match &self.kind {
2511            LookupResultKind::Bound { debruijn, entry: ParamEntry { name, .. }, kind, index } => {
2512                match *kind {
2513                    LayerKind::List { bound_regions } => {
2514                        rty::Expr::bvar(
2515                            *debruijn,
2516                            BoundVar::from_u32(bound_regions + *index),
2517                            rty::BoundReftKind::Named(*name),
2518                        )
2519                        .at(espan)
2520                    }
2521                    LayerKind::Coalesce(def_id) => {
2522                        let var =
2523                            rty::Expr::bvar(*debruijn, BoundVar::ZERO, rty::BoundReftKind::Annon)
2524                                .at(espan);
2525                        rty::Expr::field_proj(var, rty::FieldProj::Adt { def_id, field: *index })
2526                            .at(espan)
2527                    }
2528                }
2529            }
2530            &LookupResultKind::EarlyParam { index, name, .. } => {
2531                rty::Expr::early_param(index, name).at(espan)
2532            }
2533        }
2534    }
2535
2536    fn to_path(&self) -> rty::Path {
2537        self.to_expr().to_path().unwrap_or_else(|| {
2538            span_bug!(self.var_span, "expected path, found `{:?}`", self.to_expr())
2539        })
2540    }
2541}
2542
2543pub fn conv_func_decl(genv: GlobalEnv, func: &fhir::SpecFunc) -> QueryResult<rty::PolyFuncSort> {
2544    let wfckresults = WfckResults::new(FluxOwnerId::Flux(func.def_id));
2545    let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
2546    let inputs_and_output = func
2547        .args
2548        .iter()
2549        .map(|p| &p.sort)
2550        .chain(iter::once(&func.sort))
2551        .map(|sort| cx.conv_sort(sort))
2552        .try_collect()?;
2553    let params = iter::repeat_n(rty::SortParamKind::Sort, func.params).collect();
2554    Ok(rty::PolyFuncSort::new(params, rty::FuncSort { inputs_and_output }))
2555}
2556
2557fn conv_un_op(op: fhir::UnOp) -> rty::UnOp {
2558    match op {
2559        fhir::UnOp::Not => rty::UnOp::Not,
2560        fhir::UnOp::Neg => rty::UnOp::Neg,
2561    }
2562}
2563
2564fn def_id_to_param_ty(genv: GlobalEnv, def_id: DefId) -> rty::ParamTy {
2565    rty::ParamTy { index: genv.def_id_to_param_index(def_id), name: ty_param_name(genv, def_id) }
2566}
2567
2568fn def_id_to_param_const(genv: GlobalEnv, def_id: DefId) -> rty::ParamConst {
2569    rty::ParamConst { index: genv.def_id_to_param_index(def_id), name: ty_param_name(genv, def_id) }
2570}
2571
2572fn ty_param_owner(genv: GlobalEnv, def_id: DefId) -> DefId {
2573    let def_kind = genv.def_kind(def_id);
2574    match def_kind {
2575        DefKind::Trait | DefKind::TraitAlias => def_id,
2576        DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
2577            genv.tcx().parent(def_id)
2578        }
2579        _ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind),
2580    }
2581}
2582
2583fn ty_param_name(genv: GlobalEnv, def_id: DefId) -> Symbol {
2584    let def_kind = genv.tcx().def_kind(def_id);
2585    match def_kind {
2586        DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper,
2587        DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
2588            genv.tcx().item_name(def_id)
2589        }
2590        _ => bug!("ty_param_name: {:?} is a {:?} not a type parameter", def_id, def_kind),
2591    }
2592}
2593
2594mod errors {
2595    use flux_errors::E0999;
2596    use flux_macros::Diagnostic;
2597    use flux_middle::{fhir, global_env::GlobalEnv, rty::Sort};
2598    use rustc_hir::def_id::DefId;
2599    use rustc_span::{Span, Symbol, symbol::Ident};
2600
2601    #[derive(Diagnostic)]
2602    #[diag(fhir_analysis_assoc_type_not_found, code = E0999)]
2603    #[note]
2604    pub(super) struct AssocTypeNotFound {
2605        #[primary_span]
2606        #[label]
2607        span: Span,
2608    }
2609
2610    impl AssocTypeNotFound {
2611        pub(super) fn new(assoc_ident: Ident) -> Self {
2612            Self { span: assoc_ident.span }
2613        }
2614    }
2615
2616    #[derive(Diagnostic)]
2617    #[diag(fhir_analysis_ambiguous_assoc_type, code = E0999)]
2618    pub(super) struct AmbiguousAssocType {
2619        #[primary_span]
2620        #[label]
2621        pub span: Span,
2622        pub name: Ident,
2623    }
2624
2625    #[derive(Diagnostic)]
2626    #[diag(fhir_analysis_invalid_base_instance, code = E0999)]
2627    pub(super) struct InvalidBaseInstance {
2628        #[primary_span]
2629        span: Span,
2630    }
2631
2632    impl InvalidBaseInstance {
2633        pub(super) fn new(span: Span) -> Self {
2634            Self { span }
2635        }
2636    }
2637
2638    #[derive(Diagnostic)]
2639    #[diag(fhir_analysis_generic_argument_count_mismatch, code = E0999)]
2640    pub(super) struct GenericArgCountMismatch {
2641        #[primary_span]
2642        #[label]
2643        span: Span,
2644        found: usize,
2645        expected: usize,
2646        def_descr: &'static str,
2647    }
2648
2649    impl GenericArgCountMismatch {
2650        pub(super) fn new(
2651            genv: GlobalEnv,
2652            def_id: DefId,
2653            segment: &fhir::PathSegment,
2654            expected: usize,
2655        ) -> Self {
2656            GenericArgCountMismatch {
2657                span: segment.ident.span,
2658                found: segment.args.len(),
2659                expected,
2660                def_descr: genv.tcx().def_descr(def_id),
2661            }
2662        }
2663    }
2664
2665    #[derive(Diagnostic)]
2666    #[diag(fhir_analysis_too_few_generic_args, code = E0999)]
2667    pub(super) struct TooFewGenericArgs {
2668        #[primary_span]
2669        #[label]
2670        span: Span,
2671        found: usize,
2672        min: usize,
2673        def_descr: &'static str,
2674    }
2675
2676    impl TooFewGenericArgs {
2677        pub(super) fn new(
2678            genv: GlobalEnv,
2679            def_id: DefId,
2680            segment: &fhir::PathSegment,
2681            min: usize,
2682        ) -> Self {
2683            Self {
2684                span: segment.ident.span,
2685                found: segment.args.len(),
2686                min,
2687                def_descr: genv.tcx().def_descr(def_id),
2688            }
2689        }
2690    }
2691
2692    #[derive(Diagnostic)]
2693    #[diag(fhir_analysis_too_many_generic_args, code = E0999)]
2694    pub(super) struct TooManyGenericArgs {
2695        #[primary_span]
2696        #[label]
2697        span: Span,
2698        found: usize,
2699        max: usize,
2700        def_descr: &'static str,
2701    }
2702
2703    impl TooManyGenericArgs {
2704        pub(super) fn new(
2705            genv: GlobalEnv,
2706            def_id: DefId,
2707            segment: &fhir::PathSegment,
2708            max: usize,
2709        ) -> Self {
2710            Self {
2711                span: segment.ident.span,
2712                found: segment.args.len(),
2713                max,
2714                def_descr: genv.tcx().def_descr(def_id),
2715            }
2716        }
2717    }
2718
2719    #[derive(Diagnostic)]
2720    #[diag(fhir_analysis_refined_unrefinable_type, code = E0999)]
2721    pub(super) struct RefinedUnrefinableType {
2722        #[primary_span]
2723        span: Span,
2724    }
2725
2726    impl RefinedUnrefinableType {
2727        pub(super) fn new(span: Span) -> Self {
2728            Self { span }
2729        }
2730    }
2731
2732    #[derive(Diagnostic)]
2733    #[diag(fhir_analysis_generics_on_primitive_sort, code = E0999)]
2734    pub(super) struct GenericsOnPrimitiveSort {
2735        #[primary_span]
2736        #[label]
2737        span: Span,
2738        name: &'static str,
2739        found: usize,
2740        expected: usize,
2741    }
2742
2743    impl GenericsOnPrimitiveSort {
2744        pub(super) fn new(span: Span, name: &'static str, found: usize, expected: usize) -> Self {
2745            Self { span, found, expected, name }
2746        }
2747    }
2748
2749    #[derive(Diagnostic)]
2750    #[diag(fhir_analysis_incorrect_generics_on_sort, code = E0999)]
2751    pub(super) struct IncorrectGenericsOnSort {
2752        #[primary_span]
2753        #[label]
2754        span: Span,
2755        found: usize,
2756        expected: usize,
2757        def_descr: &'static str,
2758    }
2759
2760    impl IncorrectGenericsOnSort {
2761        pub(super) fn new(
2762            genv: GlobalEnv,
2763            def_id: DefId,
2764            span: Span,
2765            found: usize,
2766            expected: usize,
2767        ) -> Self {
2768            Self { span, found, expected, def_descr: genv.tcx().def_descr(def_id) }
2769        }
2770    }
2771
2772    #[derive(Diagnostic)]
2773    #[diag(fhir_analysis_generics_on_sort_ty_param, code = E0999)]
2774    pub(super) struct GenericsOnSortTyParam {
2775        #[primary_span]
2776        #[label]
2777        span: Span,
2778        found: usize,
2779    }
2780
2781    impl GenericsOnSortTyParam {
2782        pub(super) fn new(span: Span, found: usize) -> Self {
2783            Self { span, found }
2784        }
2785    }
2786
2787    #[derive(Diagnostic)]
2788    #[diag(fhir_analysis_generics_on_self_alias, code = E0999)]
2789    pub(super) struct GenericsOnSelf {
2790        #[primary_span]
2791        #[label]
2792        span: Span,
2793        found: usize,
2794    }
2795
2796    impl GenericsOnSelf {
2797        pub(super) fn new(span: Span, found: usize) -> Self {
2798            Self { span, found }
2799        }
2800    }
2801
2802    #[derive(Diagnostic)]
2803    #[diag(fhir_analysis_fields_on_reflected_enum_variant, code = E0999)]
2804    pub(super) struct FieldsOnReflectedEnumVariant {
2805        #[primary_span]
2806        #[label]
2807        span: Span,
2808    }
2809
2810    impl FieldsOnReflectedEnumVariant {
2811        pub(super) fn new(span: Span) -> Self {
2812            Self { span }
2813        }
2814    }
2815
2816    #[derive(Diagnostic)]
2817    #[diag(fhir_analysis_generics_on_opaque_sort, code = E0999)]
2818    pub(super) struct GenericsOnUserDefinedOpaqueSort {
2819        #[primary_span]
2820        #[label]
2821        span: Span,
2822        found: usize,
2823    }
2824
2825    impl GenericsOnUserDefinedOpaqueSort {
2826        pub(super) fn new(span: Span, found: usize) -> Self {
2827            Self { span, found }
2828        }
2829    }
2830
2831    #[derive(Diagnostic)]
2832    #[diag(fhir_analysis_generics_on_prim_ty, code = E0999)]
2833    pub(super) struct GenericsOnPrimTy {
2834        #[primary_span]
2835        pub span: Span,
2836        pub name: &'static str,
2837    }
2838
2839    #[derive(Diagnostic)]
2840    #[diag(fhir_analysis_generics_on_ty_param, code = E0999)]
2841    pub(super) struct GenericsOnTyParam {
2842        #[primary_span]
2843        pub span: Span,
2844        pub name: Symbol,
2845    }
2846
2847    #[derive(Diagnostic)]
2848    #[diag(fhir_analysis_generics_on_self_ty, code = E0999)]
2849    pub(super) struct GenericsOnSelfTy {
2850        #[primary_span]
2851        pub span: Span,
2852    }
2853
2854    #[derive(Diagnostic)]
2855    #[diag(fhir_analysis_generics_on_foreign_ty, code = E0999)]
2856    pub(super) struct GenericsOnForeignTy {
2857        #[primary_span]
2858        pub span: Span,
2859    }
2860
2861    #[derive(Diagnostic)]
2862    #[diag(fhir_analysis_invalid_bitvector_constant, code = E0999)]
2863    pub struct InvalidBitVectorConstant {
2864        #[primary_span]
2865        #[label]
2866        span: Span,
2867        sort: Sort,
2868    }
2869
2870    impl InvalidBitVectorConstant {
2871        pub(crate) fn new(span: Span, sort: Sort) -> Self {
2872            Self { span, sort }
2873        }
2874    }
2875
2876    #[derive(Diagnostic)]
2877    #[diag(fhir_analysis_invalid_assoc_reft, code = E0999)]
2878    pub struct InvalidAssocReft {
2879        #[primary_span]
2880        span: Span,
2881        trait_: String,
2882        name: Symbol,
2883    }
2884
2885    impl InvalidAssocReft {
2886        pub(crate) fn new(span: Span, name: Symbol, trait_: String) -> Self {
2887            Self { span, trait_, name }
2888        }
2889    }
2890
2891    #[derive(Diagnostic)]
2892    #[diag(fhir_analysis_refine_arg_mismatch, code = E0999)]
2893    pub(super) struct RefineArgMismatch {
2894        #[primary_span]
2895        #[label]
2896        pub span: Span,
2897        pub expected: usize,
2898        pub found: usize,
2899        pub kind: &'static str,
2900    }
2901
2902    #[derive(Diagnostic)]
2903    #[diag(fhir_analysis_expected_type, code = E0999)]
2904    pub(super) struct ExpectedType {
2905        #[primary_span]
2906        pub span: Span,
2907        pub def_descr: &'static str,
2908        pub name: String,
2909    }
2910
2911    #[derive(Diagnostic)]
2912    #[diag(fhir_analysis_fail_to_match_predicates, code = E0999)]
2913    pub(super) struct FailToMatchPredicates {
2914        #[primary_span]
2915        pub span: Span,
2916    }
2917
2918    #[derive(Diagnostic)]
2919    #[diag(fhir_analysis_invalid_position, code = E0999)]
2920    pub(super) struct InvalidPosition {
2921        #[primary_span]
2922        pub(super) span: Span,
2923    }
2924}