flux_desugar/
desugar.rs

1mod lift;
2
3use std::iter;
4
5use flux_common::{
6    bug, dbg,
7    index::IndexGen,
8    iter::IterExt,
9    result::{ErrorCollector, ErrorEmitter},
10    span_bug,
11};
12use flux_config as config;
13use flux_errors::Errors;
14use flux_middle::{
15    ResolverOutput,
16    def_id::{FluxLocalDefId, MaybeExternId},
17    fhir::{self, ExprRes, FhirId, FluxOwnerId, Res},
18    global_env::GlobalEnv,
19    try_alloc_slice,
20};
21use flux_syntax::{
22    surface::{self, ConstructorArg, NodeId, visit::Visitor as _},
23    walk_list,
24};
25use hir::{ItemKind, def::DefKind};
26use itertools::{Either, Itertools};
27use rustc_data_structures::fx::FxIndexSet;
28use rustc_errors::{Diagnostic, ErrorGuaranteed};
29use rustc_hash::FxHashSet;
30use rustc_hir::{self as hir, OwnerId};
31use rustc_span::{
32    DUMMY_SP, Span,
33    def_id::{DefId, LocalDefId},
34    sym,
35    symbol::kw,
36};
37
38type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
39
40use crate::{errors, resolver::refinement_resolver::SORTS};
41
42pub(crate) fn desugar_qualifier<'genv>(
43    genv: GlobalEnv<'genv, '_>,
44    resolver_output: &'genv ResolverOutput,
45    def_id: FluxLocalDefId,
46    qualifier: &surface::Qualifier,
47) -> Result<fhir::Qualifier<'genv>> {
48    FluxItemCtxt::with(genv, resolver_output, def_id, |cx| {
49        let qualifier = fhir::Qualifier {
50            def_id,
51            args: cx.desugar_refine_params(&qualifier.params),
52            global: qualifier.global,
53            expr: cx.desugar_expr(&qualifier.expr),
54        };
55        qualifier
56    })
57}
58
59pub(crate) fn desugar_spec_func<'genv>(
60    genv: GlobalEnv<'genv, '_>,
61    resolver_output: &'genv ResolverOutput,
62    def_id: FluxLocalDefId,
63    spec_func: &surface::SpecFunc,
64) -> Result<fhir::SpecFunc<'genv>> {
65    FluxItemCtxt::with(genv, resolver_output, def_id, |cx| {
66        let body = spec_func.body.as_ref().map(|body| cx.desugar_expr(body));
67        let params = spec_func.sort_vars.len();
68        let sort = cx.desugar_sort(&spec_func.output, None);
69        let args = cx.desugar_refine_params(&spec_func.params);
70        fhir::SpecFunc { def_id, params, args, sort, body, hide: spec_func.hide }
71    })
72}
73
74/// Collect all sorts resolved to a generic type in a list of refinement parameters. Return the set
75/// of generic def_ids used (sorted by their position in the list of generics).
76fn collect_generics_in_params(
77    genv: GlobalEnv,
78    owner: MaybeExternId<OwnerId>,
79    resolver_output: &ResolverOutput,
80    params: &surface::RefineParams,
81) -> FxIndexSet<DefId> {
82    struct ParamCollector<'a> {
83        resolver_output: &'a ResolverOutput,
84        found: FxHashSet<DefId>,
85    }
86    impl surface::visit::Visitor for ParamCollector<'_> {
87        fn visit_base_sort(&mut self, bsort: &surface::BaseSort) {
88            if let surface::BaseSort::Path(path) = bsort {
89                let res = self.resolver_output.sort_path_res_map[&path.node_id];
90                if let fhir::SortRes::TyParam(def_id) = res {
91                    self.found.insert(def_id);
92                }
93            }
94            surface::visit::walk_base_sort(self, bsort);
95        }
96    }
97    let mut vis = ParamCollector { resolver_output, found: FxHashSet::default() };
98    walk_list!(vis, visit_refine_param, params);
99    genv.tcx()
100        .generics_of(owner.resolved_id())
101        .own_params
102        .iter()
103        .filter_map(
104            |param| if vis.found.contains(&param.def_id) { Some(param.def_id) } else { None },
105        )
106        .collect()
107}
108
109pub(crate) struct RustItemCtxt<'a, 'genv, 'tcx> {
110    genv: GlobalEnv<'genv, 'tcx>,
111    local_id_gen: IndexGen<fhir::ItemLocalId>,
112    owner: MaybeExternId<OwnerId>,
113    fn_sig_scope: Option<NodeId>,
114    resolver_output: &'genv ResolverOutput,
115    opaque_tys: Option<&'a mut Vec<&'genv fhir::OpaqueTy<'genv>>>,
116    errors: Errors<'genv>,
117}
118
119impl<'a, 'genv, 'tcx: 'genv> RustItemCtxt<'a, 'genv, 'tcx> {
120    pub(crate) fn with<T>(
121        genv: GlobalEnv<'genv, 'tcx>,
122        owner: MaybeExternId<OwnerId>,
123        resolver_output: &'genv ResolverOutput,
124        opaque_tys: Option<&'a mut Vec<&'genv fhir::OpaqueTy<'genv>>>,
125        f: impl FnOnce(&mut Self) -> Result<T>,
126    ) -> Result<T> {
127        let mut cx = RustItemCtxt {
128            genv,
129            owner,
130            fn_sig_scope: None,
131            local_id_gen: IndexGen::new(),
132            resolver_output,
133            opaque_tys,
134            errors: Errors::new(genv.sess()),
135        };
136        let r = f(&mut cx)?;
137        cx.into_result()?;
138        Ok(r)
139    }
140
141    pub(crate) fn desugar_trait(&mut self, trait_: &surface::Trait) -> fhir::Item<'genv> {
142        let generics = if let Some(generics) = &trait_.generics {
143            self.desugar_generics(generics)
144        } else {
145            self.lift_generics()
146        };
147        let assoc_refinements = self.desugar_trait_assoc_refts(&trait_.assoc_refinements);
148        let trait_ = fhir::Trait { assoc_refinements };
149
150        if config::dump_fhir() {
151            dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", &trait_).unwrap();
152        }
153
154        fhir::Item { generics, kind: fhir::ItemKind::Trait(trait_), owner_id: self.owner }
155    }
156
157    fn desugar_trait_assoc_refts(
158        &mut self,
159        assoc_refts: &[surface::TraitAssocReft],
160    ) -> &'genv [fhir::TraitAssocReft<'genv>] {
161        self.genv()
162            .alloc_slice_fill_iter(assoc_refts.iter().map(|assoc_reft| {
163                let name = assoc_reft.name.name;
164                let params = self.desugar_refine_params(&assoc_reft.params);
165                let output = self.desugar_base_sort(&assoc_reft.output, None);
166                let body = assoc_reft.body.as_ref().map(|expr| self.desugar_expr(expr));
167                fhir::TraitAssocReft { name, params, output, body, span: assoc_reft.span }
168            }))
169    }
170
171    pub(crate) fn desugar_impl(&mut self, impl_: &surface::Impl) -> fhir::Item<'genv> {
172        let generics = if let Some(generics) = &impl_.generics {
173            self.desugar_generics(generics)
174        } else {
175            self.lift_generics()
176        };
177        let assoc_refinements = self.desugar_impl_assoc_refts(&impl_.assoc_refinements);
178        let impl_ = fhir::Impl { assoc_refinements };
179
180        if config::dump_fhir() {
181            dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", &impl_).unwrap();
182        }
183
184        fhir::Item { generics, kind: fhir::ItemKind::Impl(impl_), owner_id: self.owner }
185    }
186
187    fn desugar_impl_assoc_refts(
188        &mut self,
189        assoc_refts: &[surface::ImplAssocReft],
190    ) -> &'genv [fhir::ImplAssocReft<'genv>] {
191        self.genv()
192            .alloc_slice_fill_iter(assoc_refts.iter().map(|assoc_reft| {
193                let name = assoc_reft.name.name;
194                let body = self.desugar_expr(&assoc_reft.body);
195                let params = self.desugar_refine_params(&assoc_reft.params);
196                let output = self.desugar_base_sort(&assoc_reft.output, None);
197                fhir::ImplAssocReft { name, params, output, body, span: assoc_reft.span }
198            }))
199    }
200
201    pub(crate) fn desugar_generics(
202        &mut self,
203        generics: &surface::Generics,
204    ) -> fhir::Generics<'genv> {
205        let params = self.genv.alloc_slice_fill_iter(
206            self.genv
207                .tcx()
208                .hir_get_generics(self.owner.local_id().def_id)
209                .unwrap()
210                .params
211                .iter()
212                .map(|hir_param| self.lift_generic_param(hir_param)),
213        );
214
215        let predicates = generics
216            .predicates
217            .as_ref()
218            .map(|preds| self.desugar_generic_predicates(preds));
219        fhir::Generics { params, refinement_params: &[], predicates }
220    }
221
222    fn desugar_opt_generics(
223        &mut self,
224        generics: Option<&surface::Generics>,
225    ) -> fhir::Generics<'genv> {
226        if let Some(generics) = generics {
227            self.desugar_generics(generics)
228        } else {
229            self.lift_generics()
230        }
231    }
232
233    fn desugar_generic_predicates(
234        &mut self,
235        predicates: &[surface::WhereBoundPredicate],
236    ) -> &'genv [fhir::WhereBoundPredicate<'genv>] {
237        self.genv
238            .alloc_slice_fill_iter(predicates.iter().map(|pred| {
239                let bounded_ty = self.desugar_ty(&pred.bounded_ty);
240                let bounds = self.desugar_generic_bounds(&pred.bounds);
241                fhir::WhereBoundPredicate { span: pred.span, bounded_ty, bounds }
242            }))
243    }
244
245    fn desugar_generic_bounds(
246        &mut self,
247        bounds: &[surface::TraitRef],
248    ) -> fhir::GenericBounds<'genv> {
249        self.genv().alloc_slice_fill_iter(
250            bounds
251                .iter()
252                .map(|bound| fhir::GenericBound::Trait(self.desugar_trait_ref(bound))),
253        )
254    }
255
256    fn desugar_trait_ref(&mut self, trait_ref: &surface::TraitRef) -> fhir::PolyTraitRef<'genv> {
257        let fhir::QPath::Resolved(None, path) = self.desugar_qpath(None, &trait_ref.path) else {
258            span_bug!(trait_ref.path.span, "desugar_alias_reft: unexpected qpath")
259        };
260        let span = path.span;
261
262        let refine_params = self
263            .genv
264            .alloc_slice_fill_iter(self.implicit_params_to_params(trait_ref.node_id));
265
266        fhir::PolyTraitRef {
267            bound_generic_params: &[],
268            refine_params,
269            modifiers: fhir::TraitBoundModifier::None,
270            trait_ref: path,
271            span,
272        }
273    }
274
275    fn desugar_refined_by(&mut self, refined_by: &surface::RefineParams) -> fhir::RefinedBy<'genv> {
276        let generic_id_to_var_idx =
277            collect_generics_in_params(self.genv, self.owner, self.resolver_output, refined_by);
278
279        let fields = refined_by
280            .iter()
281            .map(|param| {
282                (param.ident.name, self.desugar_sort(&param.sort, Some(&generic_id_to_var_idx)))
283            })
284            .collect();
285
286        fhir::RefinedBy::new(fields, generic_id_to_var_idx)
287    }
288
289    pub(crate) fn desugar_struct_def(
290        &mut self,
291        struct_def: &surface::StructDef,
292    ) -> fhir::Item<'genv> {
293        let refined_by = if let Some(refined_by) = &struct_def.refined_by {
294            self.desugar_refined_by(refined_by)
295        } else {
296            fhir::RefinedBy::trivial()
297        };
298
299        let generics = self.desugar_opt_generics(struct_def.generics.as_ref());
300
301        let invariants = self.genv().alloc_slice_fill_iter(
302            struct_def
303                .invariants
304                .iter()
305                .map(|invariant| self.desugar_expr(invariant)),
306        );
307
308        let kind = if struct_def.opaque {
309            fhir::StructKind::Opaque
310        } else {
311            let kind = &self
312                .genv
313                .hir()
314                .expect_item(self.owner.local_id().def_id)
315                .kind;
316            match kind {
317                hir::ItemKind::Struct(variant_data, _) | hir::ItemKind::Union(variant_data, _) => {
318                    debug_assert_eq!(struct_def.fields.len(), variant_data.fields().len());
319                    let fields = self.genv.alloc_slice_fill_iter(
320                        iter::zip(&struct_def.fields, variant_data.fields()).map(
321                            |(ty, hir_field)| {
322                                if let Some(ty) = ty {
323                                    fhir::FieldDef { ty: self.desugar_ty(ty), lifted: false }
324                                } else {
325                                    self.lift_field_def(hir_field)
326                                }
327                            },
328                        ),
329                    );
330                    fhir::StructKind::Transparent { fields }
331                }
332                _ => bug!("expected struct or union"),
333            }
334        };
335
336        let params = self.desugar_refine_params(struct_def.refined_by.as_deref().unwrap_or(&[]));
337        let refinement = fhir::RefinementKind::Refined(refined_by);
338        let struct_def =
339            fhir::StructDef { refinement: self.genv.alloc(refinement), params, kind, invariants };
340
341        if config::dump_fhir() {
342            dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", struct_def)
343                .unwrap();
344        }
345
346        fhir::Item { generics, kind: fhir::ItemKind::Struct(struct_def), owner_id: self.owner }
347    }
348
349    pub(crate) fn desugar_enum_def(
350        &mut self,
351        enum_def: &surface::EnumDef,
352    ) -> Result<fhir::Item<'genv>> {
353        let def_id = self.owner.local_id().def_id;
354        let ItemKind::Enum(hir_enum, _) = self.genv.hir().expect_item(def_id).kind else {
355            bug!("expected enum");
356        };
357        let reflected = enum_def.reflected;
358        let variants = try_alloc_slice!(
359            self.genv,
360            iter::zip(&enum_def.variants, hir_enum.variants),
361            |(variant, hir_variant)| self.desugar_enum_variant_def(reflected, variant, hir_variant)
362        )?;
363
364        let kind = if enum_def.reflected {
365            fhir::RefinementKind::Reflected
366        } else if let Some(refined_by) = &enum_def.refined_by {
367            fhir::RefinementKind::Refined(self.desugar_refined_by(refined_by))
368        } else {
369            fhir::RefinementKind::Refined(fhir::RefinedBy::trivial())
370        };
371
372        let generics = self.desugar_opt_generics(enum_def.generics.as_ref());
373
374        let invariants = self.genv().alloc_slice_fill_iter(
375            enum_def
376                .invariants
377                .iter()
378                .map(|invariant| self.desugar_expr(invariant)),
379        );
380
381        let params = self.desugar_refine_params(enum_def.refined_by.as_deref().unwrap_or(&[]));
382        let enum_def =
383            fhir::EnumDef { refinement: self.genv.alloc(kind), params, variants, invariants };
384
385        if config::dump_fhir() {
386            dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", &enum_def).unwrap();
387        }
388
389        Ok(fhir::Item { generics, kind: fhir::ItemKind::Enum(enum_def), owner_id: self.owner })
390    }
391
392    fn desugar_enum_variant_def(
393        &mut self,
394        reflected: bool,
395        variant_def: &Option<surface::VariantDef>,
396        hir_variant: &hir::Variant,
397    ) -> Result<fhir::VariantDef<'genv>> {
398        if let Some(variant_def) = variant_def {
399            if reflected {
400                return Err(self.emit(errors::InvalidReflectedVariant::new(hir_variant.span)));
401            }
402            let fields = self.genv.alloc_slice_fill_iter(
403                variant_def
404                    .fields
405                    .iter()
406                    .map(|ty| fhir::FieldDef { ty: self.desugar_ty(ty), lifted: false }),
407            );
408
409            let ret = if let Some(ret) = &variant_def.ret {
410                self.desugar_variant_ret(ret)?
411            } else {
412                self.lift_variant_ret()
413            };
414
415            let params = self
416                .genv
417                .alloc_slice_fill_iter(self.implicit_params_to_params(variant_def.node_id));
418
419            Ok(fhir::VariantDef {
420                def_id: hir_variant.def_id,
421                params,
422                fields,
423                ret,
424                span: variant_def.span,
425                lifted: false,
426            })
427        } else {
428            Ok(self.lift_enum_variant(hir_variant))
429        }
430    }
431
432    pub(crate) fn desugar_type_alias(
433        &mut self,
434        ty_alias: Option<&surface::TyAlias>,
435    ) -> fhir::Item<'genv> {
436        let Some(ty_alias) = ty_alias else {
437            return self.lift_type_alias();
438        };
439
440        let mut generics = self.desugar_generics(&ty_alias.generics);
441
442        let ty = self.desugar_ty(&ty_alias.ty);
443
444        generics.refinement_params = self.desugar_refine_params(&ty_alias.params);
445
446        let index = ty_alias
447            .index
448            .as_ref()
449            .map(|index| self.desugar_refine_param(index));
450
451        let ty_alias = fhir::TyAlias { index, ty, span: ty_alias.span, lifted: false };
452
453        if config::dump_fhir() {
454            dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", &ty_alias).unwrap();
455        }
456
457        fhir::Item { generics, kind: fhir::ItemKind::TyAlias(ty_alias), owner_id: self.owner }
458    }
459
460    pub(crate) fn desugar_trait_assoc_ty(&mut self) -> fhir::TraitItem<'genv> {
461        let generics = self.lift_generics();
462        fhir::TraitItem { generics, kind: fhir::TraitItemKind::Type, owner_id: self.owner }
463    }
464
465    pub(crate) fn desugar_impl_assoc_ty(&mut self) -> fhir::ImplItem<'genv> {
466        let generics = self.lift_generics();
467        fhir::ImplItem { generics, kind: fhir::ImplItemKind::Type, owner_id: self.owner }
468    }
469
470    pub(crate) fn desugar_foreign_item(
471        &mut self,
472        foreign_item: hir::ForeignItem,
473    ) -> Result<fhir::ForeignItem<'genv>> {
474        let foreign_item = self.lift_foreign_item(foreign_item)?;
475        Ok(foreign_item)
476    }
477
478    pub(crate) fn desugar_item_fn(
479        &mut self,
480        fn_spec: &surface::FnSpec,
481    ) -> Result<fhir::Item<'genv>> {
482        let (generics, fn_sig) = self.desugar_fn_spec(fn_spec)?;
483        Ok(fhir::Item { generics, kind: fhir::ItemKind::Fn(fn_sig), owner_id: self.owner })
484    }
485
486    pub(crate) fn desugar_trait_fn(
487        &mut self,
488        fn_spec: &surface::FnSpec,
489    ) -> Result<fhir::TraitItem<'genv>> {
490        let (generics, fn_sig) = self.desugar_fn_spec(fn_spec)?;
491        Ok(fhir::TraitItem {
492            generics,
493            kind: fhir::TraitItemKind::Fn(fn_sig),
494            owner_id: self.owner,
495        })
496    }
497
498    pub(crate) fn desugar_impl_fn(
499        &mut self,
500        fn_spec: &surface::FnSpec,
501    ) -> Result<fhir::ImplItem<'genv>> {
502        let (generics, fn_sig) = self.desugar_fn_spec(fn_spec)?;
503        Ok(fhir::ImplItem { generics, kind: fhir::ImplItemKind::Fn(fn_sig), owner_id: self.owner })
504    }
505
506    pub(crate) fn desugar_const(
507        &mut self,
508        const_info: &surface::ConstantInfo,
509    ) -> fhir::Item<'genv> {
510        let expr = const_info.expr.as_ref().map(|e| self.desugar_expr(e));
511        let owner_id = self.owner;
512        let generics = self.lift_generics();
513        let kind = fhir::ItemKind::Const(expr);
514        fhir::Item { owner_id, generics, kind }
515    }
516
517    pub(crate) fn desugar_impl_const(&mut self) -> fhir::ImplItem<'genv> {
518        let owner_id = self.owner;
519        let generics = self.lift_generics();
520        fhir::ImplItem { owner_id, generics, kind: fhir::ImplItemKind::Const }
521    }
522
523    pub(crate) fn desugar_trait_const(&mut self) -> fhir::TraitItem<'genv> {
524        let owner_id = self.owner;
525        let generics = self.lift_generics();
526        fhir::TraitItem { owner_id, generics, kind: fhir::TraitItemKind::Const }
527    }
528
529    pub(crate) fn desugar_fn_spec(
530        &mut self,
531        fn_spec: &surface::FnSpec,
532    ) -> Result<(fhir::Generics<'genv>, fhir::FnSig<'genv>)> {
533        let mut header = self.lift_fn_header();
534        let (generics, decl) = if let Some(fn_sig) = &fn_spec.fn_sig {
535            self.fn_sig_scope = Some(fn_sig.node_id);
536
537            let mut requires = vec![];
538
539            let mut generics = self.desugar_generics(&fn_sig.generics);
540
541            for surface_requires in &fn_sig.requires {
542                let params = self.desugar_refine_params(&surface_requires.params);
543                let pred = self.desugar_expr(&surface_requires.pred);
544                requires.push(fhir::Requires { params, pred });
545            }
546
547            // Bail out if there's an error in the arguments to avoid confusing error messages
548            let inputs = self
549                .genv()
550                .alloc_slice_fill_iter(fn_sig.inputs.iter().map(|arg| self.desugar_fn_input(arg)));
551
552            let output = self.desugar_fn_output(fn_sig.asyncness, &fn_sig.output)?;
553
554            generics.refinement_params = self.desugar_fn_sig_refine_params(fn_sig);
555
556            let decl = fhir::FnDecl {
557                requires: self.genv.alloc_slice(&requires),
558                inputs,
559                output,
560                span: fn_sig.span,
561                lifted: false,
562            };
563            // Fix up the span in asyncness
564            if let surface::Async::Yes { span, .. } = fn_sig.asyncness {
565                header.asyncness = hir::IsAsync::Async(span);
566            }
567            (generics, decl)
568        } else {
569            (self.lift_generics(), self.lift_fn_decl())
570        };
571        if config::dump_fhir() {
572            dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", decl).unwrap();
573        }
574
575        let qual_names = self
576            .owner
577            .as_local()
578            .map_or(&[][..], |owner_id| &self.resolver_output.qualifier_res_map[&owner_id]);
579
580        let reveal_names = self
581            .owner
582            .as_local()
583            .map_or(&[][..], |owner_id| &self.resolver_output.reveal_res_map[&owner_id]);
584
585        Ok((
586            generics,
587            fhir::FnSig {
588                header,
589                qualifiers: self.genv.alloc_slice(qual_names),
590                reveals: self.genv.alloc_slice(reveal_names),
591                decl: self.genv.alloc(decl),
592            },
593        ))
594    }
595
596    fn desugar_fn_sig_refine_params(
597        &mut self,
598        fn_sig: &surface::FnSig,
599    ) -> &'genv [fhir::RefineParam<'genv>] {
600        let genv = self.genv;
601        let mut params = self
602            .desugar_refine_params_iter(&fn_sig.params)
603            .collect_vec();
604        params.extend(self.implicit_params_to_params(fn_sig.node_id));
605
606        genv.alloc_slice(&params)
607    }
608
609    fn desugar_fn_output(
610        &mut self,
611        asyncness: surface::Async,
612        output: &surface::FnOutput,
613    ) -> Result<fhir::FnOutput<'genv>> {
614        let ret = self.desugar_asyncness(asyncness, &output.returns);
615
616        let ensures = try_alloc_slice!(self.genv, &output.ensures, |it| self.desugar_ensures(it))?;
617
618        let params = self
619            .genv
620            .alloc_slice_fill_iter(self.implicit_params_to_params(output.node_id));
621        Ok(fhir::FnOutput { params, ret, ensures })
622    }
623
624    fn desugar_ensures(&mut self, cstr: &surface::Ensures) -> Result<fhir::Ensures<'genv>> {
625        match cstr {
626            surface::Ensures::Type(loc, ty, node_id) => {
627                let res = self.desugar_loc(*loc, *node_id)?;
628                let path = fhir::PathExpr {
629                    segments: self.genv().alloc_slice(&[*loc]),
630                    res,
631                    fhir_id: self.next_fhir_id(),
632                    span: loc.span,
633                };
634                let ty = self.desugar_ty(ty);
635                Ok(fhir::Ensures::Type(path, ty))
636            }
637            surface::Ensures::Pred(e) => {
638                let pred = self.desugar_expr(e);
639                Ok(fhir::Ensures::Pred(pred))
640            }
641        }
642    }
643
644    fn desugar_fn_input(&mut self, input: &surface::FnInput) -> fhir::Ty<'genv> {
645        match input {
646            surface::FnInput::Constr(bind, path, pred, node_id) => {
647                let bty = self.desugar_path_to_bty(None, path);
648
649                let pred = self.desugar_expr(pred);
650
651                let ty = if let Some(idx) = self.implicit_param_into_refine_arg(*bind, *node_id) {
652                    fhir::Ty { kind: fhir::TyKind::Indexed(bty, idx), span: path.span }
653                } else {
654                    fhir::Ty { kind: fhir::TyKind::BaseTy(bty), span: path.span }
655                };
656
657                let span = path.span.to(pred.span);
658                let kind = fhir::TyKind::Constr(pred, self.genv.alloc(ty));
659                fhir::Ty { kind, span }
660            }
661            surface::FnInput::StrgRef(loc, ty, node_id) => {
662                let span = loc.span;
663                let (id, kind) = self.resolve_implicit_param(*node_id).unwrap();
664                let path = fhir::PathExpr {
665                    segments: self.genv.alloc_slice(&[*loc]),
666                    res: ExprRes::Param(kind, id),
667                    fhir_id: self.next_fhir_id(),
668                    span: loc.span,
669                };
670                let ty = self.desugar_ty(ty);
671                let kind = fhir::TyKind::StrgRef(
672                    self.mk_lft_hole(),
673                    self.genv.alloc(path),
674                    self.genv.alloc(ty),
675                );
676                fhir::Ty { kind, span }
677            }
678            surface::FnInput::Ty(bind, ty, node_id) => {
679                if let Some(bind) = bind
680                    && let surface::TyKind::Base(bty) = &ty.kind
681                {
682                    let bty = self.desugar_bty(bty);
683                    let kind =
684                        if let Some(idx) = self.implicit_param_into_refine_arg(*bind, *node_id) {
685                            fhir::TyKind::Indexed(bty, idx)
686                        } else {
687                            fhir::TyKind::BaseTy(bty)
688                        };
689                    fhir::Ty { kind, span: ty.span }
690                } else {
691                    self.desugar_ty(ty)
692                }
693            }
694        }
695    }
696
697    fn desugar_asyncness(
698        &mut self,
699        asyncness: surface::Async,
700        returns: &surface::FnRetTy,
701    ) -> fhir::Ty<'genv> {
702        match asyncness {
703            surface::Async::Yes { node_id, span } => {
704                let def_id = self.resolver_output.impl_trait_res_map[&node_id];
705                // FIXME(nilehmann) since we can only pass local ids for opaque types it means we
706                // can't support extern specs with opaque types.
707                let opaque_ty = self.desugar_opaque_ty_for_async(def_id, returns);
708                let opaque_ty = self.insert_opaque_ty(opaque_ty);
709
710                let kind = fhir::TyKind::OpaqueDef(opaque_ty);
711                fhir::Ty { kind, span }
712            }
713            surface::Async::No => self.desugar_fn_ret_ty(returns),
714        }
715    }
716
717    fn desugar_opaque_ty_for_async(
718        &mut self,
719        def_id: LocalDefId,
720        returns: &surface::FnRetTy,
721    ) -> fhir::OpaqueTy<'genv> {
722        let output = self.desugar_fn_ret_ty(returns);
723        let trait_ref = self.make_lang_item_path(
724            hir::LangItem::Future,
725            DUMMY_SP,
726            &[],
727            self.genv.alloc_slice(&[fhir::AssocItemConstraint {
728                ident: surface::Ident::with_dummy_span(sym::Output),
729                kind: fhir::AssocItemConstraintKind::Equality { term: output },
730            }]),
731        );
732        let bound = fhir::GenericBound::Trait(fhir::PolyTraitRef {
733            bound_generic_params: &[],
734            refine_params: &[],
735            modifiers: fhir::TraitBoundModifier::None,
736            trait_ref,
737            span: trait_ref.span,
738        });
739        let opaque_ty = fhir::OpaqueTy {
740            def_id: MaybeExternId::Local(def_id),
741            bounds: self.genv.alloc_slice(&[bound]),
742        };
743        opaque_ty
744    }
745
746    fn make_lang_item_path(
747        &mut self,
748        lang_item: hir::LangItem,
749        span: Span,
750        args: &'genv [fhir::GenericArg<'genv>],
751        constraints: &'genv [fhir::AssocItemConstraint<'genv>],
752    ) -> fhir::Path<'genv> {
753        let def_id = self.genv.tcx().require_lang_item(lang_item, Some(span));
754        let def_kind = self.genv.def_kind(def_id);
755        let res = Res::Def(def_kind, def_id);
756        fhir::Path {
757            span,
758            fhir_id: self.next_fhir_id(),
759            res,
760            segments: self.genv.alloc_slice_fill_iter([fhir::PathSegment {
761                ident: surface::Ident::new(lang_item.name(), span),
762                res,
763                args,
764                constraints,
765            }]),
766            refine: &[],
767        }
768    }
769
770    fn desugar_fn_ret_ty(&mut self, returns: &surface::FnRetTy) -> fhir::Ty<'genv> {
771        match returns {
772            surface::FnRetTy::Ty(ty) => self.desugar_ty(ty),
773            surface::FnRetTy::Default(span) => {
774                let kind = fhir::TyKind::Tuple(&[]);
775                fhir::Ty { kind, span: *span }
776            }
777        }
778    }
779
780    fn desugar_opaque_ty_for_impl_trait(
781        &mut self,
782        def_id: LocalDefId,
783        bounds: &[surface::TraitRef],
784    ) -> fhir::OpaqueTy<'genv> {
785        let bounds = self.desugar_generic_bounds(bounds);
786        fhir::OpaqueTy { def_id: MaybeExternId::Local(def_id), bounds }
787    }
788
789    fn desugar_variant_ret(
790        &mut self,
791        ret: &surface::VariantRet,
792    ) -> Result<fhir::VariantRet<'genv>> {
793        let Some(enum_id) = self.check_variant_ret_path(&ret.path) else {
794            return Err(self.emit(errors::InvalidVariantRet::new(&ret.path)));
795        };
796        let idx = self.desugar_indices(&ret.indices);
797        Ok(fhir::VariantRet { enum_id, idx })
798    }
799
800    fn check_variant_ret_path(&mut self, path: &surface::Path) -> Option<DefId> {
801        let resolved_id = self.owner.resolved_id();
802
803        match self.resolver_output().path_res_map[&path.node_id].full_res()? {
804            fhir::Res::Def(DefKind::Enum, def_id) if def_id == resolved_id => {}
805            fhir::Res::SelfTyAlias { .. } => return Some(resolved_id),
806            _ => return None,
807        }
808
809        let generics = self.genv.tcx().generics_of(resolved_id);
810        let args = &path.last().args;
811        if generics.own_counts().types != args.len() {
812            return None;
813        }
814        let mut i = 0;
815        for param in &generics.own_params {
816            let rustc_middle::ty::GenericParamDefKind::Type { .. } = param.kind else { continue };
817            let arg = &args[i];
818            if let surface::GenericArgKind::Type(arg_ty) = &arg.kind
819                && let surface::TyKind::Base(arg_bty) = &arg_ty.kind
820                && let surface::BaseTyKind::Path(None, arg_path) = &arg_bty.kind
821                && let fhir::Res::Def(DefKind::TyParam, def_id) =
822                    self.resolver_output().path_res_map[&arg_path.node_id].full_res()?
823                && def_id == param.def_id
824            {
825            } else {
826                return None;
827            }
828            i += 1;
829        }
830
831        Some(resolved_id)
832    }
833
834    fn insert_opaque_ty(
835        &mut self,
836        opaque_ty: fhir::OpaqueTy<'genv>,
837    ) -> &'genv fhir::OpaqueTy<'genv> {
838        let opaque_ty = self.genv.alloc(opaque_ty);
839        self.opaque_tys
840            .as_mut()
841            .unwrap_or_else(|| bug!("`impl Trait` not supported in this item `{:?}`", self.owner))
842            .push(opaque_ty);
843        opaque_ty
844    }
845}
846
847impl ErrorEmitter for RustItemCtxt<'_, '_, '_> {
848    fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
849        self.errors.emit(err)
850    }
851}
852
853impl ErrorCollector<ErrorGuaranteed> for RustItemCtxt<'_, '_, '_> {
854    type Result = std::result::Result<(), ErrorGuaranteed>;
855
856    fn collect(&mut self, err: ErrorGuaranteed) {
857        self.errors.collect(err);
858    }
859
860    fn into_result(self) -> Self::Result {
861        self.errors.into_result()
862    }
863}
864
865struct FluxItemCtxt<'genv, 'tcx> {
866    genv: GlobalEnv<'genv, 'tcx>,
867    resolver_output: &'genv ResolverOutput,
868    local_id_gen: IndexGen<fhir::ItemLocalId>,
869    owner: FluxLocalDefId,
870    errors: Errors<'genv>,
871}
872
873impl<'genv, 'tcx> FluxItemCtxt<'genv, 'tcx> {
874    fn with<T>(
875        genv: GlobalEnv<'genv, 'tcx>,
876        resolver_output: &'genv ResolverOutput,
877        owner: FluxLocalDefId,
878        f: impl FnOnce(&mut Self) -> T,
879    ) -> Result<T> {
880        let mut cx = Self {
881            genv,
882            resolver_output,
883            local_id_gen: Default::default(),
884            owner,
885            errors: Errors::new(genv.sess()),
886        };
887        let r = f(&mut cx);
888        cx.into_result()?;
889        Ok(r)
890    }
891}
892
893impl ErrorEmitter for FluxItemCtxt<'_, '_> {
894    fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
895        self.errors.emit(err)
896    }
897}
898
899impl ErrorCollector<ErrorGuaranteed> for FluxItemCtxt<'_, '_> {
900    type Result = std::result::Result<(), ErrorGuaranteed>;
901
902    fn collect(&mut self, err: ErrorGuaranteed) {
903        self.errors.collect(err);
904    }
905
906    fn into_result(self) -> Self::Result {
907        self.errors.into_result()
908    }
909}
910
911trait DesugarCtxt<'genv, 'tcx: 'genv>: ErrorEmitter + ErrorCollector<ErrorGuaranteed> {
912    fn genv(&self) -> GlobalEnv<'genv, 'tcx>;
913    fn resolver_output(&self) -> &'genv ResolverOutput;
914    fn next_fhir_id(&self) -> FhirId;
915    fn desugar_impl_trait(
916        &mut self,
917        node_id: NodeId,
918        bounds: &[surface::TraitRef],
919    ) -> fhir::TyKind<'genv>;
920
921    fn resolve_implicit_param(&self, node_id: NodeId) -> Option<(fhir::ParamId, fhir::ParamKind)> {
922        self.resolver_output().param_res_map.get(&node_id).copied()
923    }
924
925    fn desugar_epath(&self, path: &surface::ExprPath) -> fhir::PathExpr<'genv> {
926        let res = *self
927            .resolver_output()
928            .expr_path_res_map
929            .get(&path.node_id)
930            .unwrap_or_else(|| span_bug!(path.span, "unresolved expr path"));
931
932        fhir::PathExpr {
933            segments: self
934                .genv()
935                .alloc_slice_fill_iter(path.segments.iter().map(|s| s.ident)),
936            res,
937            fhir_id: self.next_fhir_id(),
938            span: path.span,
939        }
940    }
941
942    #[track_caller]
943    fn desugar_loc(&self, ident: surface::Ident, node_id: NodeId) -> Result<ExprRes> {
944        let res = self.resolver_output().expr_path_res_map[&node_id];
945        if let ExprRes::Param(fhir::ParamKind::Loc, _) = res {
946            Ok(res)
947        } else {
948            let span = ident.span;
949            Err(self.emit(errors::InvalidLoc { span }))
950        }
951    }
952
953    #[track_caller]
954    fn resolve_param(&self, node_id: NodeId) -> (fhir::ParamId, fhir::ParamKind) {
955        self.resolver_output().param_res_map[&node_id]
956    }
957
958    fn resolve_implicit_params(
959        &self,
960        scope: NodeId,
961    ) -> impl ExactSizeIterator<Item = (surface::Ident, fhir::ParamId, fhir::ParamKind)> {
962        self.resolver_output()
963            .implicit_params
964            .get(&scope)
965            .map_or(&[][..], |it| it)
966            .iter()
967            .map(|(ident, param_id)| {
968                let (param_id, kind) = self.resolve_param(*param_id);
969                (*ident, param_id, kind)
970            })
971    }
972
973    fn implicit_params_to_params(
974        &self,
975        scope: NodeId,
976    ) -> impl ExactSizeIterator<Item = fhir::RefineParam<'genv>> {
977        self.resolve_implicit_params(scope)
978            .map(|(ident, id, kind)| {
979                let sort = if kind.is_loc() { fhir::Sort::Loc } else { fhir::Sort::Infer };
980                fhir::RefineParam {
981                    id,
982                    name: ident.name,
983                    span: ident.span,
984                    kind,
985                    sort,
986                    fhir_id: self.next_fhir_id(),
987                }
988            })
989    }
990
991    fn desugar_refine_params(
992        &mut self,
993        params: &[surface::RefineParam],
994    ) -> &'genv [fhir::RefineParam<'genv>] {
995        self.genv()
996            .alloc_slice_fill_iter(self.desugar_refine_params_iter(params))
997    }
998
999    fn desugar_refine_params_iter(
1000        &mut self,
1001        params: &[surface::RefineParam],
1002    ) -> impl ExactSizeIterator<Item = fhir::RefineParam<'genv>> {
1003        params.iter().map(|param| self.desugar_refine_param(param))
1004    }
1005
1006    fn desugar_refine_param(&mut self, param: &surface::RefineParam) -> fhir::RefineParam<'genv> {
1007        let (id, kind) = self.resolve_param(param.node_id);
1008        fhir::RefineParam {
1009            id,
1010            name: param.ident.name,
1011            span: param.ident.span,
1012            kind,
1013            sort: self.desugar_sort(&param.sort, None),
1014            fhir_id: self.next_fhir_id(),
1015        }
1016    }
1017
1018    fn desugar_sort(
1019        &mut self,
1020        sort: &surface::Sort,
1021        generic_id_to_var_idx: Option<&FxIndexSet<DefId>>,
1022    ) -> fhir::Sort<'genv> {
1023        match sort {
1024            surface::Sort::Base(bsort) => self.desugar_base_sort(bsort, generic_id_to_var_idx),
1025            surface::Sort::Func { inputs, output } => {
1026                let inputs_and_output = self.genv().alloc_slice_with_capacity(
1027                    inputs.len() + 1,
1028                    inputs
1029                        .iter()
1030                        .chain(iter::once(output))
1031                        .map(|sort| self.desugar_base_sort(sort, generic_id_to_var_idx)),
1032                );
1033                fhir::Sort::Func(fhir::PolyFuncSort::new(0, inputs_and_output))
1034            }
1035            surface::Sort::Infer => fhir::Sort::Infer,
1036        }
1037    }
1038
1039    fn desugar_base_sort(
1040        &mut self,
1041        sort: &surface::BaseSort,
1042        generic_id_to_var_idx: Option<&FxIndexSet<DefId>>,
1043    ) -> fhir::Sort<'genv> {
1044        let genv = self.genv();
1045        match sort {
1046            surface::BaseSort::BitVec(width) => fhir::Sort::BitVec(*width),
1047            surface::BaseSort::Path(surface::SortPath { segments, args, node_id }) => {
1048                let res = self.resolver_output().sort_path_res_map[node_id];
1049
1050                // In a `RefinedBy` we resolve type parameters to a sort var
1051                let res = if let fhir::SortRes::TyParam(def_id) = res
1052                    && let Some(generic_id_to_var_idx) = generic_id_to_var_idx
1053                {
1054                    let idx = generic_id_to_var_idx.get_index_of(&def_id).unwrap();
1055                    fhir::SortRes::SortParam(idx)
1056                } else {
1057                    res
1058                };
1059
1060                let args = genv.alloc_slice_fill_iter(
1061                    args.iter()
1062                        .map(|s| self.desugar_base_sort(s, generic_id_to_var_idx)),
1063                );
1064
1065                let path = fhir::SortPath { res, segments: genv.alloc_slice(segments), args };
1066                fhir::Sort::Path(path)
1067            }
1068            surface::BaseSort::SortOf(qself, path) => {
1069                fhir::Sort::SortOf(self.desugar_path_to_bty(Some(qself), path))
1070            }
1071        }
1072    }
1073
1074    fn desugar_generic_args(
1075        &mut self,
1076        res: Res,
1077        args: &[surface::GenericArg],
1078    ) -> (&'genv [fhir::GenericArg<'genv>], &'genv [fhir::AssocItemConstraint<'genv>]) {
1079        let mut fhir_args = vec![];
1080        let mut constraints = vec![];
1081        if let Res::Def(
1082            DefKind::TyAlias | DefKind::Struct | DefKind::Enum | DefKind::OpaqueTy,
1083            def_id,
1084        ) = res
1085        {
1086            let generics = self.genv().tcx().generics_of(def_id);
1087            for param in &generics.own_params {
1088                if let rustc_middle::ty::GenericParamDefKind::Lifetime = param.kind {
1089                    fhir_args.push(fhir::GenericArg::Lifetime(self.mk_lft_hole()));
1090                }
1091            }
1092        }
1093        for arg in args {
1094            match &arg.kind {
1095                surface::GenericArgKind::Type(ty) if matches!(ty.kind, surface::TyKind::Hole) => {
1096                    fhir_args.push(fhir::GenericArg::Infer);
1097                }
1098                surface::GenericArgKind::Type(ty) => {
1099                    let ty = self.desugar_ty(ty);
1100                    fhir_args.push(fhir::GenericArg::Type(self.genv().alloc(ty)));
1101                }
1102                surface::GenericArgKind::Constraint(ident, ty) => {
1103                    constraints.push(fhir::AssocItemConstraint {
1104                        ident: *ident,
1105                        kind: fhir::AssocItemConstraintKind::Equality { term: self.desugar_ty(ty) },
1106                    });
1107                }
1108            }
1109        }
1110        (self.genv().alloc_slice(&fhir_args), self.genv().alloc_slice(&constraints))
1111    }
1112
1113    /// This is the mega desugaring function [`surface::Ty`] -> [`fhir::Ty`].
1114    /// These are both similar representations. The most important difference is that
1115    /// [`fhir::Ty`] has explicit refinement parameters and [`surface::Ty`] does not.
1116    /// Refinements are implicitly scoped in surface.
1117    fn desugar_ty(&mut self, ty: &surface::Ty) -> fhir::Ty<'genv> {
1118        let node_id = ty.node_id;
1119        let span = ty.span;
1120        let kind = match &ty.kind {
1121            surface::TyKind::Base(bty) => {
1122                let bty = self.desugar_bty(bty);
1123                fhir::TyKind::BaseTy(bty)
1124            }
1125            surface::TyKind::Indexed { bty, indices } => {
1126                let bty = self.desugar_bty(bty);
1127                let idx = self.desugar_indices(indices);
1128                fhir::TyKind::Indexed(bty, idx)
1129            }
1130            surface::TyKind::Exists { bind, bty, pred } => {
1131                let ty_span = ty.span;
1132                let bty_span = bty.span;
1133
1134                let bty = self.desugar_bty(bty);
1135                let pred = self.desugar_expr(pred);
1136
1137                let (id, kind) = self.resolve_param(node_id);
1138                let param = fhir::RefineParam {
1139                    id,
1140                    name: bind.name,
1141                    span: bind.span,
1142                    sort: fhir::Sort::Infer,
1143                    kind,
1144                    fhir_id: self.next_fhir_id(),
1145                };
1146                let path = fhir::PathExpr {
1147                    segments: self.genv().alloc_slice(&[*bind]),
1148                    res: ExprRes::Param(kind, id),
1149                    fhir_id: self.next_fhir_id(),
1150                    span: bind.span,
1151                };
1152                let idx = fhir::Expr {
1153                    kind: fhir::ExprKind::Var(path, None),
1154                    span: bind.span,
1155                    fhir_id: self.next_fhir_id(),
1156                };
1157                let indexed = fhir::Ty { kind: fhir::TyKind::Indexed(bty, idx), span: bty_span };
1158                let constr = fhir::Ty {
1159                    kind: fhir::TyKind::Constr(pred, self.genv().alloc(indexed)),
1160                    span: ty_span,
1161                };
1162                fhir::TyKind::Exists(self.genv().alloc_slice(&[param]), self.genv().alloc(constr))
1163            }
1164            surface::TyKind::GeneralExists { params, ty, pred } => {
1165                let mut ty = self.desugar_ty(ty);
1166                if let Some(pred) = pred {
1167                    let pred = self.desugar_expr(pred);
1168                    ty = fhir::Ty { kind: fhir::TyKind::Constr(pred, self.genv().alloc(ty)), span };
1169                }
1170                let params = self.desugar_refine_params(params);
1171
1172                fhir::TyKind::Exists(params, self.genv().alloc(ty))
1173            }
1174            surface::TyKind::Constr(pred, ty) => {
1175                let pred = self.desugar_expr(pred);
1176                let ty = self.desugar_ty(ty);
1177                fhir::TyKind::Constr(pred, self.genv().alloc(ty))
1178            }
1179            surface::TyKind::Ref(mutbl, ty) => {
1180                let ty = self.desugar_ty(ty);
1181                let mut_ty = fhir::MutTy { ty: self.genv().alloc(ty), mutbl: *mutbl };
1182                fhir::TyKind::Ref(self.mk_lft_hole(), mut_ty)
1183            }
1184            surface::TyKind::Tuple(tys) => {
1185                let tys = self
1186                    .genv()
1187                    .alloc_slice_fill_iter(tys.iter().map(|ty| self.desugar_ty(ty)));
1188                fhir::TyKind::Tuple(tys)
1189            }
1190            surface::TyKind::Array(ty, len) => {
1191                let ty = self.desugar_ty(ty);
1192                let len = Self::desugar_const_arg(len);
1193                fhir::TyKind::Array(self.genv().alloc(ty), len)
1194            }
1195            surface::TyKind::ImplTrait(node_id, bounds) => {
1196                self.desugar_impl_trait(*node_id, bounds)
1197            }
1198            surface::TyKind::Hole => fhir::TyKind::Infer,
1199        };
1200        fhir::Ty { kind, span }
1201    }
1202
1203    fn desugar_const_arg(const_arg: &surface::ConstArg) -> fhir::ConstArg {
1204        let kind = match const_arg.kind {
1205            surface::ConstArgKind::Lit(val) => fhir::ConstArgKind::Lit(val),
1206            surface::ConstArgKind::Infer => fhir::ConstArgKind::Infer,
1207        };
1208        fhir::ConstArg { kind, span: const_arg.span }
1209    }
1210
1211    fn desugar_bty(&mut self, bty: &surface::BaseTy) -> fhir::BaseTy<'genv> {
1212        match &bty.kind {
1213            surface::BaseTyKind::Path(qself, path) => {
1214                let qpath = self.desugar_qpath(qself.as_deref(), path);
1215                fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())
1216            }
1217            surface::BaseTyKind::Slice(ty) => {
1218                let ty = self.desugar_ty(ty);
1219                let kind = fhir::BaseTyKind::Slice(self.genv().alloc(ty));
1220                fhir::BaseTy { kind, fhir_id: self.next_fhir_id(), span: bty.span }
1221            }
1222        }
1223    }
1224
1225    fn desugar_path_to_bty(
1226        &mut self,
1227        qself: Option<&surface::Ty>,
1228        path: &surface::Path,
1229    ) -> fhir::BaseTy<'genv> {
1230        let qpath = self.desugar_qpath(qself, path);
1231        fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())
1232    }
1233
1234    fn desugar_qpath(
1235        &mut self,
1236        qself: Option<&surface::Ty>,
1237        path: &surface::Path,
1238    ) -> fhir::QPath<'genv> {
1239        let qself = if let Some(ty) = qself {
1240            let ty = self.desugar_ty(ty);
1241            Some(self.genv().alloc(ty))
1242        } else {
1243            None
1244        };
1245        let partial_res = self.resolver_output().path_res_map[&path.node_id];
1246
1247        let unresolved_segments = partial_res.unresolved_segments();
1248
1249        let proj_start = path.segments.len() - unresolved_segments;
1250        let fhir_path = fhir::Path {
1251            res: partial_res.base_res(),
1252            fhir_id: self.next_fhir_id(),
1253            segments: self.genv().alloc_slice_fill_iter(
1254                path.segments[..proj_start]
1255                    .iter()
1256                    .map(|segment| self.desugar_path_segment(segment)),
1257            ),
1258            refine: self
1259                .genv()
1260                .alloc_slice_fill_iter(path.refine.iter().map(|arg| self.desugar_refine_arg(arg))),
1261            span: path.span,
1262        };
1263
1264        // Simple case, either no projections, or only fully-qualified.
1265        // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
1266        if unresolved_segments == 0 {
1267            return fhir::QPath::Resolved(qself, fhir_path);
1268        }
1269
1270        // Create the innermost type that we're projecting from.
1271        let mut ty = if fhir_path.segments.is_empty() {
1272            // If the base path is empty that means there exists a
1273            // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
1274            qself.expect("missing QSelf for <T>::...")
1275        } else {
1276            // Otherwise, the base path is an implicit `Self` type path,
1277            // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
1278            // `<I as Iterator>::Item::default`.
1279            self.genv()
1280                .alloc(self.ty_path(fhir::QPath::Resolved(qself, fhir_path)))
1281        };
1282
1283        for (i, segment) in path.segments.iter().enumerate().skip(proj_start) {
1284            let hir_segment = self.desugar_path_segment(segment);
1285            let qpath = fhir::QPath::TypeRelative(ty, self.genv().alloc(hir_segment));
1286
1287            if i == path.segments.len() - 1 {
1288                return qpath;
1289            }
1290
1291            ty = self.genv().alloc(self.ty_path(qpath));
1292        }
1293
1294        span_bug!(
1295            path.span,
1296            "desugar_qpath: no final extension segment in {}..{}",
1297            proj_start,
1298            path.segments.len()
1299        );
1300    }
1301
1302    fn desugar_path_segment(&mut self, segment: &surface::PathSegment) -> fhir::PathSegment<'genv> {
1303        let res = self
1304            .resolver_output()
1305            .path_res_map
1306            .get(&segment.node_id)
1307            .map_or(Res::Err, |r| r.expect_full_res());
1308        let (args, constraints) = self.desugar_generic_args(res, &segment.args);
1309        fhir::PathSegment { ident: segment.ident, res, args, constraints }
1310    }
1311
1312    fn ty_path(&self, qpath: fhir::QPath<'genv>) -> fhir::Ty<'genv> {
1313        fhir::Ty {
1314            span: qpath.span(),
1315            kind: fhir::TyKind::BaseTy(fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())),
1316        }
1317    }
1318
1319    fn mk_lft_hole(&self) -> fhir::Lifetime {
1320        fhir::Lifetime::Hole(self.next_fhir_id())
1321    }
1322
1323    fn desugar_indices(&mut self, idxs: &surface::Indices) -> fhir::Expr<'genv> {
1324        if let [arg] = &idxs.indices[..] {
1325            self.desugar_refine_arg(arg)
1326        } else {
1327            let flds = self
1328                .genv()
1329                .alloc_slice_fill_iter(idxs.indices.iter().map(|arg| self.desugar_refine_arg(arg)));
1330            fhir::Expr {
1331                kind: fhir::ExprKind::Record(flds),
1332                fhir_id: self.next_fhir_id(),
1333                span: idxs.span,
1334            }
1335        }
1336    }
1337
1338    fn desugar_refine_arg(&mut self, arg: &surface::RefineArg) -> fhir::Expr<'genv> {
1339        match arg {
1340            surface::RefineArg::Bind(ident, .., node_id) => {
1341                self.implicit_param_into_refine_arg(*ident, *node_id)
1342                    .unwrap()
1343            }
1344            surface::RefineArg::Expr(expr) => self.desugar_expr(expr),
1345            surface::RefineArg::Abs(params, body, span, _) => {
1346                let body = self.genv().alloc(self.desugar_expr(body));
1347                let params = self.desugar_refine_params(params);
1348                fhir::Expr {
1349                    kind: fhir::ExprKind::Abs(params, body),
1350                    fhir_id: self.next_fhir_id(),
1351                    span: *span,
1352                }
1353            }
1354        }
1355    }
1356
1357    fn implicit_param_into_refine_arg(
1358        &self,
1359        ident: surface::Ident,
1360        node_id: NodeId,
1361    ) -> Option<fhir::Expr<'genv>> {
1362        let (id, kind) = self.resolve_implicit_param(node_id)?;
1363        let path = fhir::PathExpr {
1364            segments: self.genv().alloc_slice(&[ident]),
1365            res: ExprRes::Param(kind, id),
1366            fhir_id: self.next_fhir_id(),
1367            span: ident.span,
1368        };
1369        Some(fhir::Expr {
1370            kind: fhir::ExprKind::Var(path, Some(kind)),
1371            span: ident.span,
1372            fhir_id: self.next_fhir_id(),
1373        })
1374    }
1375
1376    fn desugar_expr(&mut self, expr: &surface::Expr) -> fhir::Expr<'genv> {
1377        let kind = match &expr.kind {
1378            surface::ExprKind::Path(path) => fhir::ExprKind::Var(self.desugar_epath(path), None),
1379            surface::ExprKind::Literal(lit) => self.desugar_lit(expr.span, *lit),
1380            surface::ExprKind::BinaryOp(op, box [e1, e2]) => {
1381                let e1 = self.desugar_expr(e1);
1382                let e2 = self.desugar_expr(e2);
1383                fhir::ExprKind::BinaryOp(*op, self.genv().alloc(e1), self.genv().alloc(e2))
1384            }
1385            surface::ExprKind::UnaryOp(op, box e) => {
1386                fhir::ExprKind::UnaryOp(*op, self.genv().alloc(self.desugar_expr(e)))
1387            }
1388            surface::ExprKind::Dot(base, fld) => {
1389                let base = self.desugar_expr(base);
1390                fhir::ExprKind::Dot(self.genv().alloc(base), *fld)
1391            }
1392            surface::ExprKind::Call(callee, args) => self.desugar_call(callee, args),
1393            surface::ExprKind::AssocReft(..) => {
1394                fhir::ExprKind::Err(self.emit(errors::UnsupportedPosition::new(expr.span)))
1395            }
1396            surface::ExprKind::IfThenElse(box [p, e1, e2]) => {
1397                let p = self.desugar_expr(p);
1398                let e1 = self.desugar_expr(e1);
1399                let e2 = self.desugar_expr(e2);
1400                fhir::ExprKind::IfThenElse(
1401                    self.genv().alloc(p),
1402                    self.genv().alloc(e1),
1403                    self.genv().alloc(e2),
1404                )
1405            }
1406            surface::ExprKind::Constructor(path, args) => {
1407                self.desugar_constructor(path.as_ref(), args)
1408            }
1409            surface::ExprKind::BoundedQuant(kind, param, rng, body) => {
1410                let kind = match kind {
1411                    surface::QuantKind::Exists => fhir::QuantKind::Exists,
1412                    surface::QuantKind::Forall => fhir::QuantKind::Forall,
1413                };
1414                let body = self.genv().alloc(self.desugar_expr(body));
1415                let param = self.desugar_refine_param(param);
1416                let rng = fhir::Range { start: rng.start, end: rng.end };
1417                fhir::ExprKind::BoundedQuant(kind, param, rng, body)
1418            }
1419            surface::ExprKind::Block(decls, body) => {
1420                let decls = self.genv().alloc_slice_fill_iter(decls.iter().map(|decl| {
1421                    fhir::LetDecl {
1422                        param: self.desugar_refine_param(&decl.param),
1423                        init: self.desugar_expr(&decl.init),
1424                    }
1425                }));
1426                let body = self.genv().alloc(self.desugar_expr(body));
1427                fhir::ExprKind::Block(decls, body)
1428            }
1429        };
1430
1431        fhir::Expr { kind, span: expr.span, fhir_id: self.next_fhir_id() }
1432    }
1433
1434    fn desugar_call(
1435        &mut self,
1436        callee: &surface::Expr,
1437        args: &[surface::Expr],
1438    ) -> fhir::ExprKind<'genv> {
1439        let args = self.desugar_exprs(args);
1440        match &callee.kind {
1441            surface::ExprKind::Path(path) => {
1442                let path = self.desugar_epath(path);
1443                fhir::ExprKind::App(path, args)
1444            }
1445            surface::ExprKind::AssocReft(qself, path, name) => {
1446                let qself = self.desugar_ty(qself);
1447                let fhir::QPath::Resolved(None, fpath) = self.desugar_qpath(None, path) else {
1448                    span_bug!(path.span, "desugar_alias_reft: unexpected qpath")
1449                };
1450                let Res::Def(DefKind::Trait, _) = fpath.res else {
1451                    // FIXME(nilehmann) we ought to report this error somewhere else
1452                    return fhir::ExprKind::Err(self.emit(errors::InvalidAliasReft::new(path)));
1453                };
1454                let alias_reft = fhir::AliasReft {
1455                    qself: self.genv().alloc(qself),
1456                    path: fpath,
1457                    name: name.name,
1458                };
1459                fhir::ExprKind::Alias(alias_reft, args)
1460            }
1461            _ => fhir::ExprKind::Err(self.emit(errors::UnsupportedPosition::new(callee.span))),
1462        }
1463    }
1464
1465    fn desugar_constructor(
1466        &mut self,
1467        path: Option<&surface::ExprPath>,
1468        args: &[surface::ConstructorArg],
1469    ) -> fhir::ExprKind<'genv> {
1470        let path = if let Some(path) = path {
1471            let res = self.resolver_output().expr_path_res_map[&path.node_id];
1472            if !matches!(res, ExprRes::Ctor(..)) {
1473                return fhir::ExprKind::Err(
1474                    self.emit(errors::InvalidConstructorPath { span: path.span }),
1475                );
1476            };
1477            let segments = self
1478                .genv()
1479                .alloc_slice_fill_iter(path.segments.iter().map(|s| s.ident));
1480            Some(fhir::PathExpr { segments, res, fhir_id: self.next_fhir_id(), span: path.span })
1481        } else {
1482            None
1483        };
1484
1485        let (field_exprs, spreads): (Vec<_>, Vec<_>) = args.iter().partition_map(|arg| {
1486            match arg {
1487                ConstructorArg::FieldExpr(e) => Either::Left(e),
1488                ConstructorArg::Spread(s) => Either::Right(s),
1489            }
1490        });
1491
1492        let field_exprs = self
1493            .genv()
1494            .alloc_slice_fill_iter(field_exprs.iter().map(|field_expr| {
1495                let e = self.desugar_expr(&field_expr.expr);
1496                fhir::FieldExpr {
1497                    ident: field_expr.ident,
1498                    expr: e,
1499                    fhir_id: self.next_fhir_id(),
1500                    span: e.span,
1501                }
1502            }));
1503
1504        match &spreads[..] {
1505            [] => fhir::ExprKind::Constructor(path, field_exprs, None),
1506            [s] => {
1507                let spread = fhir::Spread {
1508                    expr: self.desugar_expr(&s.expr),
1509                    span: s.span,
1510                    fhir_id: self.next_fhir_id(),
1511                };
1512                fhir::ExprKind::Constructor(path, field_exprs, Some(self.genv().alloc(spread)))
1513            }
1514            [s1, s2, ..] => {
1515                let err = errors::MultipleSpreadsInConstructor::new(s1.span, s2.span);
1516                fhir::ExprKind::Err(self.emit(err))
1517            }
1518        }
1519    }
1520
1521    fn desugar_exprs(&mut self, exprs: &[surface::Expr]) -> &'genv [fhir::Expr<'genv>] {
1522        self.genv()
1523            .alloc_slice_fill_iter(exprs.iter().map(|e| self.desugar_expr(e)))
1524    }
1525
1526    fn try_parse_int_lit(&self, span: Span, s: &str) -> Result<u128> {
1527        let s = s.replace("_", "");
1528        let parsed_int = if s.len() <= 2 {
1529            s.parse::<u128>()
1530        } else {
1531            match &s[0..2] {
1532                "0x" => u128::from_str_radix(&s[2..], 16), // hex
1533                "0o" => u128::from_str_radix(&s[2..], 8),  // octal
1534                "0b" => u128::from_str_radix(&s[2..], 2),  // binary
1535                _ => s.parse::<u128>(),                    // must be decimal
1536            }
1537        };
1538
1539        if let Ok(n) = parsed_int {
1540            Ok(n) // convert error types
1541        } else {
1542            Err(self.emit(errors::IntTooLarge { span }))
1543        }
1544    }
1545
1546    /// Desugar surface literal
1547    fn desugar_lit(&self, span: Span, lit: surface::Lit) -> fhir::ExprKind<'genv> {
1548        let lit = match lit.kind {
1549            surface::LitKind::Integer => {
1550                let n = match self.try_parse_int_lit(span, lit.symbol.as_str()) {
1551                    Ok(n) => n,
1552                    Err(err) => return fhir::ExprKind::Err(err),
1553                };
1554                let suffix = lit.suffix.unwrap_or(SORTS.int);
1555                if suffix == SORTS.int {
1556                    fhir::Lit::Int(n)
1557                } else if suffix == SORTS.real {
1558                    fhir::Lit::Real(n)
1559                } else {
1560                    return fhir::ExprKind::Err(
1561                        self.emit(errors::InvalidNumericSuffix::new(span, suffix)),
1562                    );
1563                }
1564            }
1565            surface::LitKind::Bool => fhir::Lit::Bool(lit.symbol == kw::True),
1566            surface::LitKind::Str => fhir::Lit::Str(lit.symbol),
1567            surface::LitKind::Char => fhir::Lit::Char(lit.symbol.as_str().parse::<char>().unwrap()),
1568            _ => return fhir::ExprKind::Err(self.emit(errors::UnexpectedLiteral { span })),
1569        };
1570        fhir::ExprKind::Literal(lit)
1571    }
1572}
1573
1574impl<'genv, 'tcx> DesugarCtxt<'genv, 'tcx> for RustItemCtxt<'_, 'genv, 'tcx> {
1575    fn next_fhir_id(&self) -> FhirId {
1576        FhirId {
1577            owner: FluxOwnerId::Rust(self.owner.local_id()),
1578            local_id: self.local_id_gen.fresh(),
1579        }
1580    }
1581
1582    fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
1583        self.genv
1584    }
1585
1586    fn resolver_output(&self) -> &'genv ResolverOutput {
1587        self.resolver_output
1588    }
1589
1590    fn desugar_impl_trait(
1591        &mut self,
1592        node_id: NodeId,
1593        bounds: &[surface::TraitRef],
1594    ) -> fhir::TyKind<'genv> {
1595        let def_id = self.resolver_output().impl_trait_res_map[&node_id];
1596
1597        // FIXME(nilehmann) since we can only pass local ids for opaque types it means we can't
1598        // support extern specs with opaque types.
1599        let opaque_ty = self.desugar_opaque_ty_for_impl_trait(def_id, bounds);
1600        let opaque_ty = self.insert_opaque_ty(opaque_ty);
1601
1602        fhir::TyKind::OpaqueDef(opaque_ty)
1603    }
1604}
1605
1606impl<'genv, 'tcx> DesugarCtxt<'genv, 'tcx> for FluxItemCtxt<'genv, 'tcx> {
1607    fn next_fhir_id(&self) -> FhirId {
1608        FhirId { owner: FluxOwnerId::Flux(self.owner), local_id: self.local_id_gen.fresh() }
1609    }
1610
1611    fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
1612        self.genv
1613    }
1614
1615    fn resolver_output(&self) -> &'genv ResolverOutput {
1616        self.resolver_output
1617    }
1618
1619    fn desugar_impl_trait(&mut self, _: NodeId, _: &[surface::TraitRef]) -> fhir::TyKind<'genv> {
1620        unimplemented!("`impl Trait` not supported in this item")
1621    }
1622}