flux_desugar/
desugar.rs

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