hax_frontend_exporter/
rustc_utils.rs

1use crate::prelude::*;
2use rustc_middle::ty;
3
4#[extension_traits::extension(pub trait SubstBinder)]
5impl<'tcx, T: ty::TypeFoldable<ty::TyCtxt<'tcx>>> ty::Binder<'tcx, T> {
6    fn subst(
7        self,
8        tcx: ty::TyCtxt<'tcx>,
9        generics: &[ty::GenericArg<'tcx>],
10    ) -> ty::Binder<'tcx, T> {
11        ty::EarlyBinder::bind(self).instantiate(tcx, generics)
12    }
13}
14
15#[tracing::instrument(skip(s))]
16pub(crate) fn get_variant_information<'s, S: UnderOwnerState<'s>>(
17    adt_def: &ty::AdtDef<'s>,
18    variant_index: rustc_abi::VariantIdx,
19    s: &S,
20) -> VariantInformations {
21    fn is_named<'s, I: std::iter::Iterator<Item = &'s ty::FieldDef> + Clone>(it: I) -> bool {
22        it.clone()
23            .any(|field| field.name.to_ident_string().parse::<u64>().is_err())
24    }
25    let variant_def = adt_def.variant(variant_index);
26    let variant = variant_def.def_id;
27    let constructs_type: DefId = adt_def.did().sinto(s);
28    let kind = if adt_def.is_struct() {
29        let named = is_named(adt_def.all_fields());
30        VariantKind::Struct { named }
31    } else if adt_def.is_union() {
32        VariantKind::Union
33    } else {
34        let named = is_named(variant_def.fields.iter());
35        let index = variant_index.into();
36        VariantKind::Enum { index, named }
37    };
38    VariantInformations {
39        typ: constructs_type.clone(),
40        variant: variant.sinto(s),
41        kind,
42        type_namespace: match &constructs_type.parent {
43            Some(parent) => parent.clone(),
44            None => {
45                let span = s.base().tcx.def_span(variant);
46                fatal!(
47                    s[span],
48                    "Type {:#?} appears to have no parent",
49                    constructs_type
50                )
51            }
52        },
53    }
54}
55
56#[tracing::instrument(skip(sess))]
57pub fn translate_span(span: rustc_span::Span, sess: &rustc_session::Session) -> Span {
58    let smap: &rustc_span::source_map::SourceMap = sess.psess.source_map();
59    let filename = smap.span_to_filename(span);
60
61    let lo = smap.lookup_char_pos(span.lo());
62    let hi = smap.lookup_char_pos(span.hi());
63
64    Span {
65        lo: lo.into(),
66        hi: hi.into(),
67        filename: filename.sinto(&()),
68        rust_span_data: Some(span.data()),
69    }
70}
71
72pub trait HasParamEnv<'tcx> {
73    fn param_env(&self) -> ty::ParamEnv<'tcx>;
74    fn typing_env(&self) -> ty::TypingEnv<'tcx>;
75}
76
77impl<'tcx, S: UnderOwnerState<'tcx>> HasParamEnv<'tcx> for S {
78    fn param_env(&self) -> ty::ParamEnv<'tcx> {
79        self.base().tcx.param_env(self.owner_id())
80    }
81    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
82        ty::TypingEnv {
83            param_env: self.param_env(),
84            typing_mode: ty::TypingMode::PostAnalysis,
85        }
86    }
87}
88
89#[tracing::instrument(skip(s))]
90pub(crate) fn attribute_from_scope<'tcx, S: ExprState<'tcx>>(
91    s: &S,
92    scope: &rustc_middle::middle::region::Scope,
93) -> (Option<rustc_hir::hir_id::HirId>, Vec<Attribute>) {
94    let owner = s.owner_id();
95    let tcx = s.base().tcx;
96    let scope_tree = tcx.region_scope_tree(owner);
97    let hir_id = scope.hir_id(scope_tree);
98    let tcx = s.base().tcx;
99    let attributes = hir_id
100        .map(|hir_id| tcx.hir_attrs(hir_id).sinto(s))
101        .unwrap_or_default();
102    (hir_id, attributes)
103}
104
105/// Gets the closest ancestor of `id` that is the id of a type.
106pub fn get_closest_parent_type(
107    tcx: &ty::TyCtxt,
108    id: rustc_span::def_id::DefId,
109) -> rustc_span::def_id::DefId {
110    match tcx.def_kind(id) {
111        rustc_hir::def::DefKind::Union
112        | rustc_hir::def::DefKind::Struct
113        | rustc_hir::def::DefKind::Enum => id,
114        _ => get_closest_parent_type(tcx, tcx.parent(id)),
115    }
116}