Skip to main content

flux_desugar/
desugar.rs

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