]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
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 | ||
223e47cc LB |
11 | // Decoding metadata from a single crate's metadata |
12 | ||
0531ce1d | 13 | use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; |
9e0c209e SL |
14 | use schema::*; |
15 | ||
0531ce1d | 16 | use rustc_data_structures::sync::{Lrc, ReadGuard}; |
2c00a5a8 XL |
17 | use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, |
18 | DisambiguatedDefPathData}; | |
54a0048b | 19 | use rustc::hir; |
83c7162d | 20 | use rustc::middle::cstore::LinkagePreference; |
0531ce1d | 21 | use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; |
c30ab7b3 | 22 | use rustc::hir::def::{self, Def, CtorKind}; |
2c00a5a8 | 23 | use rustc::hir::def_id::{CrateNum, DefId, DefIndex, |
0531ce1d | 24 | CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId}; |
ea8adc8c | 25 | use rustc::ich::Fingerprint; |
9e0c209e | 26 | use rustc::middle::lang_items; |
0531ce1d | 27 | use rustc::mir::{self, interpret}; |
476ff2be | 28 | use rustc::session::Session; |
9e0c209e | 29 | use rustc::ty::{self, Ty, TyCtxt}; |
abe05a73 | 30 | use rustc::ty::codec::TyDecoder; |
c30ab7b3 | 31 | use rustc::mir::Mir; |
0531ce1d XL |
32 | use rustc::util::captures::Captures; |
33 | use rustc::util::nodemap::FxHashMap; | |
9cc50fc6 | 34 | |
c34b1796 | 35 | use std::io; |
9e0c209e | 36 | use std::mem; |
9e0c209e | 37 | use std::u32; |
1a4d82fc | 38 | |
9e0c209e | 39 | use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; |
b039eaaf | 40 | use syntax::attr; |
7cac9316 | 41 | use syntax::ast::{self, Ident}; |
3157f602 | 42 | use syntax::codemap; |
83c7162d | 43 | use syntax::symbol::InternedString; |
8bb4bdeb | 44 | use syntax::ext::base::MacroKind; |
cc61c64b | 45 | use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; |
223e47cc | 46 | |
9e0c209e SL |
47 | pub struct DecodeContext<'a, 'tcx: 'a> { |
48 | opaque: opaque::Decoder<'a>, | |
9e0c209e | 49 | cdata: Option<&'a CrateMetadata>, |
476ff2be SL |
50 | sess: Option<&'a Session>, |
51 | tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>, | |
c34b1796 | 52 | |
9e0c209e SL |
53 | // Cache the last used filemap for translating spans as an optimization. |
54 | last_filemap_index: usize, | |
223e47cc | 55 | |
c30ab7b3 | 56 | lazy_state: LazyState, |
0531ce1d XL |
57 | |
58 | // interpreter allocation cache | |
59 | interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>, | |
60 | ||
61 | // Read from the LazySeq CrateRoot::inpterpret_alloc_index on demand | |
62 | interpret_alloc_index: Option<Vec<u32>>, | |
223e47cc LB |
63 | } |
64 | ||
9e0c209e SL |
65 | /// Abstract over the various ways one can create metadata decoders. |
66 | pub trait Metadata<'a, 'tcx>: Copy { | |
67 | fn raw_bytes(self) -> &'a [u8]; | |
476ff2be SL |
68 | fn cdata(self) -> Option<&'a CrateMetadata> { None } |
69 | fn sess(self) -> Option<&'a Session> { None } | |
70 | fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { None } | |
b039eaaf | 71 | |
9e0c209e | 72 | fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { |
476ff2be | 73 | let tcx = self.tcx(); |
9e0c209e SL |
74 | DecodeContext { |
75 | opaque: opaque::Decoder::new(self.raw_bytes(), pos), | |
76 | cdata: self.cdata(), | |
476ff2be | 77 | sess: self.sess().or(tcx.map(|tcx| tcx.sess)), |
3b2f2976 | 78 | tcx, |
9e0c209e | 79 | last_filemap_index: 0, |
c30ab7b3 | 80 | lazy_state: LazyState::NoNode, |
0531ce1d XL |
81 | interpret_alloc_cache: FxHashMap::default(), |
82 | interpret_alloc_index: None, | |
9e0c209e SL |
83 | } |
84 | } | |
b039eaaf SL |
85 | } |
86 | ||
9e0c209e SL |
87 | impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob { |
88 | fn raw_bytes(self) -> &'a [u8] { | |
7cac9316 | 89 | &self.0 |
9e0c209e | 90 | } |
223e47cc LB |
91 | } |
92 | ||
abe05a73 XL |
93 | |
94 | impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'a Session) { | |
95 | fn raw_bytes(self) -> &'a [u8] { | |
96 | let (blob, _) = self; | |
97 | &blob.0 | |
98 | } | |
99 | ||
100 | fn sess(self) -> Option<&'a Session> { | |
101 | let (_, sess) = self; | |
102 | Some(sess) | |
103 | } | |
104 | } | |
105 | ||
106 | ||
9e0c209e | 107 | impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata { |
c30ab7b3 SL |
108 | fn raw_bytes(self) -> &'a [u8] { |
109 | self.blob.raw_bytes() | |
110 | } | |
111 | fn cdata(self) -> Option<&'a CrateMetadata> { | |
112 | Some(self) | |
113 | } | |
a7813a04 XL |
114 | } |
115 | ||
476ff2be SL |
116 | impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, &'a Session) { |
117 | fn raw_bytes(self) -> &'a [u8] { | |
118 | self.0.raw_bytes() | |
119 | } | |
120 | fn cdata(self) -> Option<&'a CrateMetadata> { | |
121 | Some(self.0) | |
122 | } | |
123 | fn sess(self) -> Option<&'a Session> { | |
124 | Some(&self.1) | |
125 | } | |
126 | } | |
127 | ||
9e0c209e | 128 | impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>) { |
c30ab7b3 SL |
129 | fn raw_bytes(self) -> &'a [u8] { |
130 | self.0.raw_bytes() | |
131 | } | |
132 | fn cdata(self) -> Option<&'a CrateMetadata> { | |
133 | Some(self.0) | |
134 | } | |
135 | fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { | |
136 | Some(self.1) | |
137 | } | |
223e47cc LB |
138 | } |
139 | ||
9e0c209e SL |
140 | impl<'a, 'tcx: 'a, T: Decodable> Lazy<T> { |
141 | pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T { | |
142 | let mut dcx = meta.decoder(self.position); | |
143 | dcx.lazy_state = LazyState::NodeStart(self.position); | |
144 | T::decode(&mut dcx).unwrap() | |
54a0048b SL |
145 | } |
146 | } | |
147 | ||
9e0c209e | 148 | impl<'a, 'tcx: 'a, T: Decodable> LazySeq<T> { |
0531ce1d XL |
149 | pub fn decode<M: Metadata<'a, 'tcx>>( |
150 | self, | |
151 | meta: M, | |
152 | ) -> impl Iterator<Item = T> + Captures<'tcx> + 'a { | |
9e0c209e SL |
153 | let mut dcx = meta.decoder(self.position); |
154 | dcx.lazy_state = LazyState::NodeStart(self.position); | |
c30ab7b3 | 155 | (0..self.len).map(move |_| T::decode(&mut dcx).unwrap()) |
62682a34 SL |
156 | } |
157 | } | |
158 | ||
9e0c209e SL |
159 | impl<'a, 'tcx> DecodeContext<'a, 'tcx> { |
160 | pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { | |
161 | self.tcx.expect("missing TyCtxt in DecodeContext") | |
162 | } | |
223e47cc | 163 | |
9e0c209e SL |
164 | pub fn cdata(&self) -> &'a CrateMetadata { |
165 | self.cdata.expect("missing CrateMetadata in DecodeContext") | |
166 | } | |
a7813a04 | 167 | |
c30ab7b3 | 168 | fn read_lazy_distance(&mut self, min_size: usize) -> Result<usize, <Self as Decoder>::Error> { |
9e0c209e SL |
169 | let distance = self.read_usize()?; |
170 | let position = match self.lazy_state { | |
c30ab7b3 | 171 | LazyState::NoNode => bug!("read_lazy_distance: outside of a metadata node"), |
9e0c209e SL |
172 | LazyState::NodeStart(start) => { |
173 | assert!(distance + min_size <= start); | |
174 | start - distance - min_size | |
175 | } | |
c30ab7b3 | 176 | LazyState::Previous(last_min_end) => last_min_end + distance, |
9e0c209e SL |
177 | }; |
178 | self.lazy_state = LazyState::Previous(position + min_size); | |
179 | Ok(position) | |
180 | } | |
0531ce1d XL |
181 | |
182 | fn interpret_alloc(&mut self, idx: usize) -> usize { | |
183 | if let Some(index) = self.interpret_alloc_index.as_mut() { | |
184 | return index[idx] as usize; | |
185 | } | |
186 | let cdata = self.cdata(); | |
187 | let index: Vec<u32> = cdata.root.interpret_alloc_index.decode(cdata).collect(); | |
188 | let pos = index[idx]; | |
189 | self.interpret_alloc_index = Some(index); | |
190 | pos as usize | |
191 | } | |
223e47cc LB |
192 | } |
193 | ||
abe05a73 XL |
194 | impl<'a, 'tcx: 'a> TyDecoder<'a, 'tcx> for DecodeContext<'a, 'tcx> { |
195 | ||
196 | #[inline] | |
197 | fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { | |
198 | self.tcx.expect("missing TyCtxt in DecodeContext") | |
199 | } | |
200 | ||
201 | #[inline] | |
202 | fn peek_byte(&self) -> u8 { | |
203 | self.opaque.data[self.opaque.position()] | |
9e0c209e | 204 | } |
223e47cc | 205 | |
abe05a73 XL |
206 | #[inline] |
207 | fn position(&self) -> usize { | |
208 | self.opaque.position() | |
209 | } | |
223e47cc | 210 | |
abe05a73 XL |
211 | fn cached_ty_for_shorthand<F>(&mut self, |
212 | shorthand: usize, | |
213 | or_insert_with: F) | |
214 | -> Result<Ty<'tcx>, Self::Error> | |
215 | where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error> | |
216 | { | |
217 | let tcx = self.tcx(); | |
223e47cc | 218 | |
abe05a73 XL |
219 | let key = ty::CReaderCacheKey { |
220 | cnum: self.cdata().cnum, | |
221 | pos: shorthand, | |
222 | }; | |
1a4d82fc | 223 | |
abe05a73 XL |
224 | if let Some(&ty) = tcx.rcache.borrow().get(&key) { |
225 | return Ok(ty); | |
226 | } | |
223e47cc | 227 | |
abe05a73 XL |
228 | let ty = or_insert_with(self)?; |
229 | tcx.rcache.borrow_mut().insert(key, ty); | |
230 | Ok(ty) | |
9e0c209e | 231 | } |
62682a34 | 232 | |
abe05a73 XL |
233 | fn with_position<F, R>(&mut self, pos: usize, f: F) -> R |
234 | where F: FnOnce(&mut Self) -> R | |
235 | { | |
236 | let new_opaque = opaque::Decoder::new(self.opaque.data, pos); | |
237 | let old_opaque = mem::replace(&mut self.opaque, new_opaque); | |
238 | let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode); | |
239 | let r = f(self); | |
240 | self.opaque = old_opaque; | |
241 | self.lazy_state = old_state; | |
242 | r | |
243 | } | |
244 | ||
245 | fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { | |
246 | if cnum == LOCAL_CRATE { | |
247 | self.cdata().cnum | |
248 | } else { | |
249 | self.cdata().cnum_map.borrow()[cnum] | |
250 | } | |
9e0c209e | 251 | } |
970d7e83 LB |
252 | } |
253 | ||
9e0c209e SL |
254 | impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> { |
255 | fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> { | |
256 | Ok(Lazy::with_position(self.read_lazy_distance(Lazy::<T>::min_size())?)) | |
257 | } | |
223e47cc LB |
258 | } |
259 | ||
9e0c209e SL |
260 | impl<'a, 'tcx, T> SpecializedDecoder<LazySeq<T>> for DecodeContext<'a, 'tcx> { |
261 | fn specialized_decode(&mut self) -> Result<LazySeq<T>, Self::Error> { | |
262 | let len = self.read_usize()?; | |
263 | let position = if len == 0 { | |
264 | 0 | |
265 | } else { | |
266 | self.read_lazy_distance(LazySeq::<T>::min_size(len))? | |
267 | }; | |
268 | Ok(LazySeq::with_position_and_length(position, len)) | |
269 | } | |
970d7e83 LB |
270 | } |
271 | ||
abe05a73 XL |
272 | |
273 | impl<'a, 'tcx> SpecializedDecoder<DefId> for DecodeContext<'a, 'tcx> { | |
274 | #[inline] | |
275 | fn specialized_decode(&mut self) -> Result<DefId, Self::Error> { | |
276 | let krate = CrateNum::decode(self)?; | |
277 | let index = DefIndex::decode(self)?; | |
278 | ||
279 | Ok(DefId { | |
280 | krate, | |
281 | index, | |
282 | }) | |
283 | } | |
284 | } | |
285 | ||
286 | impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> { | |
287 | #[inline] | |
288 | fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> { | |
2c00a5a8 | 289 | Ok(DefIndex::from_raw_u32(self.read_u32()?)) |
1a4d82fc JJ |
290 | } |
291 | } | |
292 | ||
0531ce1d XL |
293 | impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for DecodeContext<'a, 'tcx> { |
294 | #[inline] | |
295 | fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> { | |
296 | self.specialized_decode().map(|i| LocalDefId::from_def_id(i)) | |
297 | } | |
298 | } | |
299 | ||
300 | impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> { | |
301 | fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> { | |
302 | let tcx = self.tcx.unwrap(); | |
303 | let idx = usize::decode(self)?; | |
304 | ||
305 | if let Some(cached) = self.interpret_alloc_cache.get(&idx).cloned() { | |
306 | return Ok(cached); | |
307 | } | |
308 | let pos = self.interpret_alloc(idx); | |
309 | self.with_position(pos, |this| { | |
310 | interpret::specialized_decode_alloc_id( | |
311 | this, | |
312 | tcx, | |
313 | |this, alloc_id| { | |
314 | assert!(this.interpret_alloc_cache.insert(idx, alloc_id).is_none()); | |
315 | }, | |
316 | ) | |
317 | }) | |
318 | } | |
319 | } | |
320 | ||
9e0c209e SL |
321 | impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> { |
322 | fn specialized_decode(&mut self) -> Result<Span, Self::Error> { | |
2c00a5a8 | 323 | let tag = u8::decode(self)?; |
85aaf69f | 324 | |
2c00a5a8 | 325 | if tag == TAG_INVALID_SPAN { |
ff7c6d11 XL |
326 | return Ok(DUMMY_SP) |
327 | } | |
328 | ||
2c00a5a8 XL |
329 | debug_assert_eq!(tag, TAG_VALID_SPAN); |
330 | ||
331 | let lo = BytePos::decode(self)?; | |
332 | let len = BytePos::decode(self)?; | |
333 | let hi = lo + len; | |
ff7c6d11 | 334 | |
476ff2be SL |
335 | let sess = if let Some(sess) = self.sess { |
336 | sess | |
9e0c209e | 337 | } else { |
abe05a73 | 338 | bug!("Cannot decode Span without Session.") |
9e0c209e | 339 | }; |
85aaf69f | 340 | |
476ff2be | 341 | let imported_filemaps = self.cdata().imported_filemaps(&sess.codemap()); |
9e0c209e SL |
342 | let filemap = { |
343 | // Optimize for the case that most spans within a translated item | |
344 | // originate from the same filemap. | |
345 | let last_filemap = &imported_filemaps[self.last_filemap_index]; | |
346 | ||
abe05a73 | 347 | if lo >= last_filemap.original_start_pos && |
2c00a5a8 | 348 | lo <= last_filemap.original_end_pos { |
9e0c209e SL |
349 | last_filemap |
350 | } else { | |
351 | let mut a = 0; | |
352 | let mut b = imported_filemaps.len(); | |
970d7e83 | 353 | |
9e0c209e SL |
354 | while b - a > 1 { |
355 | let m = (a + b) / 2; | |
356 | if imported_filemaps[m].original_start_pos > lo { | |
357 | b = m; | |
358 | } else { | |
359 | a = m; | |
360 | } | |
361 | } | |
e9174d1e | 362 | |
9e0c209e SL |
363 | self.last_filemap_index = a; |
364 | &imported_filemaps[a] | |
e9174d1e | 365 | } |
9e0c209e SL |
366 | }; |
367 | ||
ff7c6d11 XL |
368 | // Make sure our binary search above is correct. |
369 | debug_assert!(lo >= filemap.original_start_pos && | |
370 | lo <= filemap.original_end_pos); | |
371 | ||
2c00a5a8 XL |
372 | // Make sure we correctly filtered out invalid spans during encoding |
373 | debug_assert!(hi >= filemap.original_start_pos && | |
374 | hi <= filemap.original_end_pos); | |
ff7c6d11 | 375 | |
abe05a73 XL |
376 | let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos; |
377 | let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos; | |
9e0c209e | 378 | |
ea8adc8c | 379 | Ok(Span::new(lo, hi, NO_EXPANSION)) |
e9174d1e | 380 | } |
9e0c209e | 381 | } |
e9174d1e | 382 | |
2c00a5a8 XL |
383 | impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> { |
384 | fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> { | |
385 | Fingerprint::decode_opaque(&mut self.opaque) | |
386 | } | |
387 | } | |
388 | ||
ff7c6d11 XL |
389 | impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>> |
390 | for DecodeContext<'a, 'tcx> { | |
391 | #[inline] | |
392 | fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> { | |
393 | Ok(mir::ClearCrossCrate::Clear) | |
394 | } | |
395 | } | |
396 | ||
abe05a73 | 397 | implement_ty_decoder!( DecodeContext<'a, 'tcx> ); |
ea8adc8c | 398 | |
9e0c209e SL |
399 | impl<'a, 'tcx> MetadataBlob { |
400 | pub fn is_compatible(&self) -> bool { | |
401 | self.raw_bytes().starts_with(METADATA_HEADER) | |
85aaf69f | 402 | } |
85aaf69f | 403 | |
476ff2be SL |
404 | pub fn get_rustc_version(&self) -> String { |
405 | Lazy::with_position(METADATA_HEADER.len() + 4).decode(self) | |
406 | } | |
407 | ||
9e0c209e SL |
408 | pub fn get_root(&self) -> CrateRoot { |
409 | let slice = self.raw_bytes(); | |
410 | let offset = METADATA_HEADER.len(); | |
c30ab7b3 | 411 | let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | |
9e0c209e SL |
412 | ((slice[offset + 2] as u32) << 8) | |
413 | ((slice[offset + 3] as u32) << 0)) as usize; | |
414 | Lazy::with_position(pos).decode(self) | |
415 | } | |
416 | ||
7cac9316 XL |
417 | pub fn list_crate_metadata(&self, |
418 | out: &mut io::Write) -> io::Result<()> { | |
9e0c209e SL |
419 | write!(out, "=External Dependencies=\n")?; |
420 | let root = self.get_root(); | |
7cac9316 | 421 | for (i, dep) in root.crate_deps |
7cac9316 XL |
422 | .decode(self) |
423 | .enumerate() { | |
9e0c209e | 424 | write!(out, "{} {}-{}\n", i + 1, dep.name, dep.hash)?; |
1a4d82fc | 425 | } |
9e0c209e SL |
426 | write!(out, "\n")?; |
427 | Ok(()) | |
970d7e83 | 428 | } |
223e47cc LB |
429 | } |
430 | ||
9e0c209e SL |
431 | impl<'tcx> EntryKind<'tcx> { |
432 | fn to_def(&self, did: DefId) -> Option<Def> { | |
433 | Some(match *self { | |
83c7162d | 434 | EntryKind::Const(..) => Def::Const(did), |
8bb4bdeb | 435 | EntryKind::AssociatedConst(..) => Def::AssociatedConst(did), |
9e0c209e SL |
436 | EntryKind::ImmStatic | |
437 | EntryKind::ForeignImmStatic => Def::Static(did, false), | |
438 | EntryKind::MutStatic | | |
439 | EntryKind::ForeignMutStatic => Def::Static(did, true), | |
8bb4bdeb XL |
440 | EntryKind::Struct(_, _) => Def::Struct(did), |
441 | EntryKind::Union(_, _) => Def::Union(did), | |
9e0c209e SL |
442 | EntryKind::Fn(_) | |
443 | EntryKind::ForeignFn(_) => Def::Fn(did), | |
444 | EntryKind::Method(_) => Def::Method(did), | |
445 | EntryKind::Type => Def::TyAlias(did), | |
446 | EntryKind::AssociatedType(_) => Def::AssociatedTy(did), | |
447 | EntryKind::Mod(_) => Def::Mod(did), | |
448 | EntryKind::Variant(_) => Def::Variant(did), | |
449 | EntryKind::Trait(_) => Def::Trait(did), | |
8bb4bdeb XL |
450 | EntryKind::Enum(..) => Def::Enum(did), |
451 | EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang), | |
cc61c64b | 452 | EntryKind::GlobalAsm => Def::GlobalAsm(did), |
abe05a73 | 453 | EntryKind::ForeignType => Def::TyForeign(did), |
9e0c209e SL |
454 | |
455 | EntryKind::ForeignMod | | |
456 | EntryKind::Impl(_) | | |
9e0c209e | 457 | EntryKind::Field | |
ea8adc8c | 458 | EntryKind::Generator(_) | |
c30ab7b3 | 459 | EntryKind::Closure(_) => return None, |
9e0c209e SL |
460 | }) |
461 | } | |
223e47cc LB |
462 | } |
463 | ||
9e0c209e | 464 | impl<'a, 'tcx> CrateMetadata { |
476ff2be SL |
465 | fn is_proc_macro(&self, id: DefIndex) -> bool { |
466 | self.proc_macros.is_some() && id != CRATE_DEF_INDEX | |
467 | } | |
468 | ||
9e0c209e | 469 | fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> { |
476ff2be | 470 | assert!(!self.is_proc_macro(item_id)); |
9e0c209e SL |
471 | self.root.index.lookup(self.blob.raw_bytes(), item_id) |
472 | } | |
970d7e83 | 473 | |
9e0c209e SL |
474 | fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { |
475 | match self.maybe_entry(item_id) { | |
c30ab7b3 SL |
476 | None => { |
477 | bug!("entry: id not found: {:?} in crate {:?} with number {}", | |
478 | item_id, | |
479 | self.name, | |
480 | self.cnum) | |
481 | } | |
482 | Some(d) => d.decode(self), | |
970d7e83 | 483 | } |
62682a34 | 484 | } |
1a4d82fc | 485 | |
9e0c209e SL |
486 | fn local_def_id(&self, index: DefIndex) -> DefId { |
487 | DefId { | |
488 | krate: self.cnum, | |
3b2f2976 | 489 | index, |
970d7e83 | 490 | } |
62682a34 | 491 | } |
5bcae85e | 492 | |
ea8adc8c | 493 | pub fn item_name(&self, item_index: DefIndex) -> InternedString { |
32a655c1 | 494 | self.def_key(item_index) |
c30ab7b3 SL |
495 | .disambiguated_data |
496 | .data | |
497 | .get_opt_name() | |
9e0c209e | 498 | .expect("no name in item_name") |
223e47cc | 499 | } |
223e47cc | 500 | |
9e0c209e | 501 | pub fn get_def(&self, index: DefIndex) -> Option<Def> { |
8bb4bdeb XL |
502 | if !self.is_proc_macro(index) { |
503 | self.entry(index).kind.to_def(self.local_def_id(index)) | |
504 | } else { | |
2c00a5a8 | 505 | let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind(); |
8bb4bdeb | 506 | Some(Def::Macro(self.local_def_id(index), kind)) |
476ff2be SL |
507 | } |
508 | } | |
509 | ||
510 | pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span { | |
511 | match self.is_proc_macro(index) { | |
512 | true => DUMMY_SP, | |
513 | false => self.entry(index).span.decode((self, sess)), | |
514 | } | |
7453a54e SL |
515 | } |
516 | ||
abe05a73 | 517 | pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { |
9e0c209e | 518 | let data = match self.entry(item_id).kind { |
abe05a73 | 519 | EntryKind::Trait(data) => data.decode((self, sess)), |
c30ab7b3 | 520 | _ => bug!(), |
9e0c209e | 521 | }; |
7453a54e | 522 | |
7cac9316 XL |
523 | ty::TraitDef::new(self.local_def_id(item_id), |
524 | data.unsafety, | |
525 | data.paren_sugar, | |
abe05a73 | 526 | data.has_auto_impl, |
7cac9316 | 527 | self.def_path_table.def_path_hash(item_id)) |
9e0c209e | 528 | } |
9cc50fc6 | 529 | |
cc61c64b | 530 | fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef { |
9e0c209e SL |
531 | let data = match item.kind { |
532 | EntryKind::Variant(data) | | |
8bb4bdeb XL |
533 | EntryKind::Struct(data, _) | |
534 | EntryKind::Union(data, _) => data.decode(self), | |
c30ab7b3 | 535 | _ => bug!(), |
9cc50fc6 | 536 | }; |
9cc50fc6 | 537 | |
cc61c64b | 538 | ty::VariantDef { |
476ff2be | 539 | did: self.local_def_id(data.struct_ctor.unwrap_or(index)), |
83c7162d | 540 | name: self.item_name(index).as_symbol(), |
476ff2be | 541 | fields: item.children.decode(self).map(|index| { |
c30ab7b3 | 542 | let f = self.entry(index); |
476ff2be SL |
543 | ty::FieldDef { |
544 | did: self.local_def_id(index), | |
83c7162d | 545 | name: self.item_name(index).as_symbol(), |
32a655c1 | 546 | vis: f.visibility.decode(self) |
476ff2be SL |
547 | } |
548 | }).collect(), | |
8bb4bdeb | 549 | discr: data.discr, |
476ff2be | 550 | ctor_kind: data.ctor_kind, |
cc61c64b | 551 | } |
c30ab7b3 SL |
552 | } |
553 | ||
554 | pub fn get_adt_def(&self, | |
555 | item_id: DefIndex, | |
556 | tcx: TyCtxt<'a, 'tcx, 'tcx>) | |
476ff2be | 557 | -> &'tcx ty::AdtDef { |
9e0c209e SL |
558 | let item = self.entry(item_id); |
559 | let did = self.local_def_id(item_id); | |
8bb4bdeb XL |
560 | let kind = match item.kind { |
561 | EntryKind::Enum(_) => ty::AdtKind::Enum, | |
562 | EntryKind::Struct(_, _) => ty::AdtKind::Struct, | |
563 | EntryKind::Union(_, _) => ty::AdtKind::Union, | |
564 | _ => bug!("get_adt_def called on a non-ADT {:?}", did), | |
565 | }; | |
8bb4bdeb | 566 | let variants = if let ty::AdtKind::Enum = kind { |
c30ab7b3 SL |
567 | item.children |
568 | .decode(self) | |
569 | .map(|index| { | |
cc61c64b | 570 | self.get_variant(&self.entry(index), index) |
c30ab7b3 SL |
571 | }) |
572 | .collect() | |
573 | } else { | |
cc61c64b | 574 | vec![self.get_variant(&item, item_id)] |
9e0c209e | 575 | }; |
8bb4bdeb XL |
576 | let (kind, repr) = match item.kind { |
577 | EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr), | |
578 | EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr), | |
579 | EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr), | |
c30ab7b3 | 580 | _ => bug!("get_adt_def called on a non-ADT {:?}", did), |
9cc50fc6 SL |
581 | }; |
582 | ||
cc61c64b | 583 | tcx.alloc_adt_def(did, kind, variants, repr) |
9cc50fc6 SL |
584 | } |
585 | ||
c30ab7b3 SL |
586 | pub fn get_predicates(&self, |
587 | item_id: DefIndex, | |
588 | tcx: TyCtxt<'a, 'tcx, 'tcx>) | |
9e0c209e SL |
589 | -> ty::GenericPredicates<'tcx> { |
590 | self.entry(item_id).predicates.unwrap().decode((self, tcx)) | |
591 | } | |
9cc50fc6 | 592 | |
c30ab7b3 SL |
593 | pub fn get_super_predicates(&self, |
594 | item_id: DefIndex, | |
595 | tcx: TyCtxt<'a, 'tcx, 'tcx>) | |
9e0c209e SL |
596 | -> ty::GenericPredicates<'tcx> { |
597 | match self.entry(item_id).kind { | |
c30ab7b3 SL |
598 | EntryKind::Trait(data) => data.decode(self).super_predicates.decode((self, tcx)), |
599 | _ => bug!(), | |
9cc50fc6 SL |
600 | } |
601 | } | |
9cc50fc6 | 602 | |
abe05a73 XL |
603 | pub fn get_generics(&self, |
604 | item_id: DefIndex, | |
605 | sess: &Session) | |
606 | -> ty::Generics { | |
607 | self.entry(item_id).generics.unwrap().decode((self, sess)) | |
223e47cc LB |
608 | } |
609 | ||
9e0c209e SL |
610 | pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { |
611 | self.entry(id).ty.unwrap().decode((self, tcx)) | |
612 | } | |
223e47cc | 613 | |
9e0c209e | 614 | pub fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> { |
476ff2be SL |
615 | match self.is_proc_macro(id) { |
616 | true => None, | |
617 | false => self.entry(id).stability.map(|stab| stab.decode(self)), | |
618 | } | |
223e47cc | 619 | } |
223e47cc | 620 | |
9e0c209e | 621 | pub fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> { |
476ff2be SL |
622 | match self.is_proc_macro(id) { |
623 | true => None, | |
624 | false => self.entry(id).deprecation.map(|depr| depr.decode(self)), | |
625 | } | |
9e0c209e | 626 | } |
1a4d82fc | 627 | |
9e0c209e | 628 | pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { |
476ff2be SL |
629 | match self.is_proc_macro(id) { |
630 | true => ty::Visibility::Public, | |
32a655c1 | 631 | false => self.entry(id).visibility.decode(self), |
476ff2be | 632 | } |
9e0c209e | 633 | } |
1a4d82fc | 634 | |
9e0c209e SL |
635 | fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { |
636 | match self.entry(id).kind { | |
637 | EntryKind::Impl(data) => data.decode(self), | |
c30ab7b3 | 638 | _ => bug!(), |
1a4d82fc | 639 | } |
223e47cc | 640 | } |
223e47cc | 641 | |
9e0c209e SL |
642 | pub fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> { |
643 | self.get_impl_data(id).parent_impl | |
644 | } | |
1a4d82fc | 645 | |
9e0c209e SL |
646 | pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity { |
647 | self.get_impl_data(id).polarity | |
648 | } | |
223e47cc | 649 | |
7cac9316 XL |
650 | pub fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness { |
651 | self.get_impl_data(id).defaultness | |
652 | } | |
653 | ||
cc61c64b XL |
654 | pub fn get_coerce_unsized_info(&self, |
655 | id: DefIndex) | |
656 | -> Option<ty::adjustment::CoerceUnsizedInfo> { | |
657 | self.get_impl_data(id).coerce_unsized_info | |
9e0c209e | 658 | } |
1a4d82fc | 659 | |
9e0c209e SL |
660 | pub fn get_impl_trait(&self, |
661 | id: DefIndex, | |
662 | tcx: TyCtxt<'a, 'tcx, 'tcx>) | |
663 | -> Option<ty::TraitRef<'tcx>> { | |
664 | self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx))) | |
665 | } | |
223e47cc | 666 | |
9e0c209e | 667 | /// Iterates over the language items in the given crate. |
ea8adc8c | 668 | pub fn get_lang_items(&self) -> Vec<(DefId, usize)> { |
7cac9316 XL |
669 | self.root |
670 | .lang_items | |
7cac9316 | 671 | .decode(self) |
ea8adc8c | 672 | .map(|(def_index, index)| (self.local_def_id(def_index), index)) |
7cac9316 | 673 | .collect() |
9e0c209e | 674 | } |
223e47cc | 675 | |
9e0c209e | 676 | /// Iterates over each child of the given item. |
041b39d2 | 677 | pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session) |
9e0c209e SL |
678 | where F: FnMut(def::Export) |
679 | { | |
476ff2be SL |
680 | if let Some(ref proc_macros) = self.proc_macros { |
681 | if id == CRATE_DEF_INDEX { | |
8bb4bdeb XL |
682 | for (id, &(name, ref ext)) in proc_macros.iter().enumerate() { |
683 | let def = Def::Macro( | |
684 | DefId { | |
685 | krate: self.cnum, | |
2c00a5a8 | 686 | index: DefIndex::from_proc_macro_index(id), |
8bb4bdeb XL |
687 | }, |
688 | ext.kind() | |
689 | ); | |
7cac9316 | 690 | let ident = Ident::with_empty_ctxt(name); |
ff7c6d11 XL |
691 | callback(def::Export { |
692 | ident: ident, | |
693 | def: def, | |
694 | vis: ty::Visibility::Public, | |
695 | span: DUMMY_SP, | |
696 | is_import: false, | |
697 | }); | |
476ff2be SL |
698 | } |
699 | } | |
700 | return | |
701 | } | |
702 | ||
9e0c209e SL |
703 | // Find the item. |
704 | let item = match self.maybe_entry(id) { | |
705 | None => return, | |
041b39d2 | 706 | Some(item) => item.decode((self, sess)), |
9e0c209e | 707 | }; |
223e47cc | 708 | |
9e0c209e | 709 | // Iterate over all children. |
0531ce1d | 710 | let macros_only = self.dep_kind.lock().macros_only(); |
041b39d2 | 711 | for child_index in item.children.decode((self, sess)) { |
476ff2be SL |
712 | if macros_only { |
713 | continue | |
714 | } | |
715 | ||
9e0c209e SL |
716 | // Get the item. |
717 | if let Some(child) = self.maybe_entry(child_index) { | |
041b39d2 | 718 | let child = child.decode((self, sess)); |
476ff2be SL |
719 | match child.kind { |
720 | EntryKind::MacroDef(..) => {} | |
721 | _ if macros_only => continue, | |
722 | _ => {} | |
723 | } | |
724 | ||
9e0c209e SL |
725 | // Hand off the item to the callback. |
726 | match child.kind { | |
727 | // FIXME(eddyb) Don't encode these in children. | |
728 | EntryKind::ForeignMod => { | |
041b39d2 | 729 | for child_index in child.children.decode((self, sess)) { |
c30ab7b3 SL |
730 | if let Some(def) = self.get_def(child_index) { |
731 | callback(def::Export { | |
3b2f2976 | 732 | def, |
83c7162d | 733 | ident: Ident::from_interned_str(self.item_name(child_index)), |
ff7c6d11 | 734 | vis: self.get_visibility(child_index), |
041b39d2 | 735 | span: self.entry(child_index).span.decode((self, sess)), |
ff7c6d11 | 736 | is_import: false, |
c30ab7b3 SL |
737 | }); |
738 | } | |
9e0c209e SL |
739 | } |
740 | continue; | |
741 | } | |
2c00a5a8 | 742 | EntryKind::Impl(_) => continue, |
d9579d0f | 743 | |
9e0c209e SL |
744 | _ => {} |
745 | } | |
b039eaaf | 746 | |
32a655c1 | 747 | let def_key = self.def_key(child_index); |
041b39d2 | 748 | let span = child.span.decode((self, sess)); |
c30ab7b3 SL |
749 | if let (Some(def), Some(name)) = |
750 | (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) { | |
83c7162d | 751 | let ident = Ident::from_interned_str(name); |
ff7c6d11 XL |
752 | let vis = self.get_visibility(child_index); |
753 | let is_import = false; | |
754 | callback(def::Export { def, ident, vis, span, is_import }); | |
2c00a5a8 XL |
755 | // For non-re-export structs and variants add their constructors to children. |
756 | // Re-export lists automatically contain constructors when necessary. | |
c30ab7b3 SL |
757 | match def { |
758 | Def::Struct(..) => { | |
759 | if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) { | |
760 | let ctor_kind = self.get_ctor_kind(child_index); | |
761 | let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind); | |
ff7c6d11 XL |
762 | callback(def::Export { |
763 | def: ctor_def, | |
764 | vis: self.get_visibility(ctor_def_id.index), | |
765 | ident, span, is_import, | |
766 | }); | |
c30ab7b3 SL |
767 | } |
768 | } | |
769 | Def::Variant(def_id) => { | |
770 | // Braced variants, unlike structs, generate unusable names in | |
771 | // value namespace, they are reserved for possible future use. | |
772 | let ctor_kind = self.get_ctor_kind(child_index); | |
773 | let ctor_def = Def::VariantCtor(def_id, ctor_kind); | |
ff7c6d11 XL |
774 | let vis = self.get_visibility(child_index); |
775 | callback(def::Export { def: ctor_def, ident, vis, span, is_import }); | |
c30ab7b3 SL |
776 | } |
777 | _ => {} | |
778 | } | |
d9579d0f AL |
779 | } |
780 | } | |
9e0c209e | 781 | } |
7453a54e | 782 | |
9e0c209e | 783 | if let EntryKind::Mod(data) = item.kind { |
041b39d2 | 784 | for exp in data.decode((self, sess)).reexports.decode((self, sess)) { |
476ff2be SL |
785 | match exp.def { |
786 | Def::Macro(..) => {} | |
787 | _ if macros_only => continue, | |
788 | _ => {} | |
789 | } | |
9e0c209e SL |
790 | callback(exp); |
791 | } | |
792 | } | |
793 | } | |
1a4d82fc | 794 | |
32a655c1 | 795 | pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool { |
83c7162d XL |
796 | match self.entry(id).kind { |
797 | EntryKind::AssociatedConst(_, data, _) | | |
798 | EntryKind::Const(data, _) => data.ast_promotable, | |
799 | _ => bug!(), | |
800 | } | |
32a655c1 SL |
801 | } |
802 | ||
9e0c209e | 803 | pub fn is_item_mir_available(&self, id: DefIndex) -> bool { |
476ff2be | 804 | !self.is_proc_macro(id) && |
9e0c209e SL |
805 | self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() |
806 | } | |
1a4d82fc | 807 | |
7cac9316 XL |
808 | pub fn maybe_get_optimized_mir(&self, |
809 | tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
810 | id: DefIndex) | |
811 | -> Option<Mir<'tcx>> { | |
476ff2be SL |
812 | match self.is_proc_macro(id) { |
813 | true => None, | |
814 | false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))), | |
815 | } | |
223e47cc | 816 | } |
223e47cc | 817 | |
8bb4bdeb XL |
818 | pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { |
819 | match self.entry(id).kind { | |
83c7162d XL |
820 | EntryKind::Const(qualif, _) | |
821 | EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif, _) | | |
822 | EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif, _) => { | |
823 | qualif.mir | |
8bb4bdeb XL |
824 | } |
825 | _ => bug!(), | |
826 | } | |
827 | } | |
828 | ||
829 | pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem { | |
9e0c209e | 830 | let item = self.entry(id); |
8bb4bdeb XL |
831 | let def_key = self.def_key(id); |
832 | let parent = self.local_def_id(def_key.parent.unwrap()); | |
833 | let name = def_key.disambiguated_data.data.get_opt_name().unwrap(); | |
223e47cc | 834 | |
8bb4bdeb | 835 | let (kind, container, has_self) = match item.kind { |
83c7162d | 836 | EntryKind::AssociatedConst(container, _, _) => { |
8bb4bdeb | 837 | (ty::AssociatedKind::Const, container, false) |
9e0c209e SL |
838 | } |
839 | EntryKind::Method(data) => { | |
9e0c209e | 840 | let data = data.decode(self); |
8bb4bdeb | 841 | (ty::AssociatedKind::Method, data.container, data.has_self) |
9e0c209e SL |
842 | } |
843 | EntryKind::AssociatedType(container) => { | |
8bb4bdeb | 844 | (ty::AssociatedKind::Type, container, false) |
9e0c209e | 845 | } |
7cac9316 | 846 | _ => bug!("cannot get associated-item of `{:?}`", def_key) |
8bb4bdeb XL |
847 | }; |
848 | ||
849 | ty::AssociatedItem { | |
83c7162d | 850 | name: name.as_symbol(), |
3b2f2976 | 851 | kind, |
8bb4bdeb XL |
852 | vis: item.visibility.decode(self), |
853 | defaultness: container.defaultness(), | |
854 | def_id: self.local_def_id(id), | |
855 | container: container.with_def_id(parent), | |
856 | method_has_self_argument: has_self | |
857 | } | |
9e0c209e | 858 | } |
223e47cc | 859 | |
9e0c209e SL |
860 | pub fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> { |
861 | self.entry(id).variances.decode(self).collect() | |
223e47cc | 862 | } |
223e47cc | 863 | |
c30ab7b3 | 864 | pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { |
9e0c209e | 865 | match self.entry(node_id).kind { |
8bb4bdeb XL |
866 | EntryKind::Struct(data, _) | |
867 | EntryKind::Union(data, _) | | |
c30ab7b3 SL |
868 | EntryKind::Variant(data) => data.decode(self).ctor_kind, |
869 | _ => CtorKind::Fictive, | |
9e0c209e SL |
870 | } |
871 | } | |
223e47cc | 872 | |
9e0c209e SL |
873 | pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> { |
874 | match self.entry(node_id).kind { | |
8bb4bdeb | 875 | EntryKind::Struct(data, _) => { |
9e0c209e SL |
876 | data.decode(self).struct_ctor.map(|index| self.local_def_id(index)) |
877 | } | |
c30ab7b3 | 878 | _ => None, |
9e0c209e | 879 | } |
223e47cc LB |
880 | } |
881 | ||
0531ce1d | 882 | pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> { |
cc61c64b XL |
883 | let (node_as, node_index) = |
884 | (node_id.address_space().index(), node_id.as_array_index()); | |
476ff2be | 885 | if self.is_proc_macro(node_id) { |
0531ce1d | 886 | return Lrc::new([]); |
cc61c64b XL |
887 | } |
888 | ||
889 | if let Some(&Some(ref val)) = | |
890 | self.attribute_cache.borrow()[node_as].get(node_index) { | |
891 | return val.clone(); | |
476ff2be | 892 | } |
cc61c64b | 893 | |
9e0c209e SL |
894 | // The attributes for a tuple struct are attached to the definition, not the ctor; |
895 | // we assume that someone passing in a tuple struct ctor is actually wanting to | |
896 | // look at the definition | |
897 | let mut item = self.entry(node_id); | |
32a655c1 | 898 | let def_key = self.def_key(node_id); |
9e0c209e SL |
899 | if def_key.disambiguated_data.data == DefPathData::StructCtor { |
900 | item = self.entry(def_key.parent.unwrap()); | |
901 | } | |
0531ce1d | 902 | let result: Lrc<[ast::Attribute]> = Lrc::from(self.get_attributes(&item, sess)); |
cc61c64b XL |
903 | let vec_ = &mut self.attribute_cache.borrow_mut()[node_as]; |
904 | if vec_.len() < node_index + 1 { | |
905 | vec_.resize(node_index + 1, None); | |
906 | } | |
0531ce1d XL |
907 | // This can overwrite the result produced by another thread, but the value |
908 | // written should be the same | |
cc61c64b XL |
909 | vec_[node_index] = Some(result.clone()); |
910 | result | |
9e0c209e | 911 | } |
223e47cc | 912 | |
9e0c209e | 913 | pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> { |
c30ab7b3 SL |
914 | self.entry(id) |
915 | .children | |
916 | .decode(self) | |
83c7162d | 917 | .map(|index| self.item_name(index).as_symbol()) |
c30ab7b3 | 918 | .collect() |
9e0c209e | 919 | } |
223e47cc | 920 | |
abe05a73 | 921 | fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec<ast::Attribute> { |
c30ab7b3 | 922 | item.attributes |
abe05a73 | 923 | .decode((self, sess)) |
c30ab7b3 SL |
924 | .map(|mut attr| { |
925 | // Need new unique IDs: old thread-local IDs won't map to new threads. | |
476ff2be | 926 | attr.id = attr::mk_attr_id(); |
c30ab7b3 SL |
927 | attr |
928 | }) | |
929 | .collect() | |
9e0c209e | 930 | } |
223e47cc | 931 | |
9e0c209e SL |
932 | // Translate a DefId from the current compilation environment to a DefId |
933 | // for an external crate. | |
934 | fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> { | |
935 | for (local, &global) in self.cnum_map.borrow().iter_enumerated() { | |
936 | if global == did.krate { | |
c30ab7b3 SL |
937 | return Some(DefId { |
938 | krate: local, | |
939 | index: did.index, | |
940 | }); | |
9e0c209e | 941 | } |
62682a34 | 942 | } |
223e47cc | 943 | |
9e0c209e | 944 | None |
223e47cc LB |
945 | } |
946 | ||
9e0c209e | 947 | pub fn get_inherent_implementations_for_type(&self, id: DefIndex) -> Vec<DefId> { |
c30ab7b3 SL |
948 | self.entry(id) |
949 | .inherent_impls | |
950 | .decode(self) | |
951 | .map(|index| self.local_def_id(index)) | |
952 | .collect() | |
9e0c209e | 953 | } |
223e47cc | 954 | |
7cac9316 XL |
955 | pub fn get_implementations_for_trait(&self, |
956 | filter: Option<DefId>, | |
7cac9316 | 957 | result: &mut Vec<DefId>) { |
9e0c209e SL |
958 | // Do a reverse lookup beforehand to avoid touching the crate_num |
959 | // hash map in the loop below. | |
960 | let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) { | |
961 | Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)), | |
962 | Some(None) => return, | |
476ff2be | 963 | None if self.proc_macros.is_some() => return, |
c30ab7b3 | 964 | None => None, |
9e0c209e | 965 | }; |
223e47cc | 966 | |
7cac9316 XL |
967 | if let Some(filter) = filter { |
968 | if let Some(impls) = self.trait_impls | |
7cac9316 XL |
969 | .get(&filter) { |
970 | result.extend(impls.decode(self).map(|idx| self.local_def_id(idx))); | |
971 | } | |
972 | } else { | |
ea8adc8c | 973 | for impls in self.trait_impls.values() { |
7cac9316 | 974 | result.extend(impls.decode(self).map(|idx| self.local_def_id(idx))); |
9e0c209e SL |
975 | } |
976 | } | |
977 | } | |
223e47cc | 978 | |
9e0c209e | 979 | pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> { |
83c7162d XL |
980 | let def_key = self.def_key(id); |
981 | match def_key.disambiguated_data.data { | |
982 | DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (), | |
983 | // Not an associated item | |
984 | _ => return None, | |
985 | } | |
986 | def_key.parent.and_then(|parent_index| { | |
9e0c209e SL |
987 | match self.entry(parent_index).kind { |
988 | EntryKind::Trait(_) => Some(self.local_def_id(parent_index)), | |
c30ab7b3 | 989 | _ => None, |
9e0c209e SL |
990 | } |
991 | }) | |
992 | } | |
223e47cc | 993 | |
223e47cc | 994 | |
abe05a73 XL |
995 | pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> { |
996 | self.root.native_libraries.decode((self, sess)).collect() | |
223e47cc LB |
997 | } |
998 | ||
0531ce1d XL |
999 | pub fn get_foreign_modules(&self, sess: &Session) -> Vec<ForeignModule> { |
1000 | self.root.foreign_modules.decode((self, sess)).collect() | |
1001 | } | |
1002 | ||
ea8adc8c | 1003 | pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> { |
c30ab7b3 SL |
1004 | self.root |
1005 | .dylib_dependency_formats | |
1006 | .decode(self) | |
1007 | .enumerate() | |
1008 | .flat_map(|(i, link)| { | |
1009 | let cnum = CrateNum::new(i + 1); | |
1010 | link.map(|link| (self.cnum_map.borrow()[cnum], link)) | |
1011 | }) | |
1012 | .collect() | |
223e47cc | 1013 | } |
223e47cc | 1014 | |
ea8adc8c | 1015 | pub fn get_missing_lang_items(&self) -> Vec<lang_items::LangItem> { |
7cac9316 XL |
1016 | self.root |
1017 | .lang_items_missing | |
7cac9316 XL |
1018 | .decode(self) |
1019 | .collect() | |
d9579d0f AL |
1020 | } |
1021 | ||
9e0c209e SL |
1022 | pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec<ast::Name> { |
1023 | let arg_names = match self.entry(id).kind { | |
1024 | EntryKind::Fn(data) | | |
1025 | EntryKind::ForeignFn(data) => data.decode(self).arg_names, | |
1026 | EntryKind::Method(data) => data.decode(self).fn_data.arg_names, | |
c30ab7b3 | 1027 | _ => LazySeq::empty(), |
9e0c209e SL |
1028 | }; |
1029 | arg_names.decode(self).collect() | |
1030 | } | |
9cc50fc6 | 1031 | |
83c7162d XL |
1032 | pub fn exported_symbols(&self, |
1033 | tcx: TyCtxt<'a, 'tcx, 'tcx>) | |
1034 | -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> { | |
1035 | let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> = | |
1036 | LazySeq::with_position_and_length(self.root.exported_symbols.position, | |
1037 | self.root.exported_symbols.len); | |
1038 | lazy_seq.decode((self, tcx)).collect() | |
1039 | } | |
1040 | ||
1041 | pub fn get_rendered_const(&self, id: DefIndex) -> String { | |
1042 | match self.entry(id).kind { | |
1043 | EntryKind::Const(_, data) | | |
1044 | EntryKind::AssociatedConst(_, _, data) => data.decode(self).0, | |
1045 | _ => bug!(), | |
1046 | } | |
476ff2be SL |
1047 | } |
1048 | ||
0531ce1d XL |
1049 | pub fn wasm_custom_sections(&self) -> Vec<DefId> { |
1050 | let sections = self.root | |
1051 | .wasm_custom_sections | |
1052 | .decode(self) | |
1053 | .map(|def_index| self.local_def_id(def_index)) | |
1054 | .collect::<Vec<_>>(); | |
1055 | info!("loaded wasm sections {:?}", sections); | |
1056 | return sections | |
1057 | } | |
1058 | ||
ea8adc8c | 1059 | pub fn get_macro(&self, id: DefIndex) -> (InternedString, MacroDef) { |
476ff2be SL |
1060 | let entry = self.entry(id); |
1061 | match entry.kind { | |
32a655c1 | 1062 | EntryKind::MacroDef(macro_def) => (self.item_name(id), macro_def.decode(self)), |
476ff2be SL |
1063 | _ => bug!(), |
1064 | } | |
9e0c209e | 1065 | } |
9cc50fc6 | 1066 | |
9e0c209e | 1067 | pub fn is_const_fn(&self, id: DefIndex) -> bool { |
32a655c1 SL |
1068 | let constness = match self.entry(id).kind { |
1069 | EntryKind::Method(data) => data.decode(self).fn_data.constness, | |
1070 | EntryKind::Fn(data) => data.decode(self).constness, | |
1071 | _ => hir::Constness::NotConst, | |
1072 | }; | |
1073 | constness == hir::Constness::Const | |
9e0c209e | 1074 | } |
9cc50fc6 | 1075 | |
9e0c209e SL |
1076 | pub fn is_foreign_item(&self, id: DefIndex) -> bool { |
1077 | match self.entry(id).kind { | |
1078 | EntryKind::ForeignImmStatic | | |
1079 | EntryKind::ForeignMutStatic | | |
1080 | EntryKind::ForeignFn(_) => true, | |
c30ab7b3 | 1081 | _ => false, |
62682a34 | 1082 | } |
d9579d0f | 1083 | } |
1a4d82fc | 1084 | |
041b39d2 XL |
1085 | pub fn fn_sig(&self, |
1086 | id: DefIndex, | |
1087 | tcx: TyCtxt<'a, 'tcx, 'tcx>) | |
1088 | -> ty::PolyFnSig<'tcx> { | |
1089 | let sig = match self.entry(id).kind { | |
1090 | EntryKind::Fn(data) | | |
1091 | EntryKind::ForeignFn(data) => data.decode(self).sig, | |
1092 | EntryKind::Method(data) => data.decode(self).fn_data.sig, | |
1093 | EntryKind::Variant(data) | | |
1094 | EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(), | |
1095 | EntryKind::Closure(data) => data.decode(self).sig, | |
c30ab7b3 | 1096 | _ => bug!(), |
041b39d2 XL |
1097 | }; |
1098 | sig.decode((self, tcx)) | |
1a4d82fc | 1099 | } |
1a4d82fc | 1100 | |
cc61c64b | 1101 | #[inline] |
32a655c1 | 1102 | pub fn def_key(&self, index: DefIndex) -> DefKey { |
2c00a5a8 XL |
1103 | if !self.is_proc_macro(index) { |
1104 | self.def_path_table.def_key(index) | |
1105 | } else { | |
1106 | // FIXME(#49271) - It would be better if the DefIds were consistent | |
1107 | // with the DefPathTable, but for proc-macro crates | |
1108 | // they aren't. | |
1109 | let name = self.proc_macros | |
1110 | .as_ref() | |
1111 | .unwrap()[index.to_proc_macro_index()].0; | |
1112 | DefKey { | |
1113 | parent: Some(CRATE_DEF_INDEX), | |
1114 | disambiguated_data: DisambiguatedDefPathData { | |
83c7162d | 1115 | data: DefPathData::MacroDef(name.as_interned_str()), |
2c00a5a8 XL |
1116 | disambiguator: 0, |
1117 | } | |
1118 | } | |
1119 | } | |
62682a34 | 1120 | } |
62682a34 | 1121 | |
32a655c1 SL |
1122 | // Returns the path leading to the thing with this `id`. |
1123 | pub fn def_path(&self, id: DefIndex) -> DefPath { | |
9e0c209e | 1124 | debug!("def_path(id={:?})", id); |
32a655c1 | 1125 | DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent)) |
92a42be0 | 1126 | } |
92a42be0 | 1127 | |
cc61c64b | 1128 | #[inline] |
7cac9316 | 1129 | pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { |
cc61c64b XL |
1130 | self.def_path_table.def_path_hash(index) |
1131 | } | |
1132 | ||
9e0c209e SL |
1133 | /// Imports the codemap from an external crate into the codemap of the crate |
1134 | /// currently being compiled (the "local crate"). | |
1135 | /// | |
1136 | /// The import algorithm works analogous to how AST items are inlined from an | |
1137 | /// external crate's metadata: | |
1138 | /// For every FileMap in the external codemap an 'inline' copy is created in the | |
1139 | /// local codemap. The correspondence relation between external and local | |
1140 | /// FileMaps is recorded in the `ImportedFileMap` objects returned from this | |
1141 | /// function. When an item from an external crate is later inlined into this | |
1142 | /// crate, this correspondence information is used to translate the span | |
1143 | /// information of the inlined item so that it refers the correct positions in | |
1144 | /// the local codemap (see `<decoder::DecodeContext as SpecializedDecoder<Span>>`). | |
1145 | /// | |
1146 | /// The import algorithm in the function below will reuse FileMaps already | |
1147 | /// existing in the local codemap. For example, even if the FileMap of some | |
1148 | /// source file of libstd gets imported many times, there will only ever be | |
1149 | /// one FileMap object for the corresponding file in the local codemap. | |
1150 | /// | |
1151 | /// Note that imported FileMaps do not actually contain the source code of the | |
1152 | /// file they represent, just information about length, line breaks, and | |
1153 | /// multibyte characters. This information is enough to generate valid debuginfo | |
1154 | /// for items inlined from other crates. | |
c30ab7b3 SL |
1155 | pub fn imported_filemaps(&'a self, |
1156 | local_codemap: &codemap::CodeMap) | |
0531ce1d | 1157 | -> ReadGuard<'a, Vec<cstore::ImportedFileMap>> { |
9e0c209e SL |
1158 | { |
1159 | let filemaps = self.codemap_import_info.borrow(); | |
1160 | if !filemaps.is_empty() { | |
1161 | return filemaps; | |
1162 | } | |
1163 | } | |
62682a34 | 1164 | |
0531ce1d XL |
1165 | // Lock the codemap_import_info to ensure this only happens once |
1166 | let mut codemap_import_info = self.codemap_import_info.borrow_mut(); | |
1167 | ||
1168 | if !codemap_import_info.is_empty() { | |
1169 | drop(codemap_import_info); | |
1170 | return self.codemap_import_info.borrow(); | |
1171 | } | |
1172 | ||
9e0c209e SL |
1173 | let external_codemap = self.root.codemap.decode(self); |
1174 | ||
1175 | let imported_filemaps = external_codemap.map(|filemap_to_import| { | |
7cac9316 XL |
1176 | // We can't reuse an existing FileMap, so allocate a new one |
1177 | // containing the information we need. | |
1178 | let syntax_pos::FileMap { name, | |
1179 | name_was_remapped, | |
041b39d2 | 1180 | src_hash, |
7cac9316 XL |
1181 | start_pos, |
1182 | end_pos, | |
1183 | lines, | |
1184 | multibyte_chars, | |
abe05a73 | 1185 | non_narrow_chars, |
ff7c6d11 | 1186 | name_hash, |
7cac9316 XL |
1187 | .. } = filemap_to_import; |
1188 | ||
1189 | let source_length = (end_pos - start_pos).to_usize(); | |
1190 | ||
1191 | // Translate line-start positions and multibyte character | |
1192 | // position into frame of reference local to file. | |
1193 | // `CodeMap::new_imported_filemap()` will then translate those | |
1194 | // coordinates to their new global frame of reference when the | |
1195 | // offset of the FileMap is known. | |
1196 | let mut lines = lines.into_inner(); | |
1197 | for pos in &mut lines { | |
1198 | *pos = *pos - start_pos; | |
1199 | } | |
1200 | let mut multibyte_chars = multibyte_chars.into_inner(); | |
1201 | for mbc in &mut multibyte_chars { | |
1202 | mbc.pos = mbc.pos - start_pos; | |
1203 | } | |
abe05a73 XL |
1204 | let mut non_narrow_chars = non_narrow_chars.into_inner(); |
1205 | for swc in &mut non_narrow_chars { | |
1206 | *swc = *swc - start_pos; | |
1207 | } | |
b039eaaf | 1208 | |
7cac9316 XL |
1209 | let local_version = local_codemap.new_imported_filemap(name, |
1210 | name_was_remapped, | |
1211 | self.cnum.as_u32(), | |
041b39d2 | 1212 | src_hash, |
ff7c6d11 | 1213 | name_hash, |
7cac9316 XL |
1214 | source_length, |
1215 | lines, | |
abe05a73 XL |
1216 | multibyte_chars, |
1217 | non_narrow_chars); | |
7cac9316 XL |
1218 | debug!("CrateMetaData::imported_filemaps alloc \ |
1219 | filemap {:?} original (start_pos {:?} end_pos {:?}) \ | |
1220 | translated (start_pos {:?} end_pos {:?})", | |
1221 | local_version.name, start_pos, end_pos, | |
1222 | local_version.start_pos, local_version.end_pos); | |
1223 | ||
1224 | cstore::ImportedFileMap { | |
1225 | original_start_pos: start_pos, | |
1226 | original_end_pos: end_pos, | |
1227 | translated_filemap: local_version, | |
1228 | } | |
1229 | }).collect(); | |
85aaf69f | 1230 | |
0531ce1d XL |
1231 | *codemap_import_info = imported_filemaps; |
1232 | drop(codemap_import_info); | |
1233 | ||
9e0c209e | 1234 | // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. |
9e0c209e | 1235 | self.codemap_import_info.borrow() |
b039eaaf | 1236 | } |
a7813a04 | 1237 | } |