1use std::fmt::{self, Write};
8use std::hash::Hash;
9
10use rustc_data_structures::stable_hasher::StableHasher;
11use rustc_data_structures::unord::UnordMap;
12use rustc_hashes::Hash64;
13use rustc_index::IndexVec;
14use rustc_macros::{Decodable, Encodable};
15use rustc_span::{Symbol, kw, sym};
16use tracing::{debug, instrument};
17
18pub use crate::def_id::DefPathHash;
19use crate::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId};
20use crate::def_path_hash_map::DefPathHashMap;
21
22#[derive(Debug)]
27pub struct DefPathTable {
28    stable_crate_id: StableCrateId,
29    index_to_key: IndexVec<DefIndex, DefKey>,
30    def_path_hashes: IndexVec<DefIndex, Hash64>,
32    def_path_hash_to_index: DefPathHashMap,
33}
34
35impl DefPathTable {
36    fn new(stable_crate_id: StableCrateId) -> DefPathTable {
37        DefPathTable {
38            stable_crate_id,
39            index_to_key: Default::default(),
40            def_path_hashes: Default::default(),
41            def_path_hash_to_index: Default::default(),
42        }
43    }
44
45    fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex {
46        debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id());
48        let local_hash = def_path_hash.local_hash();
49
50        let index = self.index_to_key.push(key);
51        debug!("DefPathTable::insert() - {key:?} <-> {index:?}");
52
53        self.def_path_hashes.push(local_hash);
54        debug_assert!(self.def_path_hashes.len() == self.index_to_key.len());
55
56        if let Some(existing) = self.def_path_hash_to_index.insert(&local_hash, &index) {
59            let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx));
60            let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx));
61
62            panic!(
71                "found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
72                    Compilation cannot continue."
73            );
74        }
75
76        index
77    }
78
79    #[inline(always)]
80    pub fn def_key(&self, index: DefIndex) -> DefKey {
81        self.index_to_key[index]
82    }
83
84    #[instrument(level = "trace", skip(self), ret)]
85    #[inline(always)]
86    pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
87        let hash = self.def_path_hashes[index];
88        DefPathHash::new(self.stable_crate_id, hash)
89    }
90
91    pub fn enumerated_keys_and_path_hashes(
92        &self,
93    ) -> impl Iterator<Item = (DefIndex, &DefKey, DefPathHash)> + ExactSizeIterator {
94        self.index_to_key
95            .iter_enumerated()
96            .map(move |(index, key)| (index, key, self.def_path_hash(index)))
97    }
98}
99
100#[derive(Debug)]
101pub struct DisambiguatorState {
102    next: UnordMap<(LocalDefId, DefPathData), u32>,
103}
104
105impl DisambiguatorState {
106    pub fn new() -> Self {
107        Self { next: Default::default() }
108    }
109
110    pub fn with(def_id: LocalDefId, data: DefPathData, index: u32) -> Self {
113        let mut this = Self::new();
114        this.next.insert((def_id, data), index);
115        this
116    }
117}
118
119#[derive(Debug)]
123pub struct Definitions {
124    table: DefPathTable,
125}
126
127#[derive(Copy, Clone, PartialEq, Debug, Encodable, Decodable)]
131pub struct DefKey {
132    pub parent: Option<DefIndex>,
134
135    pub disambiguated_data: DisambiguatedDefPathData,
137}
138
139impl DefKey {
140    pub(crate) fn compute_stable_hash(&self, parent: DefPathHash) -> DefPathHash {
141        let mut hasher = StableHasher::new();
142
143        parent.local_hash().hash(&mut hasher);
146
147        let DisambiguatedDefPathData { ref data, disambiguator } = self.disambiguated_data;
148
149        std::mem::discriminant(data).hash(&mut hasher);
150        if let Some(name) = data.hashed_symbol() {
151            name.as_str().hash(&mut hasher);
154        }
155
156        disambiguator.hash(&mut hasher);
157
158        let local_hash = hasher.finish();
159
160        DefPathHash::new(parent.stable_crate_id(), local_hash)
165    }
166
167    #[inline]
168    pub fn get_opt_name(&self) -> Option<Symbol> {
169        self.disambiguated_data.data.get_opt_name()
170    }
171}
172
173#[derive(Copy, Clone, PartialEq, Debug, Encodable, Decodable)]
180pub struct DisambiguatedDefPathData {
181    pub data: DefPathData,
182    pub disambiguator: u32,
183}
184
185impl DisambiguatedDefPathData {
186    pub fn as_sym(&self, verbose: bool) -> Symbol {
187        match self.data.name() {
188            DefPathDataName::Named(name) => {
189                if verbose && self.disambiguator != 0 {
190                    Symbol::intern(&format!("{}#{}", name, self.disambiguator))
191                } else {
192                    name
193                }
194            }
195            DefPathDataName::Anon { namespace } => {
196                if let DefPathData::AnonAssocTy(method) = self.data {
197                    Symbol::intern(&format!("{}::{{{}#{}}}", method, namespace, self.disambiguator))
198                } else {
199                    Symbol::intern(&format!("{{{}#{}}}", namespace, self.disambiguator))
200                }
201            }
202        }
203    }
204}
205
206#[derive(Clone, Debug, Encodable, Decodable)]
207pub struct DefPath {
208    pub data: Vec<DisambiguatedDefPathData>,
210
211    pub krate: CrateNum,
213}
214
215impl DefPath {
216    pub fn make<FN>(krate: CrateNum, start_index: DefIndex, mut get_key: FN) -> DefPath
217    where
218        FN: FnMut(DefIndex) -> DefKey,
219    {
220        let mut data = vec![];
221        let mut index = Some(start_index);
222        loop {
223            debug!("DefPath::make: krate={:?} index={:?}", krate, index);
224            let p = index.unwrap();
225            let key = get_key(p);
226            debug!("DefPath::make: key={:?}", key);
227            match key.disambiguated_data.data {
228                DefPathData::CrateRoot => {
229                    assert!(key.parent.is_none());
230                    break;
231                }
232                _ => {
233                    data.push(key.disambiguated_data);
234                    index = key.parent;
235                }
236            }
237        }
238        data.reverse();
239        DefPath { data, krate }
240    }
241
242    pub fn to_string_no_crate_verbose(&self) -> String {
246        let mut s = String::with_capacity(self.data.len() * 16);
247
248        for component in &self.data {
249            write!(s, "::{}", component.as_sym(true)).unwrap();
250        }
251
252        s
253    }
254
255    pub fn to_filename_friendly_no_crate(&self) -> String {
259        let mut s = String::with_capacity(self.data.len() * 16);
260
261        let mut opt_delimiter = None;
262        for component in &self.data {
263            s.extend(opt_delimiter);
264            opt_delimiter = Some('-');
265            write!(s, "{}", component.as_sym(true)).unwrap();
266        }
267
268        s
269    }
270}
271
272#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
274pub enum DefPathData {
275    CrateRoot,
279
280    Impl,
283    ForeignMod,
285    Use,
287    GlobalAsm,
289    TypeNs(Symbol),
291    ValueNs(Symbol),
293    MacroNs(Symbol),
295    LifetimeNs(Symbol),
297    Closure,
299
300    Ctor,
303    AnonConst,
305    OpaqueTy,
308    OpaqueLifetime(Symbol),
310    AnonAssocTy(Symbol),
313    SyntheticCoroutineBody,
315    NestedStatic,
317}
318
319impl Definitions {
320    pub fn def_path_table(&self) -> &DefPathTable {
321        &self.table
322    }
323
324    pub fn def_index_count(&self) -> usize {
326        self.table.index_to_key.len()
327    }
328
329    #[inline]
330    pub fn def_key(&self, id: LocalDefId) -> DefKey {
331        self.table.def_key(id.local_def_index)
332    }
333
334    #[inline(always)]
335    pub fn def_path_hash(&self, id: LocalDefId) -> DefPathHash {
336        self.table.def_path_hash(id.local_def_index)
337    }
338
339    pub fn def_path(&self, id: LocalDefId) -> DefPath {
345        DefPath::make(LOCAL_CRATE, id.local_def_index, |index| {
346            self.def_key(LocalDefId { local_def_index: index })
347        })
348    }
349
350    pub fn new(stable_crate_id: StableCrateId) -> Definitions {
352        let key = DefKey {
353            parent: None,
354            disambiguated_data: DisambiguatedDefPathData {
355                data: DefPathData::CrateRoot,
356                disambiguator: 0,
357            },
358        };
359
360        let def_path_hash =
369            DefPathHash::new(stable_crate_id, Hash64::new(stable_crate_id.as_u64()));
370
371        let mut table = DefPathTable::new(stable_crate_id);
373        let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
374        assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
375
376        Definitions { table }
377    }
378
379    pub fn create_def(
385        &mut self,
386        parent: LocalDefId,
387        data: DefPathData,
388        disambiguator: &mut DisambiguatorState,
389    ) -> LocalDefId {
390        debug!(
393            "create_def(parent={}, data={data:?})",
394            self.def_path(parent).to_string_no_crate_verbose(),
395        );
396
397        assert!(data != DefPathData::CrateRoot);
399
400        let disambiguator = {
402            let next_disamb = disambiguator.next.entry((parent, data)).or_insert(0);
403            let disambiguator = *next_disamb;
404            *next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
405            disambiguator
406        };
407        let key = DefKey {
408            parent: Some(parent.local_def_index),
409            disambiguated_data: DisambiguatedDefPathData { data, disambiguator },
410        };
411
412        let parent_hash = self.table.def_path_hash(parent.local_def_index);
413        let def_path_hash = key.compute_stable_hash(parent_hash);
414
415        debug!("create_def: after disambiguation, key = {:?}", key);
416
417        LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }
419    }
420
421    #[inline(always)]
422    pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option<LocalDefId> {
428        debug_assert!(hash.stable_crate_id() == self.table.stable_crate_id);
429        self.table
430            .def_path_hash_to_index
431            .get(&hash.local_hash())
432            .map(|local_def_index| LocalDefId { local_def_index })
433    }
434
435    pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap {
436        &self.table.def_path_hash_to_index
437    }
438
439    pub fn num_definitions(&self) -> usize {
440        self.table.def_path_hashes.len()
441    }
442}
443
444#[derive(Copy, Clone, PartialEq, Debug)]
445pub enum DefPathDataName {
446    Named(Symbol),
447    Anon { namespace: Symbol },
448}
449
450impl DefPathData {
451    pub fn get_opt_name(&self) -> Option<Symbol> {
452        use self::DefPathData::*;
453        match *self {
454            TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name)
455            | OpaqueLifetime(name) => Some(name),
456
457            Impl
458            | ForeignMod
459            | CrateRoot
460            | Use
461            | GlobalAsm
462            | Closure
463            | Ctor
464            | AnonConst
465            | OpaqueTy
466            | AnonAssocTy(..)
467            | SyntheticCoroutineBody
468            | NestedStatic => None,
469        }
470    }
471
472    fn hashed_symbol(&self) -> Option<Symbol> {
473        use self::DefPathData::*;
474        match *self {
475            TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name)
476            | OpaqueLifetime(name) => Some(name),
477
478            Impl
479            | ForeignMod
480            | CrateRoot
481            | Use
482            | GlobalAsm
483            | Closure
484            | Ctor
485            | AnonConst
486            | OpaqueTy
487            | SyntheticCoroutineBody
488            | NestedStatic => None,
489        }
490    }
491
492    pub fn name(&self) -> DefPathDataName {
493        use self::DefPathData::*;
494        match *self {
495            TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name)
496            | OpaqueLifetime(name) => DefPathDataName::Named(name),
497            CrateRoot => DefPathDataName::Anon { namespace: kw::Crate },
499            Impl => DefPathDataName::Anon { namespace: kw::Impl },
500            ForeignMod => DefPathDataName::Anon { namespace: kw::Extern },
501            Use => DefPathDataName::Anon { namespace: kw::Use },
502            GlobalAsm => DefPathDataName::Anon { namespace: sym::global_asm },
503            Closure => DefPathDataName::Anon { namespace: sym::closure },
504            Ctor => DefPathDataName::Anon { namespace: sym::constructor },
505            AnonConst => DefPathDataName::Anon { namespace: sym::constant },
506            OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
507            AnonAssocTy(..) => DefPathDataName::Anon { namespace: sym::anon_assoc },
508            SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
509            NestedStatic => DefPathDataName::Anon { namespace: sym::nested },
510        }
511    }
512}
513
514impl fmt::Display for DefPathData {
515    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
516        match self.name() {
517            DefPathDataName::Named(name) => f.write_str(name.as_str()),
518            DefPathDataName::Anon { namespace } => write!(f, "{{{{{namespace}}}}}"),
520        }
521    }
522}