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