Skip to main content

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