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