Skip to main content

flux_desugar/
desugar.rs

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