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