1use crate::hax::AdtInto;
10use crate::hax::prelude::*;
11use charon_lib::ast::HashConsed;
12
13pub use rustc_middle::mir::Promoted as PromotedId;
14use {rustc_hir as hir, rustc_hir::def_id::DefId as RDefId, rustc_middle::ty};
15
16sinto_reexport!(hir::Safety);
17sinto_reexport!(hir::Mutability);
18sinto_reexport!(hir::def::CtorKind);
19sinto_reexport!(hir::def::MacroKinds);
20sinto_reexport!(hir::def::CtorOf);
21sinto_reexport!(rustc_span::symbol::Symbol);
22sinto_reexport!(rustc_span::symbol::ByteSymbol);
23
24#[derive(AdtInto)]
26#[args(<S>, from: rustc_hir::def::DefKind, state: S as tcx)]
27#[derive(Debug, Clone, PartialEq, Hash, Eq)]
28pub enum DefKind {
29 Mod,
30 Struct,
31 Union,
32 Enum,
33 Variant,
34 Trait,
35 TyAlias,
36 ForeignTy,
37 TraitAlias,
38 AssocTy,
39 TyParam,
40 Fn,
41 Const,
42 ConstParam,
43 Static {
44 safety: Safety,
45 mutability: Mutability,
46 nested: bool,
47 },
48 Ctor(CtorOf, CtorKind),
49 AssocFn,
50 AssocConst,
51 Macro(MacroKinds),
52 ExternCrate,
53 Use,
54 ForeignMod,
55 AnonConst,
56 InlineConst,
57 #[disable_mapping]
58 PromotedConst,
60 OpaqueTy,
61 Field,
62 LifetimeParam,
63 GlobalAsm,
64 Impl {
65 of_trait: bool,
66 },
67 Closure,
68 SyntheticCoroutineBody,
69}
70
71const SYNTHETIC_CRATE_NAME: &str = "<synthetic>";
73
74#[derive(Clone, PartialEq, Eq)]
77pub struct DefId {
78 pub(crate) contents: HashConsed<DefIdContents>,
79}
80
81#[derive(Debug, Hash, Clone, PartialEq, Eq)]
82pub struct DefIdContents {
83 pub base: DefIdBase,
84 pub kind: crate::hax::DefKind,
86}
87
88#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
89pub enum DefIdBase {
90 Real(RDefId),
91 Promoted(RDefId, PromotedId),
92 Synthetic(SyntheticItem, RDefId),
93}
94
95impl DefIdBase {
96 pub fn underlying_def_id(self) -> Option<RDefId> {
97 match self {
98 Self::Real(did) | Self::Promoted(did, ..) => Some(did),
99 Self::Synthetic(.., did) => Some(did),
100 }
101 }
102 pub fn as_real(self) -> Option<RDefId> {
103 match self {
104 Self::Real(did) => Some(did),
105 _ => None,
106 }
107 }
108 pub fn as_promoted(self) -> Option<(RDefId, PromotedId)> {
109 match self {
110 Self::Promoted(did, promoted) => Some((did, promoted)),
111 _ => None,
112 }
113 }
114 pub fn as_real_or_promoted(self) -> Option<RDefId> {
115 match self {
116 Self::Real(did) | Self::Promoted(did, ..) => Some(did),
117 _ => None,
118 }
119 }
120 pub fn as_synthetic(self) -> Option<SyntheticItem> {
121 if let Self::Synthetic(v, _) = self {
122 Some(v)
123 } else {
124 None
125 }
126 }
127}
128
129impl DefIdContents {
130 pub fn make_def_id<'tcx, S: BaseState<'tcx>>(self, _s: &S) -> DefId {
131 let contents = HashConsed::new(self);
132 DefId { contents }
133 }
134}
135
136impl DefId {
137 pub fn as_rust_def_id(&self) -> Option<RDefId> {
140 self.base.as_real()
141 }
142 pub fn real_rust_def_id(&self) -> RDefId {
144 self.as_rust_def_id().unwrap()
145 }
146 pub fn underlying_rust_def_id(&self) -> Option<RDefId> {
148 self.base.as_real_or_promoted()
149 }
150 pub fn as_def_id_even_synthetic(&self) -> RDefId {
154 self.base.underlying_def_id().unwrap()
155 }
156
157 pub fn is_local(&self) -> bool {
158 self.base
159 .underlying_def_id()
160 .is_some_and(|did| did.is_local())
161 }
162 pub fn promoted_id(&self) -> Option<PromotedId> {
163 self.base.as_promoted().map(|(_, p)| p)
164 }
165
166 fn make<'tcx, S: BaseState<'tcx>>(s: &S, def_id: RDefId) -> Self {
167 let base = match s.with_global_cache(|c| c.reverse_synthetic_map.get(&def_id).copied()) {
168 None => DefIdBase::Real(def_id),
169 Some(synthetic) => return Self::make_synthetic(s, synthetic, def_id),
170 };
171 let tcx = s.base().tcx;
172 let contents = DefIdContents {
173 base,
174 kind: get_def_kind(tcx, def_id).sinto(s),
175 };
176 contents.make_def_id(s)
177 }
178
179 pub fn make_synthetic<'tcx, S: BaseState<'tcx>>(
180 s: &S,
181 synthetic: SyntheticItem,
182 def_id: RDefId,
183 ) -> Self {
184 let contents = DefIdContents {
185 base: DefIdBase::Synthetic(synthetic, def_id),
186 kind: DefKind::Struct,
187 };
188 contents.make_def_id(s)
189 }
190
191 pub fn as_synthetic<'tcx>(&self, _s: &impl BaseState<'tcx>) -> Option<SyntheticItem> {
197 self.base.as_synthetic()
198 }
199
200 pub fn parent<'tcx>(&self, s: &impl BaseState<'tcx>) -> Option<DefId> {
201 match self.base {
202 DefIdBase::Real(def_id) => s.tcx().opt_parent(def_id),
203 DefIdBase::Promoted(def_id, _) => Some(def_id),
204 DefIdBase::Synthetic(..) => Some(rustc_span::def_id::CRATE_DEF_ID.to_def_id()),
205 }
206 .sinto(s)
207 }
208
209 pub fn crate_name<'tcx>(&self, s: &impl BaseState<'tcx>) -> Symbol {
210 let tcx = s.base().tcx;
211 match self.base {
212 DefIdBase::Real(def_id) | DefIdBase::Promoted(def_id, ..) => {
213 tcx.crate_name(def_id.krate)
214 }
215 DefIdBase::Synthetic(..) => Symbol::intern(SYNTHETIC_CRATE_NAME),
216 }
217 }
218
219 pub fn path_item<'tcx>(&self, s: &impl BaseState<'tcx>) -> DisambiguatedDefPathItem {
221 match self.base {
222 DefIdBase::Real(def_id) => {
223 let tcx = s.base().tcx;
224 let state_with_id = s.with_hax_owner(self);
226 tcx.def_path(def_id)
227 .data
228 .last()
229 .map(|x| x.sinto(&state_with_id))
230 .unwrap_or_else(|| DisambiguatedDefPathItem {
231 disambiguator: 0,
232 data: DefPathItem::CrateRoot {
233 name: self.crate_name(s),
234 },
235 })
236 }
237 DefIdBase::Promoted(_, id) => DisambiguatedDefPathItem {
238 data: DefPathItem::PromotedConst,
239 disambiguator: id.as_u32(),
241 },
242 DefIdBase::Synthetic(synthetic, ..) => DisambiguatedDefPathItem {
243 disambiguator: 0,
244 data: DefPathItem::TypeNs(Symbol::intern(&synthetic.name())),
245 },
246 }
247 }
248
249 pub fn make_promoted_child<'tcx, S: BaseState<'tcx>>(
252 &self,
253 s: &S,
254 promoted_id: PromotedId,
255 ) -> Self {
256 let contents = DefIdContents {
257 base: DefIdBase::Promoted(self.real_rust_def_id(), promoted_id),
258 kind: DefKind::PromotedConst,
259 };
260 contents.make_def_id(s)
261 }
262}
263
264impl DefId {
265 pub fn visibility<'tcx>(&self, tcx: ty::TyCtxt<'tcx>) -> Option<bool> {
268 use DefKind::*;
269 match self.kind {
270 AssocConst
271 | AssocFn
272 | Const
273 | Enum
274 | Field
275 | Fn
276 | ForeignTy
277 | Macro { .. }
278 | Mod
279 | Static { .. }
280 | Struct
281 | Trait
282 | TraitAlias
283 | TyAlias { .. }
284 | Union
285 | Use
286 | Variant => {
287 let def_id = self.as_rust_def_id()?;
288 Some(tcx.visibility(def_id).is_public())
289 }
290 AnonConst
292 | AssocTy
293 | Closure
294 | ConstParam
295 | Ctor { .. }
296 | ExternCrate
297 | ForeignMod
298 | GlobalAsm
299 | Impl { .. }
300 | InlineConst
301 | PromotedConst
302 | LifetimeParam
303 | OpaqueTy
304 | SyntheticCoroutineBody
305 | TyParam => None,
306 }
307 }
308
309 pub fn attrs<'tcx>(&self, tcx: ty::TyCtxt<'tcx>) -> &'tcx [rustc_hir::Attribute] {
311 use DefKind::*;
312 match self.kind {
313 ConstParam | LifetimeParam | TyParam | ForeignMod | InlineConst => &[],
315 _ => {
316 if let Some(def_id) = self.as_rust_def_id() {
317 if let Some(ldid) = def_id.as_local() {
318 tcx.hir_attrs(tcx.local_def_id_to_hir_id(ldid))
319 } else {
320 tcx.attrs_for_def(def_id)
321 }
322 } else {
323 &[]
324 }
325 }
326 }
327 }
328}
329
330impl std::ops::Deref for DefId {
331 type Target = DefIdContents;
332 fn deref(&self) -> &Self::Target {
333 &self.contents
334 }
335}
336
337impl std::fmt::Debug for DefId {
338 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
339 match self.base {
340 DefIdBase::Real(def_id) => write!(f, "{def_id:?}"),
341 DefIdBase::Promoted(def_id, promoted) => {
342 write!(f, "{def_id:?}::promoted#{}", promoted.as_u32())
343 }
344 DefIdBase::Synthetic(item, _) => write!(f, "{}", item.name()),
345 }
346 }
347}
348
349impl std::hash::Hash for DefId {
350 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
351 self.base.hash(state);
352 }
353}
354
355pub(crate) fn get_def_kind<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> hir::def::DefKind {
358 if def_id == rustc_span::def_id::CRATE_DEF_ID.to_def_id() {
359 let _ = tcx.def_span(def_id);
362 };
363 tcx.def_kind(def_id)
364}
365
366impl<'s, S: BaseState<'s>> SInto<S, DefId> for RDefId {
367 fn sinto(&self, s: &S) -> DefId {
368 if let Some(def_id) = s.with_item_cache(*self, |cache| cache.def_id.clone()) {
369 return def_id;
370 }
371 let def_id = DefId::make(s, *self);
372 s.with_item_cache(*self, |cache| cache.def_id = Some(def_id.clone()));
373 def_id
374 }
375}
376
377#[derive(Clone, Debug, Hash, PartialEq, Eq, AdtInto)]
380#[args(<'ctx, S: UnderOwnerState<'ctx>>, from: rustc_hir::definitions::DefPathData, state: S as s)]
381pub enum DefPathItem {
382 CrateRoot {
383 #[value(s.base().tcx.crate_name(s.owner_id().krate).sinto(s))]
384 name: Symbol,
385 },
386 Impl,
387 ForeignMod,
388 Use,
389 GlobalAsm,
390 TypeNs(Symbol),
391 ValueNs(Symbol),
392 MacroNs(Symbol),
393 LifetimeNs(Symbol),
394 Closure,
395 Ctor,
396 LateAnonConst,
397 AnonConst,
398 #[disable_mapping]
399 PromotedConst,
400 DesugaredAnonymousLifetime,
401 OpaqueTy,
402 OpaqueLifetime(Symbol),
403 AnonAssocTy(Symbol),
404 SyntheticCoroutineBody,
405 NestedStatic,
406}
407
408#[derive(Clone, Debug, Hash, PartialEq, Eq, AdtInto)]
409#[args(<'a, S: UnderOwnerState<'a>>, from: rustc_hir::definitions::DisambiguatedDefPathData, state: S as s)]
410pub struct DisambiguatedDefPathItem {
412 pub data: DefPathItem,
413 pub disambiguator: u32,
414}