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    fn lift_opaque_ty(&mut self, opaque_ty: &hir::OpaqueTy) -> Result<fhir::OpaqueTy<'genv>> {
180        let bounds =
181            try_alloc_slice!(self.genv, &opaque_ty.bounds, |bound| self.lift_generic_bound(bound))?;
182
183        Ok(fhir::OpaqueTy { def_id: MaybeExternId::Local(opaque_ty.def_id), bounds })
184    }
185
186    pub(crate) fn lift_fn_header(&mut self) -> FnHeader {
187        let hir_id = self.genv.tcx().local_def_id_to_hir_id(self.local_id());
188        self.genv
189            .tcx()
190            .hir_fn_sig_by_hir_id(hir_id)
191            .expect("item does not have a `FnDecl`")
192            .header
193    }
194
195    pub(crate) fn lift_fn_decl(&mut self) -> fhir::FnDecl<'genv> {
196        let hir_id = self.genv.tcx().local_def_id_to_hir_id(self.local_id());
197        let fn_sig = self
198            .genv
199            .tcx()
200            .hir_fn_sig_by_hir_id(hir_id)
201            .expect("item does not have a `FnDecl`");
202
203        self.lift_fn_decl_inner(fn_sig.span, fn_sig.decl)
204    }
205
206    fn lift_fn_decl_inner(&mut self, span: Span, decl: &hir::FnDecl) -> fhir::FnDecl<'genv> {
207        let inputs = self
208            .genv
209            .alloc_slice_fill_iter(decl.inputs.iter().map(|ty| self.lift_ty(ty)));
210
211        let output =
212            fhir::FnOutput { params: &[], ensures: &[], ret: self.lift_fn_ret_ty(&decl.output) };
213
214        fhir::FnDecl { requires: &[], inputs, output, span, lifted: true }
215    }
216
217    fn lift_fn_ret_ty(&mut self, ret_ty: &hir::FnRetTy) -> fhir::Ty<'genv> {
218        match ret_ty {
219            hir::FnRetTy::DefaultReturn(_) => {
220                let kind = fhir::TyKind::Tuple(&[]);
221                fhir::Ty { kind, span: ret_ty.span() }
222            }
223            hir::FnRetTy::Return(ty) => self.lift_ty(ty),
224        }
225    }
226
227    fn lift_type_alias(&mut self, span: Span, ty: &hir::Ty) -> fhir::TyAlias<'genv> {
228        let ty = self.lift_ty(ty);
229        fhir::TyAlias { index: None, ty, span, lifted: true }
230    }
231
232    fn lift_struct_def(&mut self, variant_data: hir::VariantData) -> fhir::StructDef<'genv> {
233        fhir::StructDef {
234            refinement: self
235                .genv
236                .alloc(fhir::RefinementKind::Refined(fhir::RefinedBy::trivial())),
237            params: &[],
238            kind: fhir::StructKind::Transparent {
239                fields: self.genv.alloc_slice_fill_iter(
240                    variant_data.fields().iter().map(|f| self.lift_field_def(f)),
241                ),
242            },
243            invariants: &[],
244        }
245    }
246
247    pub(crate) fn lift_field_def(&mut self, field_def: &hir::FieldDef) -> fhir::FieldDef<'genv> {
248        let ty = self.lift_ty(field_def.ty);
249        fhir::FieldDef { ty, lifted: true }
250    }
251
252    fn lift_enum_def(&mut self, enum_def: hir::EnumDef) -> fhir::EnumDef<'genv> {
253        fhir::EnumDef {
254            refinement: self
255                .genv
256                .alloc(fhir::RefinementKind::Refined(fhir::RefinedBy::trivial())),
257            params: &[],
258            variants: self.genv.alloc_slice_fill_iter(
259                enum_def
260                    .variants
261                    .iter()
262                    .map(|variant| self.lift_enum_variant(variant)),
263            ),
264            invariants: &[],
265        }
266    }
267
268    pub(crate) fn lift_enum_variant(&mut self, variant: &hir::Variant) -> fhir::VariantDef<'genv> {
269        let item = self.genv.tcx().hir_expect_item(self.local_id());
270        let hir::ItemKind::Enum(_, generics, _) = &item.kind else { bug!("expected an enum") };
271
272        let fields = self.genv.alloc_slice_fill_iter(
273            variant
274                .data
275                .fields()
276                .iter()
277                .map(|field| self.lift_field_def(field)),
278        );
279
280        let ret = self.lift_variant_ret_inner(generics);
281
282        fhir::VariantDef {
283            def_id: variant.def_id,
284            params: &[],
285            fields,
286            ret,
287            span: variant.span,
288            lifted: true,
289        }
290    }
291
292    pub(crate) fn lift_variant_ret(&mut self) -> fhir::VariantRet<'genv> {
293        let item = self.genv.tcx().hir_expect_item(self.local_id());
294        let hir::ItemKind::Enum(_, generics, _) = &item.kind else { bug!("expected an enum") };
295        self.lift_variant_ret_inner(generics)
296    }
297
298    fn lift_variant_ret_inner(&mut self, generics: &hir::Generics) -> fhir::VariantRet<'genv> {
299        let kind = fhir::ExprKind::Record(&[]);
300        fhir::VariantRet {
301            enum_id: self.owner.resolved_id(),
302            idx: fhir::Expr {
303                kind,
304                fhir_id: self.next_fhir_id(),
305                span: generics.span.shrink_to_hi(),
306            },
307        }
308    }
309
310    fn lift_ty(&mut self, ty: &hir::Ty) -> fhir::Ty<'genv> {
311        let kind = match ty.kind {
312            hir::TyKind::Slice(ty) => {
313                let ty = self.lift_ty(ty);
314                let kind = fhir::BaseTyKind::Slice(self.genv.alloc(ty));
315                let bty = fhir::BaseTy { kind, fhir_id: self.next_fhir_id(), span: ty.span };
316                return fhir::Ty { kind: fhir::TyKind::BaseTy(bty), span: ty.span };
317            }
318            hir::TyKind::Array(ty, len) => {
319                let ty = self.lift_ty(ty);
320                fhir::TyKind::Array(self.genv.alloc(ty), self.lift_const_arg(len))
321            }
322            hir::TyKind::Ref(lft, mut_ty) => {
323                fhir::TyKind::Ref(self.lift_lifetime(lft), self.lift_mut_ty(mut_ty))
324            }
325            hir::TyKind::FnPtr(fn_ptr) => {
326                let bare_fn = self.lift_bare_fn(ty.span, fn_ptr);
327                fhir::TyKind::BareFn(self.genv.alloc(bare_fn))
328            }
329            hir::TyKind::Never => fhir::TyKind::Never,
330            hir::TyKind::Tup(tys) => {
331                let tys = self
332                    .genv
333                    .alloc_slice_fill_iter(tys.iter().map(|ty| self.lift_ty(ty)));
334                fhir::TyKind::Tuple(tys)
335            }
336            hir::TyKind::Path(qpath) => {
337                match self.lift_qpath(qpath) {
338                    Ok(qpath) => {
339                        let bty = fhir::BaseTy::from_qpath(qpath, self.next_fhir_id());
340                        fhir::TyKind::BaseTy(bty)
341                    }
342                    Err(err) => fhir::TyKind::Err(err),
343                }
344            }
345            hir::TyKind::Ptr(mut_ty) => {
346                let ty = self.lift_ty(mut_ty.ty);
347                fhir::TyKind::RawPtr(self.genv.alloc(ty), mut_ty.mutbl)
348            }
349            hir::TyKind::OpaqueDef(opaque_ty) => {
350                match self.lift_opaque_ty(opaque_ty) {
351                    Ok(opaque_ty) => {
352                        let opaque_ty = self.insert_opaque_ty(opaque_ty);
353                        fhir::TyKind::OpaqueDef(opaque_ty)
354                    }
355                    Err(err) => fhir::TyKind::Err(err),
356                }
357            }
358            hir::TyKind::TraitObject(poly_traits, lt) => {
359                let poly_traits = try_alloc_slice!(self.genv, poly_traits, |poly_trait| {
360                    if poly_trait.modifiers != hir::TraitBoundModifiers::NONE {
361                        return Err(self.emit_unsupported(&format!(
362                            "unsupported type: `{}`",
363                            rustc_hir_pretty::ty_to_string(&self.genv.tcx(), ty)
364                        )));
365                    }
366                    self.lift_poly_trait_ref(*poly_trait)
367                });
368                match poly_traits {
369                    Ok(poly_traits) => {
370                        let lft = self.lift_lifetime(lt.pointer());
371                        fhir::TyKind::TraitObject(poly_traits, lft, lt.tag())
372                    }
373                    Err(err) => fhir::TyKind::Err(err),
374                }
375            }
376            _ => {
377                fhir::TyKind::Err(self.emit_unsupported(&format!(
378                    "unsupported type: `{}`",
379                    rustc_hir_pretty::ty_to_string(&self.genv.tcx(), ty)
380                )))
381            }
382        };
383        fhir::Ty { kind, span: ty.span }
384    }
385
386    fn lift_bare_fn(&mut self, span: Span, fn_ptr: &hir::FnPtrTy) -> fhir::BareFnTy<'genv> {
387        let generic_params = self.genv.alloc_slice_fill_iter(
388            fn_ptr
389                .generic_params
390                .iter()
391                .map(|param| self.lift_generic_param(param)),
392        );
393        let decl = self.lift_fn_decl_inner(span, fn_ptr.decl);
394        fhir::BareFnTy {
395            safety: fn_ptr.safety,
396            abi: fn_ptr.abi,
397            generic_params,
398            decl: self.genv.alloc(decl),
399            param_idents: self.genv.alloc_slice(fn_ptr.param_idents),
400        }
401    }
402
403    fn lift_lifetime(&self, lft: &hir::Lifetime) -> fhir::Lifetime {
404        if let Some(resolved) = self.genv.tcx().named_bound_var(lft.hir_id) {
405            fhir::Lifetime::Resolved(resolved)
406        } else {
407            self.mk_lft_hole()
408        }
409    }
410
411    fn lift_mut_ty(&mut self, mut_ty: hir::MutTy) -> fhir::MutTy<'genv> {
412        let ty = self.lift_ty(mut_ty.ty);
413        fhir::MutTy { ty: self.genv.alloc(ty), mutbl: mut_ty.mutbl }
414    }
415
416    fn lift_qpath(&mut self, qpath: hir::QPath) -> Result<fhir::QPath<'genv>> {
417        match qpath {
418            hir::QPath::Resolved(qself, path) => {
419                let qself = if let Some(ty) = qself {
420                    let ty = self.lift_ty(ty);
421                    Some(self.genv.alloc(ty))
422                } else {
423                    None
424                };
425                let path = self.lift_path(path)?;
426                Ok(fhir::QPath::Resolved(qself, path))
427            }
428            hir::QPath::TypeRelative(qself, segment) => {
429                let qself = self.lift_ty(qself);
430                let segment = self.lift_path_segment(segment)?;
431                Ok(fhir::QPath::TypeRelative(self.genv.alloc(qself), self.genv.alloc(segment)))
432            }
433            hir::QPath::LangItem(_, _) => {
434                Err(self.emit_unsupported(&format!(
435                    "unsupported type: `{}`",
436                    rustc_hir_pretty::qpath_to_string(&self.genv.tcx(), &qpath)
437                )))
438            }
439        }
440    }
441
442    fn lift_path(&mut self, path: &hir::Path) -> Result<fhir::Path<'genv>> {
443        let Ok(res) = path.res.try_into() else {
444            return Err(self.emit_unsupported(&format!("unsupported res: `{:?}`", path.res)));
445        };
446        let segments =
447            try_alloc_slice!(self.genv, path.segments, |segment| self.lift_path_segment(segment))?;
448
449        Ok(fhir::Path {
450            res: self.fix_maybe_extern_id_in_res(res),
451            fhir_id: self.next_fhir_id(),
452            segments,
453            refine: &[],
454            span: path.span,
455        })
456    }
457
458    fn lift_path_segment(
459        &mut self,
460        segment: &hir::PathSegment,
461    ) -> Result<fhir::PathSegment<'genv>> {
462        let Ok(res) = segment.res.try_into() else {
463            return Err(self.emit_unsupported(&format!("unsupported res: `{:?}`", segment.res)));
464        };
465        let (args, bindings) = {
466            match segment.args {
467                Some(args) => {
468                    (
469                        self.lift_generic_args(args.args)?,
470                        self.lift_assoc_item_constraints(args.constraints)?,
471                    )
472                }
473                None => ([].as_slice(), [].as_slice()),
474            }
475        };
476
477        Ok(fhir::PathSegment { res, ident: segment.ident, args, constraints: bindings })
478    }
479
480    fn lift_generic_args(
481        &mut self,
482        args: &[hir::GenericArg<'_>],
483    ) -> Result<&'genv [fhir::GenericArg<'genv>]> {
484        try_alloc_slice!(self.genv, args, |arg| {
485            match arg {
486                hir::GenericArg::Lifetime(lft) => {
487                    let lft = self.lift_lifetime(lft);
488                    Ok(fhir::GenericArg::Lifetime(lft))
489                }
490                hir::GenericArg::Type(ty) => {
491                    let ty = self.lift_ty(ty.as_unambig_ty());
492                    Ok(fhir::GenericArg::Type(self.genv.alloc(ty)))
493                }
494                hir::GenericArg::Const(const_arg) => {
495                    Ok(fhir::GenericArg::Const(self.lift_const_arg(const_arg.as_unambig_ct())))
496                }
497                hir::GenericArg::Infer(_) => {
498                    Err(self.emit_unsupported("unsupported inference generic argument"))
499                }
500            }
501        })
502    }
503
504    fn lift_assoc_item_constraints(
505        &mut self,
506        constraints: &[hir::AssocItemConstraint<'_>],
507    ) -> Result<&'genv [fhir::AssocItemConstraint<'genv>]> {
508        try_alloc_slice!(self.genv, constraints, |cstr| {
509            let hir::AssocItemConstraintKind::Equality { term } = cstr.kind else {
510                return Err(self.emit_unsupported("unsupported type binding"));
511            };
512            let hir::Term::Ty(term) = term else {
513                return Err(self.emit_unsupported("unsupported type binding"));
514            };
515            let kind = fhir::AssocItemConstraintKind::Equality { term: self.lift_ty(term) };
516            Ok(fhir::AssocItemConstraint { ident: cstr.ident, kind })
517        })
518    }
519
520    fn lift_const_arg(&mut self, const_arg: &hir::ConstArg) -> fhir::ConstArg {
521        fhir::ConstArg { kind: fhir::ConstArgKind::Infer, span: const_arg.span() }
522    }
523
524    #[track_caller]
525    fn emit_unsupported(&self, note: &str) -> ErrorGuaranteed {
526        let tcx = self.genv.tcx();
527        let local_id = self.owner.local_id().def_id;
528        let span = tcx.def_span(local_id);
529        let def_kind = tcx.def_descr(local_id.to_def_id());
530        self.emit(errors::UnsupportedHir { span, def_kind, note })
531    }
532
533    fn next_fhir_id(&self) -> FhirId {
534        FhirId {
535            owner: FluxOwnerId::Rust(self.owner.local_id()),
536            local_id: self.local_id_gen.fresh(),
537        }
538    }
539
540    fn local_id(&self) -> LocalDefId {
541        self.owner.local_id().def_id
542    }
543
544    fn lift_fn_sig(&mut self, fn_sig: hir::FnSig) -> fhir::FnSig<'genv> {
545        let decl = self.lift_fn_decl_inner(fn_sig.span, fn_sig.decl);
546        fhir::FnSig { header: fn_sig.header, decl: self.genv.alloc(decl) }
547    }
548
549    pub(crate) fn lift_foreign_item(
550        &mut self,
551        foreign_item: hir::ForeignItem,
552    ) -> Result<fhir::ForeignItem<'genv>> {
553        let hir::ForeignItemKind::Fn(fnsig, _, _) = foreign_item.kind else {
554            return Err(self.emit_unsupported("Static and type in extern_item are not supported."));
555        };
556
557        let lifted_fnsig = self.lift_fn_sig(fnsig);
558        let fnsig = self.genv.alloc(lifted_fnsig);
559        let lifted_generics = self.lift_generics();
560        let generics = self.genv.alloc(lifted_generics);
561        let kind = fhir::ForeignItemKind::Fn(*fnsig, generics);
562
563        Ok(fhir::ForeignItem {
564            ident: foreign_item.ident,
565            kind,
566            owner_id: MaybeExternId::Local(foreign_item.owner_id),
567            span: foreign_item.span,
568        })
569    }
570
571    /// Fixes the def ids inside `res` to point to resolved ids.
572    fn fix_maybe_extern_id_in_res(&self, res: fhir::Res) -> fhir::Res {
573        match res {
574            fhir::Res::SelfTyParam { trait_ } => {
575                fhir::Res::SelfTyParam { trait_: self.fix_maybe_extern_id(trait_) }
576            }
577            fhir::Res::SelfTyAlias { alias_to, is_trait_impl } => {
578                fhir::Res::SelfTyAlias {
579                    alias_to: self.fix_maybe_extern_id(alias_to),
580                    is_trait_impl,
581                }
582            }
583            fhir::Res::Def(kind, def_id) => fhir::Res::Def(kind, self.fix_maybe_extern_id(def_id)),
584            _ => res,
585        }
586    }
587
588    /// Fixes a [`DefId`] that may correspond to a dummy local item for an extern spec to be the
589    /// "resolved id". This is to upholad the invariant that a [`DefId`] always corresponds to
590    /// the resolved item.
591    #[allow(
592        clippy::disallowed_methods,
593        reason = "we are fixing the def_id to uphold the invariant on extern specs"
594    )]
595    fn fix_maybe_extern_id(&self, def_id: DefId) -> DefId {
596        if let Some(def_id) = def_id.as_local() {
597            self.genv.maybe_extern_id(def_id).resolved_id()
598        } else {
599            def_id
600        }
601    }
602}
603
604pub mod errors {
605    use flux_errors::E0999;
606    use flux_macros::Diagnostic;
607    use rustc_span::Span;
608
609    #[derive(Diagnostic)]
610    #[diag(desugar_unsupported_hir, code = E0999)]
611    #[note]
612    pub(super) struct UnsupportedHir<'a> {
613        #[primary_span]
614        #[label]
615        pub span: Span,
616        pub def_kind: &'static str,
617        pub note: &'a str,
618    }
619}