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            hir::ItemKind::Static(..) => (hir::Generics::empty(), fhir::ItemKind::Static(None)),
56            _ => {
57                Err(query_bug!(self.owner.resolved_id(), "unsupported item")).emit(&self.genv())?
58            }
59        };
60        Ok(fhir::Item { owner_id: self.owner, generics: self.lift_generics_inner(generics), kind })
61    }
62
63    pub(crate) fn lift_trait_item(&mut self) -> fhir::TraitItem<'genv> {
64        let hir_trait_item = self
65            .genv
66            .tcx()
67            .hir_trait_item(hir::TraitItemId { owner_id: self.owner.local_id() });
68        let generics = self.lift_generics_inner(hir_trait_item.generics);
69        let kind = match hir_trait_item.kind {
70            hir::TraitItemKind::Fn(fn_sig, ..) => fhir::TraitItemKind::Fn(self.lift_fn_sig(fn_sig)),
71            hir::TraitItemKind::Const(..) => fhir::TraitItemKind::Const,
72            hir::TraitItemKind::Type(..) => fhir::TraitItemKind::Type,
73        };
74        fhir::TraitItem { owner_id: self.owner, generics, kind }
75    }
76
77    pub(crate) fn lift_impl_item(&mut self) -> fhir::ImplItem<'genv> {
78        let hir_impl_item = self
79            .genv
80            .tcx()
81            .hir_impl_item(hir::ImplItemId { owner_id: self.owner.local_id() });
82        let generics = self.lift_generics_inner(hir_impl_item.generics);
83        let kind = match hir_impl_item.kind {
84            hir::ImplItemKind::Fn(fn_sig, ..) => fhir::ImplItemKind::Fn(self.lift_fn_sig(fn_sig)),
85            hir::ImplItemKind::Const(..) => fhir::ImplItemKind::Const,
86            hir::ImplItemKind::Type(..) => fhir::ImplItemKind::Type,
87        };
88        fhir::ImplItem { owner_id: self.owner, generics, kind }
89    }
90
91    pub(crate) fn lift_generics(&mut self) -> fhir::Generics<'genv> {
92        let generics = self.genv.tcx().hir_get_generics(self.local_id()).unwrap();
93        self.lift_generics_inner(generics)
94    }
95
96    pub(crate) fn lift_generic_param(
97        &mut self,
98        param: &hir::GenericParam,
99    ) -> fhir::GenericParam<'genv> {
100        let kind = match param.kind {
101            hir::GenericParamKind::Lifetime { .. } => fhir::GenericParamKind::Lifetime,
102            hir::GenericParamKind::Type { default, .. } => {
103                fhir::GenericParamKind::Type { default: default.map(|ty| self.lift_ty(ty)) }
104            }
105            hir::GenericParamKind::Const { ty, .. } => {
106                let ty = self.lift_ty(ty);
107                fhir::GenericParamKind::Const { ty }
108            }
109        };
110        fhir::GenericParam {
111            def_id: self.genv.maybe_extern_id(param.def_id),
112            name: param.name,
113            kind,
114        }
115    }
116
117    fn lift_generics_inner(&mut self, generics: &hir::Generics) -> fhir::Generics<'genv> {
118        let params = self.genv.alloc_slice_fill_iter(
119            generics
120                .params
121                .iter()
122                .map(|param| self.lift_generic_param(param)),
123        );
124
125        fhir::Generics { params, refinement_params: &[], predicates: None }
126    }
127
128    fn lift_generic_bound(
129        &mut self,
130        bound: &hir::GenericBound,
131    ) -> Result<fhir::GenericBound<'genv>> {
132        match bound {
133            hir::GenericBound::Trait(poly_trait_ref) => {
134                Ok(fhir::GenericBound::Trait(self.lift_poly_trait_ref(*poly_trait_ref)?))
135            }
136            hir::GenericBound::Outlives(lft) => {
137                let lft = self.lift_lifetime(lft);
138                Ok(fhir::GenericBound::Outlives(lft))
139            }
140            _ => Err(self.emit_unsupported(&format!("unsupported generic bound: `{bound:?}`"))),
141        }
142    }
143
144    fn lift_poly_trait_ref(
145        &mut self,
146        poly_trait_ref: hir::PolyTraitRef,
147    ) -> Result<fhir::PolyTraitRef<'genv>> {
148        let modifiers = match poly_trait_ref.modifiers {
149            rustc_hir::TraitBoundModifiers {
150                constness: rustc_hir::BoundConstness::Never,
151                polarity: rustc_hir::BoundPolarity::Positive,
152            } => fhir::TraitBoundModifier::None,
153            rustc_hir::TraitBoundModifiers {
154                constness: rustc_hir::BoundConstness::Never,
155                polarity: rustc_hir::BoundPolarity::Maybe(_),
156            } => fhir::TraitBoundModifier::Maybe,
157            _ => {
158                return Err(self.emit_unsupported(&format!(
159                    "unsupported trait modifiers: `{:?}`",
160                    poly_trait_ref.modifiers,
161                )));
162            }
163        };
164        let bound_generic_params = self.genv.alloc_slice_fill_iter(
165            poly_trait_ref
166                .bound_generic_params
167                .iter()
168                .map(|param| self.lift_generic_param(param)),
169        );
170        let trait_ref = self.lift_path(poly_trait_ref.trait_ref.path)?;
171        Ok(fhir::PolyTraitRef {
172            bound_generic_params,
173            refine_params: &[],
174            modifiers,
175            trait_ref,
176            span: poly_trait_ref.span,
177        })
178    }
179
180    pub(crate) fn lift_opaque_ty(
181        &mut self,
182        opaque_ty: &hir::OpaqueTy,
183    ) -> Result<fhir::OpaqueTy<'genv>> {
184        let bounds =
185            try_alloc_slice!(self.genv, &opaque_ty.bounds, |bound| self.lift_generic_bound(bound))?;
186
187        Ok(fhir::OpaqueTy { def_id: MaybeExternId::Local(opaque_ty.def_id), bounds })
188    }
189
190    pub(crate) fn lift_fn_header(&mut self) -> FnHeader {
191        let hir_id = self.genv.tcx().local_def_id_to_hir_id(self.local_id());
192        self.genv
193            .tcx()
194            .hir_fn_sig_by_hir_id(hir_id)
195            .expect("item does not have a `FnDecl`")
196            .header
197    }
198
199    pub(crate) fn lift_fn_decl(&mut self) -> fhir::FnDecl<'genv> {
200        let hir_id = self.genv.tcx().local_def_id_to_hir_id(self.local_id());
201        let fn_sig = self
202            .genv
203            .tcx()
204            .hir_fn_sig_by_hir_id(hir_id)
205            .expect("item does not have a `FnDecl`");
206
207        self.lift_fn_decl_inner(fn_sig.span, fn_sig.decl)
208    }
209
210    fn lift_fn_decl_inner(&mut self, span: Span, decl: &hir::FnDecl) -> fhir::FnDecl<'genv> {
211        let inputs = self
212            .genv
213            .alloc_slice_fill_iter(decl.inputs.iter().map(|ty| self.lift_ty(ty)));
214
215        let output =
216            fhir::FnOutput { params: &[], ensures: &[], ret: self.lift_fn_ret_ty(&decl.output) };
217
218        fhir::FnDecl { requires: &[], inputs, output, span, lifted: true }
219    }
220
221    fn lift_fn_ret_ty(&mut self, ret_ty: &hir::FnRetTy) -> fhir::Ty<'genv> {
222        match ret_ty {
223            hir::FnRetTy::DefaultReturn(_) => {
224                let kind = fhir::TyKind::Tuple(&[]);
225                fhir::Ty { kind, span: ret_ty.span() }
226            }
227            hir::FnRetTy::Return(ty) => self.lift_ty(ty),
228        }
229    }
230
231    fn lift_type_alias(&mut self, span: Span, ty: &hir::Ty) -> fhir::TyAlias<'genv> {
232        let ty = self.lift_ty(ty);
233        fhir::TyAlias { index: None, ty, span, lifted: true }
234    }
235
236    fn lift_struct_def(&mut self, variant_data: hir::VariantData) -> fhir::StructDef<'genv> {
237        fhir::StructDef {
238            refinement: self
239                .genv
240                .alloc(fhir::RefinementKind::Refined(fhir::RefinedBy::trivial())),
241            params: &[],
242            kind: fhir::StructKind::Transparent {
243                fields: self.genv.alloc_slice_fill_iter(
244                    variant_data.fields().iter().map(|f| self.lift_field_def(f)),
245                ),
246            },
247            invariants: &[],
248        }
249    }
250
251    pub(crate) fn lift_field_def(&mut self, field_def: &hir::FieldDef) -> fhir::FieldDef<'genv> {
252        let ty = self.lift_ty(field_def.ty);
253        fhir::FieldDef { ty, lifted: true }
254    }
255
256    fn lift_enum_def(&mut self, enum_def: hir::EnumDef) -> fhir::EnumDef<'genv> {
257        fhir::EnumDef {
258            refinement: self
259                .genv
260                .alloc(fhir::RefinementKind::Refined(fhir::RefinedBy::trivial())),
261            params: &[],
262            variants: self.genv.alloc_slice_fill_iter(
263                enum_def
264                    .variants
265                    .iter()
266                    .map(|variant| self.lift_enum_variant(variant)),
267            ),
268            invariants: &[],
269        }
270    }
271
272    pub(crate) fn lift_enum_variant(&mut self, variant: &hir::Variant) -> fhir::VariantDef<'genv> {
273        let item = self.genv.tcx().hir_expect_item(self.local_id());
274        let hir::ItemKind::Enum(_, generics, _) = &item.kind else { bug!("expected an enum") };
275
276        let fields = self.genv.alloc_slice_fill_iter(
277            variant
278                .data
279                .fields()
280                .iter()
281                .map(|field| self.lift_field_def(field)),
282        );
283
284        let ret = self.lift_variant_ret_inner(generics);
285
286        fhir::VariantDef {
287            def_id: variant.def_id,
288            params: &[],
289            fields,
290            ret,
291            span: variant.span,
292            lifted: true,
293        }
294    }
295
296    pub(crate) fn lift_variant_ret(&mut self) -> fhir::VariantRet<'genv> {
297        let item = self.genv.tcx().hir_expect_item(self.local_id());
298        let hir::ItemKind::Enum(_, generics, _) = &item.kind else { bug!("expected an enum") };
299        self.lift_variant_ret_inner(generics)
300    }
301
302    fn lift_variant_ret_inner(&mut self, generics: &hir::Generics) -> fhir::VariantRet<'genv> {
303        let kind = fhir::ExprKind::Record(&[]);
304        fhir::VariantRet {
305            enum_id: self.owner.resolved_id(),
306            idx: fhir::Expr {
307                kind,
308                fhir_id: self.next_fhir_id(),
309                span: generics.span.shrink_to_hi(),
310            },
311        }
312    }
313
314    fn lift_ty(&mut self, ty: &hir::Ty) -> fhir::Ty<'genv> {
315        let kind = match ty.kind {
316            hir::TyKind::Slice(ty) => {
317                let ty = self.lift_ty(ty);
318                let kind = fhir::BaseTyKind::Slice(self.genv.alloc(ty));
319                let bty = fhir::BaseTy { kind, fhir_id: self.next_fhir_id(), span: ty.span };
320                return fhir::Ty { kind: fhir::TyKind::BaseTy(bty), span: ty.span };
321            }
322            hir::TyKind::Array(ty, len) => {
323                let ty = self.lift_ty(ty);
324                fhir::TyKind::Array(self.genv.alloc(ty), self.lift_const_arg(len))
325            }
326            hir::TyKind::Ref(lft, mut_ty) => {
327                fhir::TyKind::Ref(self.lift_lifetime(lft), self.lift_mut_ty(mut_ty))
328            }
329            hir::TyKind::FnPtr(fn_ptr) => {
330                let bare_fn = self.lift_bare_fn(ty.span, fn_ptr);
331                fhir::TyKind::BareFn(self.genv.alloc(bare_fn))
332            }
333            hir::TyKind::Never => fhir::TyKind::Never,
334            hir::TyKind::Tup(tys) => {
335                let tys = self
336                    .genv
337                    .alloc_slice_fill_iter(tys.iter().map(|ty| self.lift_ty(ty)));
338                fhir::TyKind::Tuple(tys)
339            }
340            hir::TyKind::Path(qpath) => {
341                match self.lift_qpath(qpath) {
342                    Ok(qpath) => {
343                        let bty = fhir::BaseTy::from_qpath(qpath, self.next_fhir_id());
344                        fhir::TyKind::BaseTy(bty)
345                    }
346                    Err(err) => fhir::TyKind::Err(err),
347                }
348            }
349            hir::TyKind::Ptr(mut_ty) => {
350                let ty = self.lift_ty(mut_ty.ty);
351                let kind = fhir::BaseTyKind::RawPtr(self.genv.alloc(ty), mut_ty.mutbl);
352                fhir::TyKind::BaseTy(fhir::BaseTy {
353                    kind,
354                    fhir_id: self.next_fhir_id(),
355                    span: ty.span,
356                })
357            }
358            hir::TyKind::OpaqueDef(opaque_ty) => {
359                match self.lift_opaque_ty(opaque_ty) {
360                    Ok(opaque_ty) => {
361                        let opaque_ty = self.insert_opaque_ty(opaque_ty);
362                        fhir::TyKind::OpaqueDef(opaque_ty)
363                    }
364                    Err(err) => fhir::TyKind::Err(err),
365                }
366            }
367            hir::TyKind::TraitObject(poly_traits, lt) => {
368                let poly_traits = try_alloc_slice!(self.genv, poly_traits, |poly_trait| {
369                    if poly_trait.modifiers != hir::TraitBoundModifiers::NONE {
370                        return Err(self.emit_unsupported(&format!(
371                            "unsupported type: `{}`",
372                            rustc_hir_pretty::ty_to_string(&self.genv.tcx(), ty)
373                        )));
374                    }
375                    self.lift_poly_trait_ref(*poly_trait)
376                });
377                match poly_traits {
378                    Ok(poly_traits) => {
379                        let lft = self.lift_lifetime(lt.pointer());
380                        fhir::TyKind::TraitObject(poly_traits, lft, lt.tag())
381                    }
382                    Err(err) => fhir::TyKind::Err(err),
383                }
384            }
385            _ => {
386                fhir::TyKind::Err(self.emit_unsupported(&format!(
387                    "unsupported type: `{}`",
388                    rustc_hir_pretty::ty_to_string(&self.genv.tcx(), ty)
389                )))
390            }
391        };
392        fhir::Ty { kind, span: ty.span }
393    }
394
395    fn lift_bare_fn(&mut self, span: Span, fn_ptr: &hir::FnPtrTy) -> fhir::BareFnTy<'genv> {
396        let generic_params = self.genv.alloc_slice_fill_iter(
397            fn_ptr
398                .generic_params
399                .iter()
400                .map(|param| self.lift_generic_param(param)),
401        );
402        let decl = self.lift_fn_decl_inner(span, fn_ptr.decl);
403        fhir::BareFnTy {
404            safety: fn_ptr.safety,
405            abi: fn_ptr.abi,
406            generic_params,
407            decl: self.genv.alloc(decl),
408            param_idents: self.genv.alloc_slice(fn_ptr.param_idents),
409        }
410    }
411
412    fn lift_lifetime(&self, lft: &hir::Lifetime) -> fhir::Lifetime {
413        if let Some(resolved) = self.genv.tcx().named_bound_var(lft.hir_id) {
414            fhir::Lifetime::Resolved(resolved)
415        } else {
416            self.mk_lft_hole()
417        }
418    }
419
420    fn lift_mut_ty(&mut self, mut_ty: hir::MutTy) -> fhir::MutTy<'genv> {
421        let ty = self.lift_ty(mut_ty.ty);
422        fhir::MutTy { ty: self.genv.alloc(ty), mutbl: mut_ty.mutbl }
423    }
424
425    fn lift_qpath(&mut self, qpath: hir::QPath) -> Result<fhir::QPath<'genv>> {
426        match qpath {
427            hir::QPath::Resolved(qself, path) => {
428                let qself = if let Some(ty) = qself {
429                    let ty = self.lift_ty(ty);
430                    Some(self.genv.alloc(ty))
431                } else {
432                    None
433                };
434                let path = self.lift_path(path)?;
435                Ok(fhir::QPath::Resolved(qself, path))
436            }
437            hir::QPath::TypeRelative(qself, segment) => {
438                let qself = self.lift_ty(qself);
439                let segment = self.lift_path_segment(segment)?;
440                Ok(fhir::QPath::TypeRelative(self.genv.alloc(qself), self.genv.alloc(segment)))
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 { owner: FluxOwnerId::Rust(self.owner), local_id: self.local_id_gen.fresh() }
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), no_panic_if: None }
547    }
548
549    pub(crate) fn lift_foreign_item(
550        &mut self,
551        foreign_item: hir::ForeignItem,
552    ) -> Result<fhir::ForeignItem<'genv>> {
553        let kind = match foreign_item.kind {
554            hir::ForeignItemKind::Fn(fnsig, _, _) => {
555                let lifted_fnsig = self.lift_fn_sig(fnsig);
556                let fnsig = self.genv.alloc(lifted_fnsig);
557                let lifted_generics = self.lift_generics();
558                let generics = self.genv.alloc(lifted_generics);
559                fhir::ForeignItemKind::Fn(*fnsig, generics)
560            }
561            rustc_hir::ForeignItemKind::Static(ty, mutbl, safety) => {
562                let lifted_ty = self.lift_ty(ty);
563                let ty = self.genv.alloc(lifted_ty);
564                let lifted_generics = fhir::Generics::empty(self.genv);
565                let generics = self.genv.alloc(lifted_generics);
566                fhir::ForeignItemKind::Static(*ty, mutbl, safety, generics)
567            }
568            _ => {
569                return Err(self.emit_unsupported("unsupported foreign item kind"));
570            }
571        };
572        Ok(fhir::ForeignItem {
573            ident: foreign_item.ident,
574            kind,
575            owner_id: MaybeExternId::Local(foreign_item.owner_id),
576            span: foreign_item.span,
577        })
578    }
579
580    /// Fixes the def ids inside `res` to point to resolved ids.
581    fn fix_maybe_extern_id_in_res(&self, res: fhir::Res) -> fhir::Res {
582        match res {
583            fhir::Res::SelfTyParam { trait_ } => {
584                fhir::Res::SelfTyParam { trait_: self.fix_maybe_extern_id(trait_) }
585            }
586            fhir::Res::SelfTyAlias { alias_to, is_trait_impl } => {
587                fhir::Res::SelfTyAlias {
588                    alias_to: self.fix_maybe_extern_id(alias_to),
589                    is_trait_impl,
590                }
591            }
592            fhir::Res::Def(kind, def_id) => fhir::Res::Def(kind, self.fix_maybe_extern_id(def_id)),
593            _ => res,
594        }
595    }
596
597    /// Fixes a [`DefId`] that may correspond to a dummy local item for an extern spec to be the
598    /// "resolved id". This is to uphold the invariant that a [`DefId`] always corresponds to
599    /// the resolved item.
600    #[allow(
601        clippy::disallowed_methods,
602        reason = "we are fixing the def_id to uphold the invariant on extern specs"
603    )]
604    fn fix_maybe_extern_id(&self, def_id: DefId) -> DefId {
605        if let Some(def_id) = def_id.as_local() {
606            self.genv.maybe_extern_id(def_id).resolved_id()
607        } else {
608            def_id
609        }
610    }
611}
612
613pub mod errors {
614    use flux_errors::E0999;
615    use flux_macros::Diagnostic;
616    use rustc_span::Span;
617
618    #[derive(Diagnostic)]
619    #[diag(desugar_unsupported_hir, code = E0999)]
620    #[note]
621    pub(super) struct UnsupportedHir<'a> {
622        #[primary_span]
623        #[label]
624        pub span: Span,
625        pub def_kind: &'static str,
626        pub note: &'a str,
627    }
628}