]> git.lizzy.rs Git - rust.git/blob - src/librustc/hir/def_id.rs
a893fb82b4892a9e75c83afe7fcc779f6c7591ca
[rust.git] / src / librustc / hir / def_id.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use ty;
12
13 use rustc_data_structures::indexed_vec::Idx;
14 use serialize::{self, Encoder, Decoder};
15
16 use std::fmt;
17 use std::u32;
18
19 newtype_index!(CrateNum nopub
20     {
21         /// Item definitions in the currently-compiled crate would have the CrateNum
22         /// LOCAL_CRATE in their DefId.
23         const LOCAL_CRATE = 0,
24
25         /// Virtual crate for builtin macros
26         // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
27         // `CrateNum`s.
28         const BUILTIN_MACROS_CRATE = u32::MAX,
29
30         /// A CrateNum value that indicates that something is wrong.
31         const INVALID_CRATE = u32::MAX - 1,
32     });
33
34 impl CrateNum {
35     pub fn new(x: usize) -> CrateNum {
36         assert!(x < (u32::MAX as usize));
37         CrateNum(x as u32)
38     }
39
40     pub fn from_u32(x: u32) -> CrateNum {
41         CrateNum(x)
42     }
43
44     pub fn as_usize(&self) -> usize {
45         self.0 as usize
46     }
47
48     pub fn as_u32(&self) -> u32 {
49         self.0
50     }
51
52     pub fn as_def_id(&self) -> DefId { DefId { krate: *self, index: CRATE_DEF_INDEX } }
53 }
54
55 impl fmt::Display for CrateNum {
56     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57         fmt::Display::fmt(&self.0, f)
58     }
59 }
60
61 impl serialize::UseSpecializedEncodable for CrateNum {
62     fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
63         s.emit_u32(self.0)
64     }
65 }
66
67 impl serialize::UseSpecializedDecodable for CrateNum {
68     fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
69         d.read_u32().map(CrateNum)
70     }
71 }
72
73 /// A DefIndex is an index into the hir-map for a crate, identifying a
74 /// particular definition. It should really be considered an interned
75 /// shorthand for a particular DefPath.
76 ///
77 /// At the moment we are allocating the numerical values of DefIndexes into two
78 /// ranges: the "low" range (starting at zero) and the "high" range (starting at
79 /// DEF_INDEX_HI_START). This allows us to allocate the DefIndexes of all
80 /// item-likes (Items, TraitItems, and ImplItems) into one of these ranges and
81 /// consequently use a simple array for lookup tables keyed by DefIndex and
82 /// known to be densely populated. This is especially important for the HIR map.
83 ///
84 /// Since the DefIndex is mostly treated as an opaque ID, you probably
85 /// don't have to care about these ranges.
86 #[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
87            RustcDecodable, Hash, Copy)]
88 pub struct DefIndex(u32);
89
90 impl Idx for DefIndex {
91     fn new(value: usize) -> Self {
92         assert!(value < (u32::MAX) as usize);
93         DefIndex(value as u32)
94     }
95
96     fn index(self) -> usize {
97         self.0 as usize
98     }
99 }
100
101 impl fmt::Debug for DefIndex {
102     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103         write!(f,
104                "DefIndex({}:{})",
105                self.address_space().index(),
106                self.as_array_index())
107     }
108 }
109
110 impl DefIndex {
111     #[inline]
112     pub fn new(x: usize) -> DefIndex {
113         assert!(x < (u32::MAX as usize));
114         DefIndex(x as u32)
115     }
116
117     #[inline]
118     pub fn from_u32(x: u32) -> DefIndex {
119         DefIndex(x)
120     }
121
122     #[inline]
123     pub fn as_usize(&self) -> usize {
124         self.0 as usize
125     }
126
127     #[inline]
128     pub fn as_u32(&self) -> u32 {
129         self.0
130     }
131
132     #[inline]
133     pub fn address_space(&self) -> DefIndexAddressSpace {
134         if self.0 < DEF_INDEX_HI_START.0 {
135             DefIndexAddressSpace::Low
136         } else {
137             DefIndexAddressSpace::High
138         }
139     }
140
141     /// Converts this DefIndex into a zero-based array index.
142     /// This index is the offset within the given "range" of the DefIndex,
143     /// that is, if the DefIndex is part of the "high" range, the resulting
144     /// index will be (DefIndex - DEF_INDEX_HI_START).
145     #[inline]
146     pub fn as_array_index(&self) -> usize {
147         (self.0 & !DEF_INDEX_HI_START.0) as usize
148     }
149
150     pub fn from_array_index(i: usize, address_space: DefIndexAddressSpace) -> DefIndex {
151         DefIndex::new(address_space.start() + i)
152     }
153 }
154
155 /// The start of the "high" range of DefIndexes.
156 const DEF_INDEX_HI_START: DefIndex = DefIndex(1 << 31);
157
158 /// The crate root is always assigned index 0 by the AST Map code,
159 /// thanks to `NodeCollector::new`.
160 pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
161
162 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
163 pub enum DefIndexAddressSpace {
164     Low = 0,
165     High = 1,
166 }
167
168 impl DefIndexAddressSpace {
169     #[inline]
170     pub fn index(&self) -> usize {
171         *self as usize
172     }
173
174     #[inline]
175     pub fn start(&self) -> usize {
176         self.index() * DEF_INDEX_HI_START.as_usize()
177     }
178 }
179
180 /// A DefId identifies a particular *definition*, by combining a crate
181 /// index and a def index.
182 #[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, RustcDecodable, Hash, Copy)]
183 pub struct DefId {
184     pub krate: CrateNum,
185     pub index: DefIndex,
186 }
187
188 impl fmt::Debug for DefId {
189     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
190         write!(f, "DefId {{ krate: {:?}, index: {:?}",
191                self.krate, self.index)?;
192
193         ty::tls::with_opt(|opt_tcx| {
194             if let Some(tcx) = opt_tcx {
195                 write!(f, " => {}", tcx.def_path_debug_str(*self))?;
196             }
197             Ok(())
198         })?;
199
200         write!(f, " }}")
201     }
202 }
203
204
205 impl DefId {
206     /// Make a local `DefId` with the given index.
207     pub fn local(index: DefIndex) -> DefId {
208         DefId { krate: LOCAL_CRATE, index: index }
209     }
210
211     pub fn is_local(&self) -> bool {
212         self.krate == LOCAL_CRATE
213     }
214 }