flux_desugar/desugar/
lift.rs

1//! "Lift" HIR types into  FHIR types.
2
3use flux_common::{
4    bug,
5    iter::IterExt,
6    result::{ErrorEmitter as _, ResultExt},
7};
8use flux_errors::ErrorGuaranteed;
9use flux_middle::{
10    def_id::MaybeExternId,
11    fhir::{self, FhirId, FluxOwnerId},
12    query_bug, try_alloc_slice,
13};
14use rustc_hir::{
15    self as hir, FnHeader,
16    def_id::{DefId, LocalDefId},
17};
18use rustc_span::Span;
19
20use super::{DesugarCtxt, RustItemCtxt};
21
22type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
23
24impl<'genv> RustItemCtxt<'_, 'genv, '_> {
25    pub(crate) fn lift_item(&mut self) -> Result<fhir::Item<'genv>> {
26        let hir_item = self
27            .genv
28            .tcx()
29            .hir_item(hir::ItemId { owner_id: self.owner.local_id() });
30        let (generics, kind) = match hir_item.kind {
31            hir::ItemKind::Const(_, generics, ..) => (generics, fhir::ItemKind::Const(None)),
32            hir::ItemKind::Fn { sig, generics, .. } => {
33                (generics, fhir::ItemKind::Fn(self.lift_fn_sig(sig)))
34            }
35            hir::ItemKind::TyAlias(_, generics, ty) => {
36                let ty_alias = self.lift_type_alias(hir_item.span, ty);
37                let kind = fhir::ItemKind::TyAlias(self.genv.alloc(ty_alias));
38                (generics, kind)
39            }
40            hir::ItemKind::Enum(_, generics, enum_def) => {
41                (generics, fhir::ItemKind::Enum(self.lift_enum_def(enum_def)))
42            }
43            hir::ItemKind::Struct(_, generics, variant_data) => {
44                (generics, fhir::ItemKind::Struct(self.lift_struct_def(variant_data)))
45            }
46            hir::ItemKind::Union(_, generics, variant_data) => {
47                (generics, fhir::ItemKind::Struct(self.lift_struct_def(variant_data)))
48            }
49            hir::ItemKind::Trait(_, _, _, _, generics, ..) => {
50                (generics, fhir::ItemKind::Trait(fhir::Trait { assoc_refinements: &[] }))
51            }
52            hir::ItemKind::Impl(impl_) => {
53                (impl_.generics, fhir::ItemKind::Impl(fhir::Impl { assoc_refinements: &[] }))
54            }
55            _ => {
56                Err(query_bug!(self.owner.resolved_id(), "unsupported item")).emit(&self.genv())?
57            }
58        };
59        Ok(fhir::Item { owner_id: self.owner, generics: self.lift_generics_inner(generics), kind })
60    }
61
62    pub(crate) fn lift_trait_item(&mut self) -> fhir::TraitItem<'genv> {
63        let hir_trait_item = self
64            .genv
65            .tcx()
66            .hir_trait_item(hir::TraitItemId { owner_id: self.owner.local_id() });
67        let generics = self.lift_generics_inner(hir_trait_item.generics);
68        let kind = match hir_trait_item.kind {
69            hir::TraitItemKind::Fn(fn_sig, ..) => fhir::TraitItemKind::Fn(self.lift_fn_sig(fn_sig)),
70            hir::TraitItemKind::Const(..) => fhir::TraitItemKind::Const,
71            hir::TraitItemKind::Type(..) => fhir::TraitItemKind::Type,
72        };
73        fhir::TraitItem { owner_id: self.owner, generics, kind }
74    }
75
76    pub(crate) fn lift_impl_item(&mut self) -> fhir::ImplItem<'genv> {
77        let hir_impl_item = self
78            .genv
79            .tcx()
80            .hir_impl_item(hir::ImplItemId { owner_id: self.owner.local_id() });
81        let generics = self.lift_generics_inner(hir_impl_item.generics);
82        let kind = match hir_impl_item.kind {
83            hir::ImplItemKind::Fn(fn_sig, ..) => fhir::ImplItemKind::Fn(self.lift_fn_sig(fn_sig)),
84            hir::ImplItemKind::Const(..) => fhir::ImplItemKind::Const,
85            hir::ImplItemKind::Type(..) => fhir::ImplItemKind::Type,
86        };
87        fhir::ImplItem { owner_id: self.owner, generics, kind }
88    }
89
90    pub(crate) fn lift_generics(&mut self) -> fhir::Generics<'genv> {
91        let generics = self.genv.tcx().hir_get_generics(self.local_id()).unwrap();
92        self.lift_generics_inner(generics)
93    }
94
95    pub(crate) fn lift_generic_param(
96        &mut self,
97        param: &hir::GenericParam,
98    ) -> fhir::GenericParam<'genv> {
99        let kind = match param.kind {
100            hir::GenericParamKind::Lifetime { .. } => fhir::GenericParamKind::Lifetime,
101            hir::GenericParamKind::Type { default, .. } => {
102                fhir::GenericParamKind::Type { default: default.map(|ty| self.lift_ty(ty)) }
103            }
104            hir::GenericParamKind::Const { ty, .. } => {
105                let ty = self.lift_ty(ty);
106                fhir::GenericParamKind::Const { ty }
107            }
108        };
109        fhir::GenericParam {
110            def_id: self.genv.maybe_extern_id(param.def_id),
111            name: param.name,
112            kind,
113        }
114    }
115
116    fn lift_generics_inner(&mut self, generics: &hir::Generics) -> fhir::Generics<'genv> {
117        let params = self.genv.alloc_slice_fill_iter(
118            generics
119                .params
120                .iter()
121                .map(|param| self.lift_generic_param(param)),
122        );
123
124        fhir::Generics { params, refinement_params: &[], predicates: None }
125    }
126
127    fn lift_generic_bound(
128        &mut self,
129        bound: &hir::GenericBound,
130    ) -> Result<fhir::GenericBound<'genv>> {
131        match bound {
132            hir::GenericBound::Trait(poly_trait_ref) => {
133                Ok(fhir::GenericBound::Trait(self.lift_poly_trait_ref(*poly_trait_ref)?))
134            }
135            hir::GenericBound::Outlives(lft) => {
136                let lft = self.lift_lifetime(lft);
137                Ok(fhir::GenericBound::Outlives(lft))
138            }
139            _ => Err(self.emit_unsupported(&format!("unsupported generic bound: `{bound:?}`"))),
140        }
141    }
142
143    fn lift_poly_trait_ref(
144        &mut self,
145        poly_trait_ref: hir::PolyTraitRef,
146    ) -> Result<fhir::PolyTraitRef<'genv>> {
147        let modifiers = match poly_trait_ref.modifiers {
148            rustc_hir::TraitBoundModifiers {
149                constness: rustc_hir::BoundConstness::Never,
150                polarity: rustc_hir::BoundPolarity::Positive,
151            } => fhir::TraitBoundModifier::None,
152            rustc_hir::TraitBoundModifiers {
153                constness: rustc_hir::BoundConstness::Never,
154                polarity: rustc_hir::BoundPolarity::Maybe(_),
155            } => fhir::TraitBoundModifier::Maybe,
156            _ => {
157                return Err(self.emit_unsupported(&format!(
158                    "unsupported trait modifiers: `{:?}`",
159                    poly_trait_ref.modifiers,
160                )));
161            }
162        };
163        let bound_generic_params = self.genv.alloc_slice_fill_iter(
164            poly_trait_ref
165                .bound_generic_params
166                .iter()
167                .map(|param| self.lift_generic_param(param)),
168        );
169        let trait_ref = self.lift_path(poly_trait_ref.trait_ref.path)?;
170        Ok(fhir::PolyTraitRef {
171            bound_generic_params,
172            refine_params: &[],
173            modifiers,
174            trait_ref,
175            span: poly_trait_ref.span,
176        })
177    }
178
179    pub(crate) fn lift_opaque_ty(
180        &mut self,
181        opaque_ty: &hir::OpaqueTy,
182    ) -> Result<fhir::OpaqueTy<'genv>> {
183        let bounds =
184            try_alloc_slice!(self.genv, &opaque_ty.bounds, |bound| self.lift_generic_bound(bound))?;
185
186        Ok(fhir::OpaqueTy { def_id: MaybeExternId::Local(opaque_ty.def_id), bounds })
187    }
188
189    pub(crate) fn lift_fn_header(&mut self) -> FnHeader {
190        let hir_id = self.genv.tcx().local_def_id_to_hir_id(self.local_id());
191        self.genv
192            .tcx()
193            .hir_fn_sig_by_hir_id(hir_id)
194            .expect("item does not have a `FnDecl`")
195            .header
196    }
197
198    pub(crate) fn lift_fn_decl(&mut self) -> fhir::FnDecl<'genv> {
199        let hir_id = self.genv.tcx().local_def_id_to_hir_id(self.local_id());
200        let fn_sig = self
201            .genv
202            .tcx()
203            .hir_fn_sig_by_hir_id(hir_id)
204            .expect("item does not have a `FnDecl`");
205
206        self.lift_fn_decl_inner(fn_sig.span, fn_sig.decl)
207    }
208
209    fn lift_fn_decl_inner(&mut self, span: Span, decl: &hir::FnDecl) -> fhir::FnDecl<'genv> {
210        let inputs = self
211            .genv
212            .alloc_slice_fill_iter(decl.inputs.iter().map(|ty| self.lift_ty(ty)));
213
214        let output =
215            fhir::FnOutput { params: &[], ensures: &[], ret: self.lift_fn_ret_ty(&decl.output) };
216
217        fhir::FnDecl { requires: &[], inputs, output, span, lifted: true }
218    }
219
220    fn lift_fn_ret_ty(&mut self, ret_ty: &hir::FnRetTy) -> fhir::Ty<'genv> {
221        match ret_ty {
222            hir::FnRetTy::DefaultReturn(_) => {
223                let kind = fhir::TyKind::Tuple(&[]);
224                fhir::Ty { kind, span: ret_ty.span() }
225            }
226            hir::FnRetTy::Return(ty) => self.lift_ty(ty),
227        }
228    }
229
230    fn lift_type_alias(&mut self, span: Span, ty: &hir::Ty) -> fhir::TyAlias<'genv> {
231        let ty = self.lift_ty(ty);
232        fhir::TyAlias { index: None, ty, span, lifted: true }
233    }
234
235    fn lift_struct_def(&mut self, variant_data: hir::VariantData) -> fhir::StructDef<'genv> {
236        fhir::StructDef {
237            refinement: self
238                .genv
239                .alloc(fhir::RefinementKind::Refined(fhir::RefinedBy::trivial())),
240            params: &[],
241            kind: fhir::StructKind::Transparent {
242                fields: self.genv.alloc_slice_fill_iter(
243                    variant_data.fields().iter().map(|f| self.lift_field_def(f)),
244                ),
245            },
246            invariants: &[],
247        }
248    }
249
250    pub(crate) fn lift_field_def(&mut self, field_def: &hir::FieldDef) -> fhir::FieldDef<'genv> {
251        let ty = self.lift_ty(field_def.ty);
252        fhir::FieldDef { ty, lifted: true }
253    }
254
255    fn lift_enum_def(&mut self, enum_def: hir::EnumDef) -> fhir::EnumDef<'genv> {
256        fhir::EnumDef {
257            refinement: self
258                .genv
259                .alloc(fhir::RefinementKind::Refined(fhir::RefinedBy::trivial())),
260            params: &[],
261            variants: self.genv.alloc_slice_fill_iter(
262                enum_def
263                    .variants
264                    .iter()
265                    .map(|variant| self.lift_enum_variant(variant)),
266            ),
267            invariants: &[],
268        }
269    }
270
271    pub(crate) fn lift_enum_variant(&mut self, variant: &hir::Variant) -> fhir::VariantDef<'genv> {
272        let item = self.genv.tcx().hir_expect_item(self.local_id());
273        let hir::ItemKind::Enum(_, generics, _) = &item.kind else { bug!("expected an enum") };
274
275        let fields = self.genv.alloc_slice_fill_iter(
276            variant
277                .data
278                .fields()
279                .iter()
280                .map(|field| self.lift_field_def(field)),
281        );
282
283        let ret = self.lift_variant_ret_inner(generics);
284
285        fhir::VariantDef {
286            def_id: variant.def_id,
287            params: &[],
288            fields,
289            ret,
290            span: variant.span,
291            lifted: true,
292        }
293    }
294
295    pub(crate) fn lift_variant_ret(&mut self) -> fhir::VariantRet<'genv> {
296        let item = self.genv.tcx().hir_expect_item(self.local_id());
297        let hir::ItemKind::Enum(_, generics, _) = &item.kind else { bug!("expected an enum") };
298        self.lift_variant_ret_inner(generics)
299    }
300
301    fn lift_variant_ret_inner(&mut self, generics: &hir::Generics) -> fhir::VariantRet<'genv> {
302        let kind = fhir::ExprKind::Record(&[]);
303        fhir::VariantRet {
304            enum_id: self.owner.resolved_id(),
305            idx: fhir::Expr {
306                kind,
307                fhir_id: self.next_fhir_id(),
308                span: generics.span.shrink_to_hi(),
309            },
310        }
311    }
312
313    fn lift_ty(&mut self, ty: &hir::Ty) -> fhir::Ty<'genv> {
314        let kind = match ty.kind {
315            hir::TyKind::Slice(ty) => {
316                let ty = self.lift_ty(ty);
317                let kind = fhir::BaseTyKind::Slice(self.genv.alloc(ty));
318                let bty = fhir::BaseTy { kind, fhir_id: self.next_fhir_id(), span: ty.span };
319                return fhir::Ty { kind: fhir::TyKind::BaseTy(bty), span: ty.span };
320            }
321            hir::TyKind::Array(ty, len) => {
322                let ty = self.lift_ty(ty);
323                fhir::TyKind::Array(self.genv.alloc(ty), self.lift_const_arg(len))
324            }
325            hir::TyKind::Ref(lft, mut_ty) => {
326                fhir::TyKind::Ref(self.lift_lifetime(lft), self.lift_mut_ty(mut_ty))
327            }
328            hir::TyKind::FnPtr(fn_ptr) => {
329                let bare_fn = self.lift_bare_fn(ty.span, fn_ptr);
330                fhir::TyKind::BareFn(self.genv.alloc(bare_fn))
331            }
332            hir::TyKind::Never => fhir::TyKind::Never,
333            hir::TyKind::Tup(tys) => {
334                let tys = self
335                    .genv
336                    .alloc_slice_fill_iter(tys.iter().map(|ty| self.lift_ty(ty)));
337                fhir::TyKind::Tuple(tys)
338            }
339            hir::TyKind::Path(qpath) => {
340                match self.lift_qpath(qpath) {
341                    Ok(qpath) => {
342                        let bty = fhir::BaseTy::from_qpath(qpath, self.next_fhir_id());
343                        fhir::TyKind::BaseTy(bty)
344                    }
345                    Err(err) => fhir::TyKind::Err(err),
346                }
347            }
348            hir::TyKind::Ptr(mut_ty) => {
349                let ty = self.lift_ty(mut_ty.ty);
350                fhir::TyKind::RawPtr(self.genv.alloc(ty), mut_ty.mutbl)
351            }
352            hir::TyKind::OpaqueDef(opaque_ty) => {
353                match self.lift_opaque_ty(opaque_ty) {
354                    Ok(opaque_ty) => {
355                        let opaque_ty = self.insert_opaque_ty(opaque_ty);
356                        fhir::TyKind::OpaqueDef(opaque_ty)
357                    }
358                    Err(err) => fhir::TyKind::Err(err),
359                }
360            }
361            hir::TyKind::TraitObject(poly_traits, lt) => {
362                let poly_traits = try_alloc_slice!(self.genv, poly_traits, |poly_trait| {
363                    if poly_trait.modifiers != hir::TraitBoundModifiers::NONE {
364                        return Err(self.emit_unsupported(&format!(
365                            "unsupported type: `{}`",
366                            rustc_hir_pretty::ty_to_string(&self.genv.tcx(), ty)
367                        )));
368                    }
369                    self.lift_poly_trait_ref(*poly_trait)
370                });
371                match poly_traits {
372                    Ok(poly_traits) => {
373                        let lft = self.lift_lifetime(lt.pointer());
374                        fhir::TyKind::TraitObject(poly_traits, lft, lt.tag())
375                    }
376                    Err(err) => fhir::TyKind::Err(err),
377                }
378            }
379            _ => {
380                fhir::TyKind::Err(self.emit_unsupported(&format!(
381                    "unsupported type: `{}`",
382                    rustc_hir_pretty::ty_to_string(&self.genv.tcx(), ty)
383                )))
384            }
385        };
386        fhir::Ty { kind, span: ty.span }
387    }
388
389    fn lift_bare_fn(&mut self, span: Span, fn_ptr: &hir::FnPtrTy) -> fhir::BareFnTy<'genv> {
390        let generic_params = self.genv.alloc_slice_fill_iter(
391            fn_ptr
392                .generic_params
393                .iter()
394                .map(|param| self.lift_generic_param(param)),
395        );
396        let decl = self.lift_fn_decl_inner(span, fn_ptr.decl);
397        fhir::BareFnTy {
398            safety: fn_ptr.safety,
399            abi: fn_ptr.abi,
400            generic_params,
401            decl: self.genv.alloc(decl),
402            param_idents: self.genv.alloc_slice(fn_ptr.param_idents),
403        }
404    }
405
406    fn lift_lifetime(&self, lft: &hir::Lifetime) -> fhir::Lifetime {
407        if let Some(resolved) = self.genv.tcx().named_bound_var(lft.hir_id) {
408            fhir::Lifetime::Resolved(resolved)
409        } else {
410            self.mk_lft_hole()
411        }
412    }
413
414    fn lift_mut_ty(&mut self, mut_ty: hir::MutTy) -> fhir::MutTy<'genv> {
415        let ty = self.lift_ty(mut_ty.ty);
416        fhir::MutTy { ty: self.genv.alloc(ty), mutbl: mut_ty.mutbl }
417    }
418
419    fn lift_qpath(&mut self, qpath: hir::QPath) -> Result<fhir::QPath<'genv>> {
420        match qpath {
421            hir::QPath::Resolved(qself, path) => {
422                let qself = if let Some(ty) = qself {
423                    let ty = self.lift_ty(ty);
424                    Some(self.genv.alloc(ty))
425                } else {
426                    None
427                };
428                let path = self.lift_path(path)?;
429                Ok(fhir::QPath::Resolved(qself, path))
430            }
431            hir::QPath::TypeRelative(qself, segment) => {
432                let qself = self.lift_ty(qself);
433                let segment = self.lift_path_segment(segment)?;
434                Ok(fhir::QPath::TypeRelative(self.genv.alloc(qself), self.genv.alloc(segment)))
435            }
436            hir::QPath::LangItem(_, _) => {
437                Err(self.emit_unsupported(&format!(
438                    "unsupported type: `{}`",
439                    rustc_hir_pretty::qpath_to_string(&self.genv.tcx(), &qpath)
440                )))
441            }
442        }
443    }
444
445    fn lift_path(&mut self, path: &hir::Path) -> Result<fhir::Path<'genv>> {
446        let Ok(res) = path.res.try_into() else {
447            return Err(self.emit_unsupported(&format!("unsupported res: `{:?}`", path.res)));
448        };
449        let segments =
450            try_alloc_slice!(self.genv, path.segments, |segment| self.lift_path_segment(segment))?;
451
452        Ok(fhir::Path {
453            res: self.fix_maybe_extern_id_in_res(res),
454            fhir_id: self.next_fhir_id(),
455            segments,
456            refine: &[],
457            span: path.span,
458        })
459    }
460
461    fn lift_path_segment(
462        &mut self,
463        segment: &hir::PathSegment,
464    ) -> Result<fhir::PathSegment<'genv>> {
465        let Ok(res) = segment.res.try_into() else {
466            return Err(self.emit_unsupported(&format!("unsupported res: `{:?}`", segment.res)));
467        };
468        let (args, bindings) = {
469            match segment.args {
470                Some(args) => {
471                    (
472                        self.lift_generic_args(args.args)?,
473                        self.lift_assoc_item_constraints(args.constraints)?,
474                    )
475                }
476                None => ([].as_slice(), [].as_slice()),
477            }
478        };
479
480        Ok(fhir::PathSegment { res, ident: segment.ident, args, constraints: bindings })
481    }
482
483    fn lift_generic_args(
484        &mut self,
485        args: &[hir::GenericArg<'_>],
486    ) -> Result<&'genv [fhir::GenericArg<'genv>]> {
487        try_alloc_slice!(self.genv, args, |arg| {
488            match arg {
489                hir::GenericArg::Lifetime(lft) => {
490                    let lft = self.lift_lifetime(lft);
491                    Ok(fhir::GenericArg::Lifetime(lft))
492                }
493                hir::GenericArg::Type(ty) => {
494                    let ty = self.lift_ty(ty.as_unambig_ty());
495                    Ok(fhir::GenericArg::Type(self.genv.alloc(ty)))
496                }
497                hir::GenericArg::Const(const_arg) => {
498                    Ok(fhir::GenericArg::Const(self.lift_const_arg(const_arg.as_unambig_ct())))
499                }
500                hir::GenericArg::Infer(_) => {
501                    Err(self.emit_unsupported("unsupported inference generic argument"))
502                }
503            }
504        })
505    }
506
507    fn lift_assoc_item_constraints(
508        &mut self,
509        constraints: &[hir::AssocItemConstraint<'_>],
510    ) -> Result<&'genv [fhir::AssocItemConstraint<'genv>]> {
511        try_alloc_slice!(self.genv, constraints, |cstr| {
512            let hir::AssocItemConstraintKind::Equality { term } = cstr.kind else {
513                return Err(self.emit_unsupported("unsupported type binding"));
514            };
515            let hir::Term::Ty(term) = term else {
516                return Err(self.emit_unsupported("unsupported type binding"));
517            };
518            let kind = fhir::AssocItemConstraintKind::Equality { term: self.lift_ty(term) };
519            Ok(fhir::AssocItemConstraint { ident: cstr.ident, kind })
520        })
521    }
522
523    fn lift_const_arg(&mut self, const_arg: &hir::ConstArg) -> fhir::ConstArg {
524        fhir::ConstArg { kind: fhir::ConstArgKind::Infer, span: const_arg.span() }
525    }
526
527    #[track_caller]
528    fn emit_unsupported(&self, note: &str) -> ErrorGuaranteed {
529        let tcx = self.genv.tcx();
530        let local_id = self.owner.local_id().def_id;
531        let span = tcx.def_span(local_id);
532        let def_kind = tcx.def_descr(local_id.to_def_id());
533        self.emit(errors::UnsupportedHir { span, def_kind, note })
534    }
535
536    fn next_fhir_id(&self) -> FhirId {
537        FhirId {
538            owner: FluxOwnerId::Rust(self.owner.local_id()),
539            local_id: self.local_id_gen.fresh(),
540        }
541    }
542
543    fn local_id(&self) -> LocalDefId {
544        self.owner.local_id().def_id
545    }
546
547    fn lift_fn_sig(&mut self, fn_sig: hir::FnSig) -> fhir::FnSig<'genv> {
548        let decl = self.lift_fn_decl_inner(fn_sig.span, fn_sig.decl);
549        fhir::FnSig { header: fn_sig.header, decl: self.genv.alloc(decl) }
550    }
551
552    pub(crate) fn lift_foreign_item(
553        &mut self,
554        foreign_item: hir::ForeignItem,
555    ) -> Result<fhir::ForeignItem<'genv>> {
556        let hir::ForeignItemKind::Fn(fnsig, _, _) = foreign_item.kind else {
557            return Err(self.emit_unsupported("Static and type in extern_item are not supported."));
558        };
559
560        let lifted_fnsig = self.lift_fn_sig(fnsig);
561        let fnsig = self.genv.alloc(lifted_fnsig);
562        let lifted_generics = self.lift_generics();
563        let generics = self.genv.alloc(lifted_generics);
564        let kind = fhir::ForeignItemKind::Fn(*fnsig, generics);
565
566        Ok(fhir::ForeignItem {
567            ident: foreign_item.ident,
568            kind,
569            owner_id: MaybeExternId::Local(foreign_item.owner_id),
570            span: foreign_item.span,
571        })
572    }
573
574    /// Fixes the def ids inside `res` to point to resolved ids.
575    fn fix_maybe_extern_id_in_res(&self, res: fhir::Res) -> fhir::Res {
576        match res {
577            fhir::Res::SelfTyParam { trait_ } => {
578                fhir::Res::SelfTyParam { trait_: self.fix_maybe_extern_id(trait_) }
579            }
580            fhir::Res::SelfTyAlias { alias_to, is_trait_impl } => {
581                fhir::Res::SelfTyAlias {
582                    alias_to: self.fix_maybe_extern_id(alias_to),
583                    is_trait_impl,
584                }
585            }
586            fhir::Res::Def(kind, def_id) => fhir::Res::Def(kind, self.fix_maybe_extern_id(def_id)),
587            _ => res,
588        }
589    }
590
591    /// Fixes a [`DefId`] that may correspond to a dummy local item for an extern spec to be the
592    /// "resolved id". This is to uphold the invariant that a [`DefId`] always corresponds to
593    /// the resolved item.
594    #[allow(
595        clippy::disallowed_methods,
596        reason = "we are fixing the def_id to uphold the invariant on extern specs"
597    )]
598    fn fix_maybe_extern_id(&self, def_id: DefId) -> DefId {
599        if let Some(def_id) = def_id.as_local() {
600            self.genv.maybe_extern_id(def_id).resolved_id()
601        } else {
602            def_id
603        }
604    }
605}
606
607pub mod errors {
608    use flux_errors::E0999;
609    use flux_macros::Diagnostic;
610    use rustc_span::Span;
611
612    #[derive(Diagnostic)]
613    #[diag(desugar_unsupported_hir, code = E0999)]
614    #[note]
615    pub(super) struct UnsupportedHir<'a> {
616        #[primary_span]
617        #[label]
618        pub span: Span,
619        pub def_kind: &'static str,
620        pub note: &'a str,
621    }
622}