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