flux_desugar/
desugar.rs

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