Skip to main content

charon_driver/hax/types/
def_id.rs

1//! This module contains the type definition for `DefId` and the types
2//! `DefId` depends on.
3//!
4//! This is purposely a very small isolated module:
5//! `hax-engine-names-extract` uses those types, but we don't want
6//! `hax-engine-names-extract` to have a build dependency on the whole
7//! frontend, that double the build times for the Rust part of hax.
8
9use crate::hax::AdtInto;
10use crate::hax::prelude::*;
11use charon_lib::ast::HashConsed;
12
13use itertools::Itertools;
14pub use rustc_middle::mir::Promoted as PromotedId;
15pub use rustc_middle::mir::interpret::AllocId as RAllocId;
16use rustc_span::DUMMY_SP;
17use rustc_trait_elaboration::param_env_from_clauses;
18use {rustc_hir as hir, rustc_hir::def_id::DefId as RDefId, rustc_middle::ty};
19
20sinto_reexport!(hir::Safety);
21sinto_reexport!(hir::Mutability);
22sinto_reexport!(hir::def::CtorKind);
23sinto_reexport!(hir::def::MacroKinds);
24sinto_reexport!(hir::def::CtorOf);
25sinto_reexport!(rustc_span::symbol::Symbol);
26sinto_reexport!(rustc_span::symbol::ByteSymbol);
27
28/// Reflects [`rustc_hir::def::DefKind`]
29#[derive(AdtInto)]
30#[args(<S>, from: rustc_hir::def::DefKind, state: S as tcx)]
31#[derive(Debug, Clone, PartialEq, Eq, Hash)]
32pub enum DefKind {
33    Mod,
34    Struct,
35    Union,
36    Enum,
37    Variant,
38    Trait,
39    TyAlias,
40    ForeignTy,
41    TraitAlias,
42    AssocTy,
43    TyParam,
44    Fn,
45    #[disable_mapping]
46    FnPtr,
47    Const,
48    ConstParam,
49    Static {
50        safety: Safety,
51        mutability: Mutability,
52        nested: bool,
53    },
54    Ctor(CtorOf, CtorKind),
55    AssocFn,
56    AssocConst,
57    Macro(MacroKinds),
58    ExternCrate,
59    Use,
60    ForeignMod,
61    AnonConst,
62    #[disable_mapping]
63    /// Added by hax: promoted constants don't have def_ids in rustc but they do in hax.
64    PromotedConst,
65    OpaqueTy,
66    Field,
67    LifetimeParam,
68    GlobalAsm,
69    Impl {
70        of_trait: bool,
71    },
72    Closure,
73    SyntheticCoroutineBody,
74    TestBinderConstraints,
75}
76
77/// The crate name under which synthetic items are exported under.
78const SYNTHETIC_CRATE_NAME: &str = "<synthetic>";
79
80/// Reflects [`rustc_hir::def_id::DefId`], augmented to also give ids to promoted constants (which
81/// have their own ad-hoc numbering scheme in rustc for now).
82#[derive(Clone, PartialEq, Eq)]
83pub struct DefId {
84    pub(crate) contents: HashConsed<DefIdContents>,
85}
86
87#[derive(Debug, Clone, PartialEq, Eq, Hash)]
88pub struct DefIdContents {
89    pub base: DefIdBase,
90    /// The kind of definition this `DefId` points to.
91    pub kind: crate::hax::DefKind,
92}
93
94#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
95pub enum DefIdBase {
96    Real(RDefId),
97    Promoted(RDefId, PromotedId),
98    /// This represents the context made of the trait impl generics plus the associated item
99    /// generics declared in the trait. We use that context to trait solve the mapping from
100    /// declared method generics to implemented method generics.
101    ImplAssocItem(VirtualImplAssocItem),
102    /// A fictitious item, used to make monomorphization and other shenanigans easier for builtin
103    /// types.
104    Synthetic(SyntheticItem),
105    /// A global standing for an anonymous const-eval allocation (e.g. the `[42]` in `&[42]`), so
106    /// that pointers to the same memory stay aliased.
107    Alloc(RAllocId),
108}
109
110#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
111pub struct VirtualImplAssocItem {
112    /// The trait impl.
113    pub trait_impl_id: RDefId,
114    /// The item declaration.
115    pub item_decl_id: RDefId,
116    /// The item implementation.
117    pub item_impl_id: RDefId,
118}
119
120impl VirtualImplAssocItem {
121    pub fn new(trait_impl_id: RDefId, item_decl_id: RDefId, item_impl_id: RDefId) -> Self {
122        Self {
123            trait_impl_id,
124            item_decl_id,
125            item_impl_id,
126        }
127    }
128
129    /// Arguments just for the item itself (works for both decl and impl), valid in the virtual
130    /// item context.
131    fn own_args<'tcx>(&self, s: &impl BaseState<'tcx>) -> Vec<ty::GenericArg<'tcx>> {
132        let tcx = s.base().tcx;
133        DefId::make_assoc_item_impl(s, *self)
134            .generics_of(s)
135            .own_params
136            .iter()
137            .map(|param| tcx.mk_param_from_def(param))
138            .collect()
139    }
140
141    /// Construct generic args for the item declaration, valid in the virtual item context.
142    pub fn args_for_item_decl<'tcx>(
143        &self,
144        s: &impl BaseState<'tcx>,
145        trait_args: ty::GenericArgsRef<'tcx>,
146    ) -> ty::GenericArgsRef<'tcx> {
147        let tcx = s.base().tcx;
148        tcx.mk_args_from_iter(trait_args.iter().chain(self.own_args(s)))
149    }
150
151    /// Construct generic args for the item implementation, valid in the virtual item context.
152    pub fn args_for_item_impl<'tcx>(
153        &self,
154        s: &impl BaseState<'tcx>,
155        impl_args: ty::GenericArgsRef<'tcx>,
156    ) -> ty::GenericArgsRef<'tcx> {
157        let tcx = s.base().tcx;
158        tcx.mk_args_from_iter(impl_args.iter().chain(self.own_args(s)))
159    }
160
161    /// Construct generic args for the item declaration, valid in the virtual item context.
162    pub fn identity_args_for_item_decl<'tcx>(
163        &self,
164        s: &impl BaseState<'tcx>,
165    ) -> ty::GenericArgsRef<'tcx> {
166        let tcx = s.base().tcx;
167        let impl_trait_ref = tcx
168            .impl_trait_ref(self.trait_impl_id)
169            .instantiate_identity()
170            .skip_normalization();
171        self.args_for_item_decl(s, impl_trait_ref.args)
172    }
173}
174
175impl DefIdContents {
176    pub fn make_def_id<'tcx, S: BaseState<'tcx>>(self, _s: &S) -> DefId {
177        let contents = HashConsed::new(self);
178        DefId { contents }
179    }
180}
181
182impl rustc_trait_elaboration::ItemId for DefId {
183    type State<'tcx> = StateWithBase<'tcx>;
184
185    fn from_rust_def_id<'tcx>(s: &Self::State<'tcx>, def_id: RDefId) -> Self {
186        def_id.sinto(s)
187    }
188
189    fn generics_of<'tcx>(&self, s: &Self::State<'tcx>) -> &'tcx ty::Generics {
190        DefId::generics_of(self, s)
191    }
192
193    fn param_env<'tcx>(&self, s: &Self::State<'tcx>) -> ty::ParamEnv<'tcx> {
194        DefId::param_env(self, s)
195    }
196
197    fn predicates_defined_on<'tcx>(
198        &self,
199        s: &Self::State<'tcx>,
200        direction: PredicateDirection,
201    ) -> ItemPredicates<'tcx, Self> {
202        let tcx = s.base().tcx;
203        match self.base {
204            DefIdBase::Real(def_id) => ItemPredicates::defined_on(tcx, s, def_id, direction),
205            DefIdBase::ImplAssocItem(id) => {
206                let item_args = id.identity_args_for_item_decl(s);
207                ItemPredicates::defined_on(tcx, s, id.item_decl_id, direction)
208                    .instantiate(tcx, item_args)
209            }
210            DefIdBase::Synthetic(synthetic) => {
211                synthetic.predicates_defined_on(s, self.clone(), direction)
212            }
213            DefIdBase::Promoted(..) | DefIdBase::Alloc(..) => {
214                ItemPredicates::new_unmapped(DUMMY_SP, [])
215            }
216        }
217    }
218
219    fn self_pred<'tcx>(&self, s: &Self::State<'tcx>) -> Option<ty::PolyTraitRef<'tcx>> {
220        let tcx = s.base().tcx;
221        match self.base {
222            DefIdBase::Real(def_id) => def_id.self_pred(&tcx),
223            _ => None,
224        }
225    }
226
227    fn as_identity_assoc_ty<'tcx>(&self, s: &Self::State<'tcx>) -> Option<ty::Ty<'tcx>> {
228        let tcx = s.base().tcx;
229        match self.base {
230            DefIdBase::Real(def_id) => def_id.as_identity_assoc_ty(&tcx),
231            _ => None,
232        }
233    }
234
235    fn typeck_parent<'tcx>(&self, s: &Self::State<'tcx>) -> Option<Self> {
236        let tcx = s.base().tcx;
237        match self.base {
238            DefIdBase::Real(def_id) => def_id.typeck_parent(&tcx).map(|def_id| def_id.sinto(s)),
239            DefIdBase::Promoted(def_id, ..) => Some(tcx.typeck_root_def_id(def_id).sinto(s)),
240            DefIdBase::ImplAssocItem(..) | DefIdBase::Synthetic(..) | DefIdBase::Alloc(..) => None,
241        }
242    }
243
244    fn parent_of_assoc<'tcx>(&self, s: &Self::State<'tcx>) -> Option<Self> {
245        let tcx = s.base().tcx;
246        match self.base {
247            DefIdBase::Real(def_id) => def_id.parent_of_assoc(&tcx).map(|def_id| def_id.sinto(s)),
248            DefIdBase::ImplAssocItem(id) => Some(id.trait_impl_id.sinto(s)),
249            _ => None,
250        }
251    }
252
253    fn parent_for_clauses<'tcx>(&self, s: &Self::State<'tcx>) -> Option<Self> {
254        let tcx = s.base().tcx;
255        match self.base {
256            DefIdBase::Real(def_id) => def_id
257                .parent_for_clauses(&tcx)
258                .map(|def_id| def_id.sinto(s)),
259            DefIdBase::ImplAssocItem(id) => Some(id.trait_impl_id.sinto(s)),
260            DefIdBase::Promoted(def_id, _) => Some(def_id.sinto(s)),
261            DefIdBase::Synthetic(..) | DefIdBase::Alloc(..) => None,
262        }
263    }
264
265    fn takes_explicit_self_clause<'tcx>(&self, s: &Self::State<'tcx>) -> bool {
266        let tcx = s.base().tcx;
267        match self.base {
268            DefIdBase::Real(def_id) | DefIdBase::Promoted(def_id, ..) => {
269                def_id.takes_explicit_self_clause(&tcx)
270            }
271            DefIdBase::ImplAssocItem(id) => id.item_decl_id.takes_explicit_self_clause(&tcx),
272            DefIdBase::Synthetic(..) | DefIdBase::Alloc(..) => false,
273        }
274    }
275
276    fn find_in_impl<'tcx>(&self, s: &Self::State<'tcx>, trait_impl: &Self) -> Option<Self> {
277        let tcx = s.base().tcx;
278        let trait_impl = trait_impl.as_real_def_id()?;
279        match self.base {
280            DefIdBase::Real(def_id) => def_id
281                .find_in_impl(&tcx, &trait_impl)
282                .map(|def_id| def_id.sinto(s)),
283            _ => None,
284        }
285    }
286}
287
288impl DefId {
289    /// The rustc def_id corresponding to this item, if there is one. Promoted constants don't have
290    /// a rustc def_id.
291    pub fn as_real_def_id(&self) -> Option<RDefId> {
292        match self.base {
293            DefIdBase::Real(did) => Some(did),
294            _ => None,
295        }
296    }
297    /// The rustc def_id of this item. Panics if this is not a real rustc item.
298    pub fn real_rust_def_id(&self) -> RDefId {
299        self.as_real_def_id().unwrap()
300    }
301    /// The def_id of this item or its parent if this is a promoted constant.
302    pub fn as_real_or_promoted(&self) -> Option<RDefId> {
303        match self.base {
304            DefIdBase::Real(did) | DefIdBase::Promoted(did, ..) => Some(did),
305            _ => None,
306        }
307    }
308    pub fn promoted_id(&self) -> Option<PromotedId> {
309        match self.base {
310            DefIdBase::Promoted(_, promoted) => Some(promoted),
311            _ => None,
312        }
313    }
314    /// Returns the [`SyntheticItem`] encoded by this hax [`DefId`], if any.
315    pub fn as_synthetic<'tcx>(&self, _s: &impl BaseState<'tcx>) -> Option<SyntheticItem> {
316        match self.base {
317            DefIdBase::Synthetic(v) => Some(v),
318            _ => None,
319        }
320    }
321
322    pub fn is_local(&self) -> bool {
323        match self.base {
324            DefIdBase::Real(did) | DefIdBase::Promoted(did, ..) => did.is_local(),
325            DefIdBase::ImplAssocItem(id) => id.trait_impl_id.is_local(),
326            DefIdBase::Synthetic(..) => false,
327            DefIdBase::Alloc(..) => true,
328        }
329    }
330    pub fn is_typeck_child<'tcx>(&self, s: &impl BaseState<'tcx>) -> bool {
331        match self.base {
332            DefIdBase::Real(did) => s.base().tcx.is_typeck_child(did),
333            _ => false,
334        }
335    }
336
337    fn make<'tcx, S: BaseState<'tcx>>(s: &S, def_id: RDefId) -> Self {
338        let base = DefIdBase::Real(def_id);
339        let tcx = s.base().tcx;
340        let contents = DefIdContents {
341            base,
342            kind: get_def_kind(tcx, def_id).sinto(s),
343        };
344        contents.make_def_id(s)
345    }
346
347    pub fn make_synthetic<'tcx, S: BaseState<'tcx>>(s: &S, synthetic: SyntheticItem) -> Self {
348        let kind = match synthetic {
349            SyntheticItem::FnPtr(_) => DefKind::FnPtr,
350            _ => DefKind::Struct,
351        };
352        let contents = DefIdContents {
353            base: DefIdBase::Synthetic(synthetic),
354            kind,
355        };
356        contents.make_def_id(s)
357    }
358
359    /// Construct a hax `DefId` for the nth promoted constant of the current item. That `DefId` has
360    /// no corresponding rustc `DefId`.
361    pub fn make_promoted_child<'tcx, S: BaseState<'tcx>>(
362        &self,
363        s: &S,
364        promoted_id: PromotedId,
365    ) -> Self {
366        let contents = DefIdContents {
367            base: DefIdBase::Promoted(self.real_rust_def_id(), promoted_id),
368            kind: DefKind::PromotedConst,
369        };
370        contents.make_def_id(s)
371    }
372
373    pub fn make_assoc_item_impl<'tcx, S: BaseState<'tcx>>(
374        s: &S,
375        vitem: VirtualImplAssocItem,
376    ) -> Self {
377        let tcx = s.base().tcx;
378        let contents = DefIdContents {
379            base: DefIdBase::ImplAssocItem(vitem),
380            kind: get_def_kind(tcx, vitem.item_decl_id).sinto(s),
381        };
382        contents.make_def_id(s)
383    }
384
385    /// The global standing for an anonymous allocation.
386    pub fn make_anon_alloc<'tcx, S: BaseState<'tcx>>(s: &S, alloc_id: RAllocId) -> Self {
387        let tcx = s.base().tcx;
388        s.with_global_cache(|cache| cache.anon_allocs.insert(alloc_id));
389        let mutability = GlobalRef::Alloc(alloc_id).mutability(tcx);
390        let contents = DefIdContents {
391            base: DefIdBase::Alloc(alloc_id),
392            kind: DefKind::Static {
393                safety: Safety::Safe,
394                mutability,
395                nested: true,
396            },
397        };
398        contents.make_def_id(s)
399    }
400}
401
402impl DefId {
403    fn crate_name_and_disambig<'tcx>(&self, s: &impl BaseState<'tcx>) -> (Symbol, u32) {
404        let tcx = s.base().tcx;
405        match self.base {
406            DefIdBase::Real(def_id)
407            | DefIdBase::Promoted(def_id, ..)
408            | DefIdBase::ImplAssocItem(VirtualImplAssocItem {
409                trait_impl_id: def_id,
410                ..
411            }) => s.with_global_cache(|cache| cache.crate_name(tcx, def_id.krate)),
412            DefIdBase::Synthetic(..) => (Symbol::intern(SYNTHETIC_CRATE_NAME), 0),
413            DefIdBase::Alloc(..) => {
414                s.with_global_cache(|cache| cache.crate_name(tcx, rustc_hir::def_id::LOCAL_CRATE))
415            }
416        }
417    }
418
419    pub fn crate_name<'tcx>(&self, s: &impl BaseState<'tcx>) -> Symbol {
420        self.crate_name_and_disambig(s).0
421    }
422
423    /// Get the span of the definition of this item. This is the span used in diagnostics when
424    /// referring to the item.
425    pub fn def_span<'tcx>(&self, s: &impl BaseState<'tcx>) -> Span {
426        use DefKind::*;
427        let tcx = s.base().tcx;
428        match self.base {
429            DefIdBase::Real(def_id) | DefIdBase::Promoted(def_id, ..) => {
430                if let ForeignMod = &self.kind {
431                    // This kind causes `def_span` to panic.
432                    rustc_span::DUMMY_SP
433                } else if let Some(ldid) = def_id.as_local()
434                    && let hir_id = tcx.local_def_id_to_hir_id(ldid)
435                    && matches!(tcx.hir_node(hir_id), rustc_hir::Node::Synthetic)
436                {
437                    // This kind causes `def_span` to panic.
438                    rustc_span::DUMMY_SP
439                } else {
440                    tcx.def_span(def_id)
441                }
442            }
443            DefIdBase::ImplAssocItem(id) => tcx.def_span(id.item_impl_id),
444            DefIdBase::Synthetic(..) | DefIdBase::Alloc(..) => rustc_span::DUMMY_SP,
445        }
446        .sinto(s)
447    }
448
449    /// The `PathItem` corresponding to this item.
450    pub fn path_item<'tcx>(&self, s: &impl BaseState<'tcx>) -> DisambiguatedDefPathItem {
451        match self.base {
452            DefIdBase::Real(def_id) => {
453                let tcx = s.base().tcx;
454                // Set the def_id so the `CrateRoot` path item can fetch the crate name.
455                let s = &s.with_hax_owner(self);
456                tcx.def_path(def_id)
457                    .data
458                    .last()
459                    .map(|x| x.sinto(s))
460                    .unwrap_or_else(|| {
461                        let (name, disambiguator) = self.crate_name_and_disambig(s);
462                        DisambiguatedDefPathItem {
463                            disambiguator,
464                            data: DefPathItem::CrateRoot { name },
465                        }
466                    })
467            }
468            DefIdBase::Promoted(_, id) => DisambiguatedDefPathItem {
469                data: DefPathItem::PromotedConst,
470                // Reuse the promoted id as disambiguator, like for inline consts.
471                disambiguator: id.as_u32(),
472            },
473            DefIdBase::ImplAssocItem(id) => {
474                let s = &s.with_hax_owner(self);
475                s.base()
476                    .tcx
477                    .def_path(id.item_decl_id)
478                    .data
479                    .last()
480                    .map(|x| x.sinto(s))
481                    .unwrap()
482            }
483            DefIdBase::Synthetic(synthetic) => DisambiguatedDefPathItem {
484                disambiguator: 0,
485                data: DefPathItem::TypeNs(Symbol::intern(&synthetic.name())),
486            },
487            DefIdBase::Alloc(alloc_id) => DisambiguatedDefPathItem {
488                data: DefPathItem::PromotedConst,
489                // Number anonymous allocations in the order we encountered them.
490                disambiguator: s.with_global_cache(|cache| {
491                    cache.anon_allocs.get_index_of(&alloc_id).unwrap() as u32
492                }),
493            },
494        }
495    }
496
497    pub fn parent<'tcx>(&self, s: &impl BaseState<'tcx>) -> Option<DefId> {
498        match self.base {
499            DefIdBase::Real(def_id) => s.tcx().opt_parent(def_id),
500            DefIdBase::Promoted(def_id, _) => Some(def_id),
501            DefIdBase::ImplAssocItem(id) => Some(id.trait_impl_id),
502            DefIdBase::Synthetic(..) | DefIdBase::Alloc(..) => {
503                Some(rustc_span::def_id::CRATE_DEF_ID.to_def_id())
504            }
505        }
506        .sinto(s)
507    }
508}
509
510impl DefId {
511    pub fn can_have_generics<'tcx>(&self, s: &impl BaseState<'tcx>) -> bool {
512        let tcx = s.base().tcx;
513        match self.base {
514            DefIdBase::Real(def_id)
515            | DefIdBase::Promoted(def_id, ..)
516            | DefIdBase::ImplAssocItem(VirtualImplAssocItem {
517                item_decl_id: def_id,
518                ..
519            }) => can_have_generics(tcx, def_id),
520            DefIdBase::Synthetic(synthetic) => synthetic.can_have_generics(s),
521            DefIdBase::Alloc(..) => false,
522        }
523    }
524
525    pub fn generics_of<'tcx>(&self, s: &impl BaseState<'tcx>) -> &'tcx ty::Generics {
526        let tcx = s.base().tcx;
527        match self.base {
528            DefIdBase::Real(def_id) => tcx.generics_of(def_id),
529            DefIdBase::Synthetic(synthetic) => synthetic.generics_of(s),
530            DefIdBase::Promoted(..) | DefIdBase::Alloc(..) => s.with_item_cache(self, |cache| {
531                if let Some(generics) = cache.virtual_generics {
532                    return generics;
533                }
534                let parent = match self.base {
535                    DefIdBase::Promoted(def_id, ..) => Some(def_id),
536                    _ => None,
537                };
538                let generics = Box::leak(Box::new(ty::Generics {
539                    parent,
540                    parent_count: parent.map_or(0, |p| tcx.generics_of(p).count()),
541                    own_params: Default::default(),
542                    param_def_id_to_index: Default::default(),
543                    has_self: false,
544                    has_late_bound_regions: None,
545                }));
546                cache.virtual_generics = Some(generics);
547                generics
548            }),
549            DefIdBase::ImplAssocItem(id) => s.with_item_cache(self, |cache| {
550                if let Some(generics) = cache.virtual_generics {
551                    return generics;
552                }
553                // We build a custom environment here.
554                let item_id = id.item_impl_id;
555                let decl_generics = tcx.generics_of(item_id);
556                let parent_count = tcx.generics_of(id.trait_impl_id).count();
557                let own_params = tcx
558                    .generics_of(id.item_decl_id)
559                    .own_params
560                    .iter()
561                    .cloned()
562                    .enumerate()
563                    .map(|(i, mut param)| {
564                        param.index = parent_count as u32 + i as u32;
565                        param
566                    })
567                    .collect_vec();
568                let param_def_id_to_index = own_params
569                    .iter()
570                    .map(|param| (param.def_id, param.index))
571                    .collect();
572                let generics = Box::leak(Box::new(ty::Generics {
573                    parent: Some(id.trait_impl_id),
574                    parent_count,
575                    own_params,
576                    param_def_id_to_index,
577                    has_self: decl_generics.has_self,
578                    has_late_bound_regions: decl_generics.has_late_bound_regions,
579                }));
580                cache.virtual_generics = Some(generics);
581                generics
582            }),
583        }
584    }
585
586    pub fn identity_args<'tcx>(&self, s: &impl BaseState<'tcx>) -> ty::GenericArgsRef<'tcx> {
587        let tcx = s.base().tcx;
588        match self.base {
589            DefIdBase::Real(def_id) | DefIdBase::Promoted(def_id, ..) => {
590                if can_have_generics(tcx, def_id) {
591                    identity_args_with_inferred(tcx, def_id)
592                } else {
593                    ty::GenericArgsRef::default()
594                }
595            }
596            DefIdBase::Synthetic(synthetic) => synthetic.identity_args(s),
597            DefIdBase::Alloc(..) => ty::GenericArgsRef::default(),
598            DefIdBase::ImplAssocItem(_) => panic!(
599                "virtual trait impl associated items do not have a \
600                sensible `identity_args`. consider `identity_args_for_item_decl`"
601            ),
602        }
603    }
604
605    pub fn param_env<'tcx>(&self, s: &impl BaseState<'tcx>) -> ty::ParamEnv<'tcx> {
606        let tcx = s.base().tcx;
607        match self.base {
608            DefIdBase::ImplAssocItem(id) => {
609                let item_args = id.identity_args_for_item_decl(s);
610                let impl_predicates = tcx.param_env(id.trait_impl_id).caller_bounds();
611                let item_predicates = tcx
612                    .clauses_of(id.item_decl_id)
613                    .instantiate_own(tcx, item_args)
614                    .map(|(predicate, _)| predicate.skip_normalization());
615                param_env_from_clauses(tcx, impl_predicates.chain(item_predicates))
616            }
617            DefIdBase::Real(def_id) | DefIdBase::Promoted(def_id, ..) => {
618                if can_have_generics(tcx, def_id) {
619                    tcx.param_env(def_id)
620                } else {
621                    ty::ParamEnv::empty()
622                }
623            }
624            DefIdBase::Synthetic(synthetic) => synthetic.param_env(s),
625            DefIdBase::Alloc(..) => ty::ParamEnv::empty(),
626        }
627    }
628
629    pub fn typing_env<'tcx>(&self, s: &impl BaseState<'tcx>) -> ty::TypingEnv<'tcx> {
630        ty::TypingEnv::new(self.param_env(s), ty::TypingMode::PostAnalysis)
631    }
632
633    pub fn required_predicates<'tcx, S: BaseState<'tcx>>(
634        &self,
635        s: &S,
636    ) -> ItemPredicates<'tcx, Self> {
637        let state = s.base_state();
638        ItemPredicates::required(s.base().elab_ctx, &state, self.clone())
639    }
640
641    pub fn type_of<'tcx, S: BaseState<'tcx>>(&self, s: &S) -> ty::EarlyBinder<'tcx, ty::Ty<'tcx>> {
642        let tcx: ty::TyCtxt<'tcx> = s.base().tcx;
643        match self.base {
644            DefIdBase::Real(def_id) | DefIdBase::Promoted(def_id, ..) => tcx.type_of(def_id),
645            DefIdBase::Synthetic(synthetic) => synthetic.type_of(s),
646            DefIdBase::ImplAssocItem(id) => tcx.type_of(id.item_decl_id),
647            DefIdBase::Alloc(alloc_id) => s.with_global_cache(|cache| {
648                ty::EarlyBinder::bind(tcx, cache.alloc_types.ty(tcx, alloc_id))
649            }),
650        }
651    }
652}
653
654impl DefId {
655    /// Gets the visibility (`pub` or not) of the definition. Returns `None` for defs that don't have a
656    /// meaningful visibility.
657    pub fn visibility<'tcx>(&self, tcx: ty::TyCtxt<'tcx>) -> Option<bool> {
658        use DefKind::*;
659        match self.kind {
660            AssocConst { .. }
661            | AssocFn
662            | Const { .. }
663            | Enum
664            | Field
665            | Fn
666            | ForeignTy
667            | Macro { .. }
668            | Mod
669            | Static { .. }
670            | Struct
671            | Trait
672            | TraitAlias
673            | TyAlias { .. }
674            | Union
675            | Use
676            | Variant => {
677                let def_id = self.as_real_def_id()?;
678                Some(tcx.visibility(def_id).is_public())
679            }
680            // These kinds don't have visibility modifiers (which would cause `visibility` to panic).
681            AnonConst
682            | AssocTy
683            | Closure
684            | ConstParam
685            | Ctor { .. }
686            | ExternCrate
687            | ForeignMod
688            | GlobalAsm
689            | Impl { .. }
690            | PromotedConst
691            | FnPtr
692            | LifetimeParam
693            | OpaqueTy
694            | SyntheticCoroutineBody
695            | TestBinderConstraints
696            | TyParam => None,
697        }
698    }
699
700    /// Gets the attributes of the definition.
701    pub fn attrs<'tcx>(&self, tcx: ty::TyCtxt<'tcx>) -> &'tcx [rustc_hir::Attribute] {
702        use DefKind::*;
703        match self.kind {
704            // These kinds cause `get_attrs` to panic.
705            ConstParam | LifetimeParam | TyParam | ForeignMod => &[],
706            _ => {
707                if let Some(def_id) = self.as_real_def_id() {
708                    if let Some(ldid) = def_id.as_local() {
709                        tcx.hir_attrs(tcx.local_def_id_to_hir_id(ldid))
710                    } else if matches!(self.kind, AnonConst) {
711                        // Rustc doesn't store the attributes of anonymous constants in crate
712                        // metadata; asking for them panics.
713                        &[]
714                    } else {
715                        tcx.attrs_for_def(def_id)
716                    }
717                } else {
718                    &[]
719                }
720            }
721        }
722    }
723}
724
725impl std::ops::Deref for DefId {
726    type Target = DefIdContents;
727    fn deref(&self) -> &Self::Target {
728        &self.contents
729    }
730}
731
732impl std::fmt::Debug for DefId {
733    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
734        match self.base {
735            DefIdBase::Real(def_id) => write!(f, "{def_id:?}"),
736            DefIdBase::Promoted(def_id, promoted) => {
737                write!(f, "{def_id:?}::promoted#{}", promoted.as_u32())
738            }
739            DefIdBase::Synthetic(item) => write!(f, "{}", item.name()),
740            DefIdBase::Alloc(alloc_id) => write!(f, "{alloc_id:?}"),
741            DefIdBase::ImplAssocItem(id) => {
742                write!(f, "{:?}::{:?}", id.trait_impl_id, id.item_decl_id)
743            }
744        }
745    }
746}
747
748impl std::hash::Hash for DefId {
749    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
750        self.base.hash(state);
751    }
752}
753
754/// Gets the kind of the definition. Can't use `def_kind` directly because this crashes on the
755/// crate root.
756pub(crate) fn get_def_kind<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> hir::def::DefKind {
757    if def_id == rustc_span::def_id::CRATE_DEF_ID.to_def_id() {
758        // Horrible hack: without this, `def_kind` crashes on the crate root. Presumably some table
759        // isn't properly initialized otherwise.
760        let _ = tcx.def_span(def_id);
761    };
762    tcx.def_kind(def_id)
763}
764
765impl<'s, S: BaseState<'s>> SInto<S, DefId> for RDefId {
766    fn sinto(&self, s: &S) -> DefId {
767        if let Some(def_id) = s.with_global_cache(|cache| cache.def_ids.get(self).cloned()) {
768            return def_id;
769        }
770        let def_id = DefId::make(s, *self);
771        s.with_global_cache(|cache| {
772            cache.def_ids.insert(*self, def_id.clone());
773        });
774        def_id
775    }
776}
777
778impl<S> SInto<S, DefId> for DefId {
779    fn sinto(&self, _s: &S) -> DefId {
780        self.clone()
781    }
782}
783
784/// Reflects [`rustc_hir::definitions::DefPathData`]
785#[derive(Debug, Clone, PartialEq, Eq, Hash)]
786#[derive(AdtInto)]
787#[args(<'ctx, S: UnderOwnerState<'ctx>>, from: rustc_hir::definitions::DefPathData, state: S as s)]
788pub enum DefPathItem {
789    CrateRoot {
790        #[value(s.owner().crate_name(s))]
791        name: Symbol,
792    },
793    Impl,
794    ForeignMod,
795    Use,
796    GlobalAsm,
797    TypeNs(Symbol),
798    ValueNs(Symbol),
799    MacroNs(Symbol),
800    LifetimeNs(Symbol),
801    Closure,
802    TestBinderConstraints,
803    Ctor,
804    AnonConst,
805    #[disable_mapping]
806    PromotedConst,
807    OpaqueTy,
808    OpaqueLifetime(Symbol),
809    AnonAssocTy(Symbol),
810    SyntheticCoroutineBody,
811    NestedStatic,
812}
813
814#[derive(Debug, Clone, PartialEq, Eq, Hash)]
815#[derive(AdtInto)]
816#[args(<'a, S: UnderOwnerState<'a>>, from: rustc_hir::definitions::DisambiguatedDefPathData, state: S as s)]
817/// Reflects [`rustc_hir::definitions::DisambiguatedDefPathData`]
818pub struct DisambiguatedDefPathItem {
819    pub data: DefPathItem,
820    pub disambiguator: u32,
821}