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        }
437    }
438
439    fn lift_path(&mut self, path: &hir::Path) -> Result<fhir::Path<'genv>> {
440        let Ok(res) = path.res.try_into() else {
441            return Err(self.emit_unsupported(&format!("unsupported res: `{:?}`", path.res)));
442        };
443        let segments =
444            try_alloc_slice!(self.genv, path.segments, |segment| self.lift_path_segment(segment))?;
445
446        Ok(fhir::Path {
447            res: self.fix_maybe_extern_id_in_res(res),
448            fhir_id: self.next_fhir_id(),
449            segments,
450            refine: &[],
451            span: path.span,
452        })
453    }
454
455    fn lift_path_segment(
456        &mut self,
457        segment: &hir::PathSegment,
458    ) -> Result<fhir::PathSegment<'genv>> {
459        let Ok(res) = segment.res.try_into() else {
460            return Err(self.emit_unsupported(&format!("unsupported res: `{:?}`", segment.res)));
461        };
462        let (args, bindings) = {
463            match segment.args {
464                Some(args) => {
465                    (
466                        self.lift_generic_args(args.args)?,
467                        self.lift_assoc_item_constraints(args.constraints)?,
468                    )
469                }
470                None => ([].as_slice(), [].as_slice()),
471            }
472        };
473
474        Ok(fhir::PathSegment { res, ident: segment.ident, args, constraints: bindings })
475    }
476
477    fn lift_generic_args(
478        &mut self,
479        args: &[hir::GenericArg<'_>],
480    ) -> Result<&'genv [fhir::GenericArg<'genv>]> {
481        try_alloc_slice!(self.genv, args, |arg| {
482            match arg {
483                hir::GenericArg::Lifetime(lft) => {
484                    let lft = self.lift_lifetime(lft);
485                    Ok(fhir::GenericArg::Lifetime(lft))
486                }
487                hir::GenericArg::Type(ty) => {
488                    let ty = self.lift_ty(ty.as_unambig_ty());
489                    Ok(fhir::GenericArg::Type(self.genv.alloc(ty)))
490                }
491                hir::GenericArg::Const(const_arg) => {
492                    Ok(fhir::GenericArg::Const(self.lift_const_arg(const_arg.as_unambig_ct())))
493                }
494                hir::GenericArg::Infer(_) => {
495                    Err(self.emit_unsupported("unsupported inference generic argument"))
496                }
497            }
498        })
499    }
500
501    fn lift_assoc_item_constraints(
502        &mut self,
503        constraints: &[hir::AssocItemConstraint<'_>],
504    ) -> Result<&'genv [fhir::AssocItemConstraint<'genv>]> {
505        try_alloc_slice!(self.genv, constraints, |cstr| {
506            let hir::AssocItemConstraintKind::Equality { term } = cstr.kind else {
507                return Err(self.emit_unsupported("unsupported type binding"));
508            };
509            let hir::Term::Ty(term) = term else {
510                return Err(self.emit_unsupported("unsupported type binding"));
511            };
512            let kind = fhir::AssocItemConstraintKind::Equality { term: self.lift_ty(term) };
513            Ok(fhir::AssocItemConstraint { ident: cstr.ident, kind })
514        })
515    }
516
517    fn lift_const_arg(&mut self, const_arg: &hir::ConstArg) -> fhir::ConstArg {
518        fhir::ConstArg { kind: fhir::ConstArgKind::Infer, span: const_arg.span() }
519    }
520
521    #[track_caller]
522    fn emit_unsupported(&self, note: &str) -> ErrorGuaranteed {
523        let tcx = self.genv.tcx();
524        let local_id = self.owner.local_id().def_id;
525        let span = tcx.def_span(local_id);
526        let def_kind = tcx.def_descr(local_id.to_def_id());
527        self.emit(errors::UnsupportedHir { span, def_kind, note })
528    }
529
530    fn next_fhir_id(&self) -> FhirId {
531        FhirId {
532            owner: FluxOwnerId::Rust(self.owner.local_id()),
533            local_id: self.local_id_gen.fresh(),
534        }
535    }
536
537    fn local_id(&self) -> LocalDefId {
538        self.owner.local_id().def_id
539    }
540
541    fn lift_fn_sig(&mut self, fn_sig: hir::FnSig) -> fhir::FnSig<'genv> {
542        let decl = self.lift_fn_decl_inner(fn_sig.span, fn_sig.decl);
543        fhir::FnSig { header: fn_sig.header, decl: self.genv.alloc(decl) }
544    }
545
546    pub(crate) fn lift_foreign_item(
547        &mut self,
548        foreign_item: hir::ForeignItem,
549    ) -> Result<fhir::ForeignItem<'genv>> {
550        let hir::ForeignItemKind::Fn(fnsig, _, _) = foreign_item.kind else {
551            return Err(self.emit_unsupported("Static and type in extern_item are not supported."));
552        };
553
554        let lifted_fnsig = self.lift_fn_sig(fnsig);
555        let fnsig = self.genv.alloc(lifted_fnsig);
556        let lifted_generics = self.lift_generics();
557        let generics = self.genv.alloc(lifted_generics);
558        let kind = fhir::ForeignItemKind::Fn(*fnsig, generics);
559
560        Ok(fhir::ForeignItem {
561            ident: foreign_item.ident,
562            kind,
563            owner_id: MaybeExternId::Local(foreign_item.owner_id),
564            span: foreign_item.span,
565        })
566    }
567
568    /// Fixes the def ids inside `res` to point to resolved ids.
569    fn fix_maybe_extern_id_in_res(&self, res: fhir::Res) -> fhir::Res {
570        match res {
571            fhir::Res::SelfTyParam { trait_ } => {
572                fhir::Res::SelfTyParam { trait_: self.fix_maybe_extern_id(trait_) }
573            }
574            fhir::Res::SelfTyAlias { alias_to, is_trait_impl } => {
575                fhir::Res::SelfTyAlias {
576                    alias_to: self.fix_maybe_extern_id(alias_to),
577                    is_trait_impl,
578                }
579            }
580            fhir::Res::Def(kind, def_id) => fhir::Res::Def(kind, self.fix_maybe_extern_id(def_id)),
581            _ => res,
582        }
583    }
584
585    /// Fixes a [`DefId`] that may correspond to a dummy local item for an extern spec to be the
586    /// "resolved id". This is to uphold the invariant that a [`DefId`] always corresponds to
587    /// the resolved item.
588    #[allow(
589        clippy::disallowed_methods,
590        reason = "we are fixing the def_id to uphold the invariant on extern specs"
591    )]
592    fn fix_maybe_extern_id(&self, def_id: DefId) -> DefId {
593        if let Some(def_id) = def_id.as_local() {
594            self.genv.maybe_extern_id(def_id).resolved_id()
595        } else {
596            def_id
597        }
598    }
599}
600
601pub mod errors {
602    use flux_errors::E0999;
603    use flux_macros::Diagnostic;
604    use rustc_span::Span;
605
606    #[derive(Diagnostic)]
607    #[diag(desugar_unsupported_hir, code = E0999)]
608    #[note]
609    pub(super) struct UnsupportedHir<'a> {
610        #[primary_span]
611        #[label]
612        pub span: Span,
613        pub def_kind: &'static str,
614        pub note: &'a str,
615    }
616}