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