1 // Copyright 2012-2014 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.
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.
11 // Decoding metadata from a single crate's metadata
13 use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule};
16 use rustc_data_structures::sync::{Lrc, ReadGuard};
17 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash,
18 DisambiguatedDefPathData};
20 use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
21 ExternBodyNestedBodies};
22 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
23 use rustc::hir::def::{self, Def, CtorKind};
24 use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
25 CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId};
26 use rustc::ich::Fingerprint;
27 use rustc::middle::lang_items;
28 use rustc::mir::{self, interpret};
29 use rustc::session::Session;
30 use rustc::ty::{self, Ty, TyCtxt};
31 use rustc::ty::codec::TyDecoder;
33 use rustc::util::captures::Captures;
34 use rustc::util::nodemap::FxHashMap;
36 use std::collections::BTreeMap;
41 use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
43 use syntax::ast::{self, Ident};
45 use syntax::symbol::{InternedString, Symbol};
46 use syntax::ext::base::MacroKind;
47 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
49 pub struct DecodeContext<'a, 'tcx: 'a> {
50 opaque: opaque::Decoder<'a>,
51 cdata: Option<&'a CrateMetadata>,
52 sess: Option<&'a Session>,
53 tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
55 // Cache the last used filemap for translating spans as an optimization.
56 last_filemap_index: usize,
58 lazy_state: LazyState,
60 // interpreter allocation cache
61 interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>,
63 // Read from the LazySeq CrateRoot::inpterpret_alloc_index on demand
64 interpret_alloc_index: Option<Vec<u32>>,
67 /// Abstract over the various ways one can create metadata decoders.
68 pub trait Metadata<'a, 'tcx>: Copy {
69 fn raw_bytes(self) -> &'a [u8];
70 fn cdata(self) -> Option<&'a CrateMetadata> { None }
71 fn sess(self) -> Option<&'a Session> { None }
72 fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { None }
74 fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
77 opaque: opaque::Decoder::new(self.raw_bytes(), pos),
79 sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
81 last_filemap_index: 0,
82 lazy_state: LazyState::NoNode,
83 interpret_alloc_cache: FxHashMap::default(),
84 interpret_alloc_index: None,
89 impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
90 fn raw_bytes(self) -> &'a [u8] {
96 impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'a Session) {
97 fn raw_bytes(self) -> &'a [u8] {
102 fn sess(self) -> Option<&'a Session> {
103 let (_, sess) = self;
109 impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
110 fn raw_bytes(self) -> &'a [u8] {
111 self.blob.raw_bytes()
113 fn cdata(self) -> Option<&'a CrateMetadata> {
118 impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, &'a Session) {
119 fn raw_bytes(self) -> &'a [u8] {
122 fn cdata(self) -> Option<&'a CrateMetadata> {
125 fn sess(self) -> Option<&'a Session> {
130 impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>) {
131 fn raw_bytes(self) -> &'a [u8] {
134 fn cdata(self) -> Option<&'a CrateMetadata> {
137 fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> {
142 impl<'a, 'tcx: 'a, T: Decodable> Lazy<T> {
143 pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
144 let mut dcx = meta.decoder(self.position);
145 dcx.lazy_state = LazyState::NodeStart(self.position);
146 T::decode(&mut dcx).unwrap()
150 impl<'a, 'tcx: 'a, T: Decodable> LazySeq<T> {
151 pub fn decode<M: Metadata<'a, 'tcx>>(
154 ) -> impl Iterator<Item = T> + Captures<'tcx> + 'a {
155 let mut dcx = meta.decoder(self.position);
156 dcx.lazy_state = LazyState::NodeStart(self.position);
157 (0..self.len).map(move |_| T::decode(&mut dcx).unwrap())
161 impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
162 pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
163 self.tcx.expect("missing TyCtxt in DecodeContext")
166 pub fn cdata(&self) -> &'a CrateMetadata {
167 self.cdata.expect("missing CrateMetadata in DecodeContext")
170 fn read_lazy_distance(&mut self, min_size: usize) -> Result<usize, <Self as Decoder>::Error> {
171 let distance = self.read_usize()?;
172 let position = match self.lazy_state {
173 LazyState::NoNode => bug!("read_lazy_distance: outside of a metadata node"),
174 LazyState::NodeStart(start) => {
175 assert!(distance + min_size <= start);
176 start - distance - min_size
178 LazyState::Previous(last_min_end) => last_min_end + distance,
180 self.lazy_state = LazyState::Previous(position + min_size);
184 fn interpret_alloc(&mut self, idx: usize) -> usize {
185 if let Some(index) = self.interpret_alloc_index.as_mut() {
186 return index[idx] as usize;
188 let cdata = self.cdata();
189 let index: Vec<u32> = cdata.root.interpret_alloc_index.decode(cdata).collect();
190 let pos = index[idx];
191 self.interpret_alloc_index = Some(index);
196 impl<'a, 'tcx: 'a> TyDecoder<'a, 'tcx> for DecodeContext<'a, 'tcx> {
199 fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
200 self.tcx.expect("missing TyCtxt in DecodeContext")
204 fn peek_byte(&self) -> u8 {
205 self.opaque.data[self.opaque.position()]
209 fn position(&self) -> usize {
210 self.opaque.position()
213 fn cached_ty_for_shorthand<F>(&mut self,
216 -> Result<Ty<'tcx>, Self::Error>
217 where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>
219 let tcx = self.tcx();
221 let key = ty::CReaderCacheKey {
222 cnum: self.cdata().cnum,
226 if let Some(&ty) = tcx.rcache.borrow().get(&key) {
230 let ty = or_insert_with(self)?;
231 tcx.rcache.borrow_mut().insert(key, ty);
235 fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
236 where F: FnOnce(&mut Self) -> R
238 let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
239 let old_opaque = mem::replace(&mut self.opaque, new_opaque);
240 let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
242 self.opaque = old_opaque;
243 self.lazy_state = old_state;
247 fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
248 if cnum == LOCAL_CRATE {
251 self.cdata().cnum_map.borrow()[cnum]
256 impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
257 fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
258 Ok(Lazy::with_position(self.read_lazy_distance(Lazy::<T>::min_size())?))
262 impl<'a, 'tcx, T> SpecializedDecoder<LazySeq<T>> for DecodeContext<'a, 'tcx> {
263 fn specialized_decode(&mut self) -> Result<LazySeq<T>, Self::Error> {
264 let len = self.read_usize()?;
265 let position = if len == 0 {
268 self.read_lazy_distance(LazySeq::<T>::min_size(len))?
270 Ok(LazySeq::with_position_and_length(position, len))
275 impl<'a, 'tcx> SpecializedDecoder<DefId> for DecodeContext<'a, 'tcx> {
277 fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
278 let krate = CrateNum::decode(self)?;
279 let index = DefIndex::decode(self)?;
288 impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
290 fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
291 Ok(DefIndex::from_raw_u32(self.read_u32()?))
295 impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for DecodeContext<'a, 'tcx> {
297 fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
298 self.specialized_decode().map(|i| LocalDefId::from_def_id(i))
302 impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
303 fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
304 let tcx = self.tcx.unwrap();
305 let idx = usize::decode(self)?;
307 if let Some(cached) = self.interpret_alloc_cache.get(&idx).cloned() {
310 let pos = self.interpret_alloc(idx);
311 self.with_position(pos, |this| {
312 interpret::specialized_decode_alloc_id(
316 assert!(this.interpret_alloc_cache.insert(idx, alloc_id).is_none());
323 impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
324 fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
325 let tag = u8::decode(self)?;
327 if tag == TAG_INVALID_SPAN {
331 debug_assert_eq!(tag, TAG_VALID_SPAN);
333 let lo = BytePos::decode(self)?;
334 let len = BytePos::decode(self)?;
337 let sess = if let Some(sess) = self.sess {
340 bug!("Cannot decode Span without Session.")
343 let imported_filemaps = self.cdata().imported_filemaps(&sess.codemap());
345 // Optimize for the case that most spans within a translated item
346 // originate from the same filemap.
347 let last_filemap = &imported_filemaps[self.last_filemap_index];
349 if lo >= last_filemap.original_start_pos &&
350 lo <= last_filemap.original_end_pos {
354 let mut b = imported_filemaps.len();
358 if imported_filemaps[m].original_start_pos > lo {
365 self.last_filemap_index = a;
366 &imported_filemaps[a]
370 // Make sure our binary search above is correct.
371 debug_assert!(lo >= filemap.original_start_pos &&
372 lo <= filemap.original_end_pos);
374 // Make sure we correctly filtered out invalid spans during encoding
375 debug_assert!(hi >= filemap.original_start_pos &&
376 hi <= filemap.original_end_pos);
378 let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
379 let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
381 Ok(Span::new(lo, hi, NO_EXPANSION))
385 impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
386 fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
387 Fingerprint::decode_opaque(&mut self.opaque)
391 impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
392 for DecodeContext<'a, 'tcx> {
394 fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
395 Ok(mir::ClearCrossCrate::Clear)
399 implement_ty_decoder!( DecodeContext<'a, 'tcx> );
401 impl<'a, 'tcx> MetadataBlob {
402 pub fn is_compatible(&self) -> bool {
403 self.raw_bytes().starts_with(METADATA_HEADER)
406 pub fn get_rustc_version(&self) -> String {
407 Lazy::with_position(METADATA_HEADER.len() + 4).decode(self)
410 pub fn get_root(&self) -> CrateRoot {
411 let slice = self.raw_bytes();
412 let offset = METADATA_HEADER.len();
413 let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) |
414 ((slice[offset + 2] as u32) << 8) |
415 ((slice[offset + 3] as u32) << 0)) as usize;
416 Lazy::with_position(pos).decode(self)
419 pub fn list_crate_metadata(&self,
420 out: &mut io::Write) -> io::Result<()> {
421 write!(out, "=External Dependencies=\n")?;
422 let root = self.get_root();
423 for (i, dep) in root.crate_deps
426 write!(out, "{} {}-{}\n", i + 1, dep.name, dep.hash)?;
433 impl<'tcx> EntryKind<'tcx> {
434 fn to_def(&self, did: DefId) -> Option<Def> {
436 EntryKind::Const(_) => Def::Const(did),
437 EntryKind::AssociatedConst(..) => Def::AssociatedConst(did),
438 EntryKind::ImmStatic |
439 EntryKind::ForeignImmStatic => Def::Static(did, false),
440 EntryKind::MutStatic |
441 EntryKind::ForeignMutStatic => Def::Static(did, true),
442 EntryKind::Struct(_, _) => Def::Struct(did),
443 EntryKind::Union(_, _) => Def::Union(did),
445 EntryKind::ForeignFn(_) => Def::Fn(did),
446 EntryKind::Method(_) => Def::Method(did),
447 EntryKind::Type => Def::TyAlias(did),
448 EntryKind::AssociatedType(_) => Def::AssociatedTy(did),
449 EntryKind::Mod(_) => Def::Mod(did),
450 EntryKind::Variant(_) => Def::Variant(did),
451 EntryKind::Trait(_) => Def::Trait(did),
452 EntryKind::Enum(..) => Def::Enum(did),
453 EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
454 EntryKind::GlobalAsm => Def::GlobalAsm(did),
455 EntryKind::ForeignType => Def::TyForeign(did),
457 EntryKind::ForeignMod |
460 EntryKind::Generator(_) |
461 EntryKind::Closure(_) => return None,
466 impl<'a, 'tcx> CrateMetadata {
467 fn is_proc_macro(&self, id: DefIndex) -> bool {
468 self.proc_macros.is_some() && id != CRATE_DEF_INDEX
471 fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
472 assert!(!self.is_proc_macro(item_id));
473 self.root.index.lookup(self.blob.raw_bytes(), item_id)
476 fn entry(&self, item_id: DefIndex) -> Entry<'tcx> {
477 match self.maybe_entry(item_id) {
479 bug!("entry: id not found: {:?} in crate {:?} with number {}",
484 Some(d) => d.decode(self),
488 fn local_def_id(&self, index: DefIndex) -> DefId {
495 pub fn item_name(&self, item_index: DefIndex) -> InternedString {
496 self.def_key(item_index)
500 .expect("no name in item_name")
503 pub fn get_def(&self, index: DefIndex) -> Option<Def> {
504 if !self.is_proc_macro(index) {
505 self.entry(index).kind.to_def(self.local_def_id(index))
507 let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind();
508 Some(Def::Macro(self.local_def_id(index), kind))
512 pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
513 match self.is_proc_macro(index) {
515 false => self.entry(index).span.decode((self, sess)),
519 pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
520 let data = match self.entry(item_id).kind {
521 EntryKind::Trait(data) => data.decode((self, sess)),
525 ty::TraitDef::new(self.local_def_id(item_id),
529 self.def_path_table.def_path_hash(item_id))
532 fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef {
533 let data = match item.kind {
534 EntryKind::Variant(data) |
535 EntryKind::Struct(data, _) |
536 EntryKind::Union(data, _) => data.decode(self),
541 did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
542 name: Symbol::intern(&self.item_name(index)),
543 fields: item.children.decode(self).map(|index| {
544 let f = self.entry(index);
546 did: self.local_def_id(index),
547 name: Symbol::intern(&self.item_name(index)),
548 vis: f.visibility.decode(self)
552 ctor_kind: data.ctor_kind,
556 pub fn get_adt_def(&self,
558 tcx: TyCtxt<'a, 'tcx, 'tcx>)
559 -> &'tcx ty::AdtDef {
560 let item = self.entry(item_id);
561 let did = self.local_def_id(item_id);
562 let kind = match item.kind {
563 EntryKind::Enum(_) => ty::AdtKind::Enum,
564 EntryKind::Struct(_, _) => ty::AdtKind::Struct,
565 EntryKind::Union(_, _) => ty::AdtKind::Union,
566 _ => bug!("get_adt_def called on a non-ADT {:?}", did),
568 let variants = if let ty::AdtKind::Enum = kind {
572 self.get_variant(&self.entry(index), index)
576 vec![self.get_variant(&item, item_id)]
578 let (kind, repr) = match item.kind {
579 EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr),
580 EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr),
581 EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr),
582 _ => bug!("get_adt_def called on a non-ADT {:?}", did),
585 tcx.alloc_adt_def(did, kind, variants, repr)
588 pub fn get_predicates(&self,
590 tcx: TyCtxt<'a, 'tcx, 'tcx>)
591 -> ty::GenericPredicates<'tcx> {
592 self.entry(item_id).predicates.unwrap().decode((self, tcx))
595 pub fn get_super_predicates(&self,
597 tcx: TyCtxt<'a, 'tcx, 'tcx>)
598 -> ty::GenericPredicates<'tcx> {
599 match self.entry(item_id).kind {
600 EntryKind::Trait(data) => data.decode(self).super_predicates.decode((self, tcx)),
605 pub fn get_generics(&self,
609 self.entry(item_id).generics.unwrap().decode((self, sess))
612 pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
613 self.entry(id).ty.unwrap().decode((self, tcx))
616 pub fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
617 match self.is_proc_macro(id) {
619 false => self.entry(id).stability.map(|stab| stab.decode(self)),
623 pub fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
624 match self.is_proc_macro(id) {
626 false => self.entry(id).deprecation.map(|depr| depr.decode(self)),
630 pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
631 match self.is_proc_macro(id) {
632 true => ty::Visibility::Public,
633 false => self.entry(id).visibility.decode(self),
637 fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> {
638 match self.entry(id).kind {
639 EntryKind::Impl(data) => data.decode(self),
644 pub fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> {
645 self.get_impl_data(id).parent_impl
648 pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity {
649 self.get_impl_data(id).polarity
652 pub fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness {
653 self.get_impl_data(id).defaultness
656 pub fn get_coerce_unsized_info(&self,
658 -> Option<ty::adjustment::CoerceUnsizedInfo> {
659 self.get_impl_data(id).coerce_unsized_info
662 pub fn get_impl_trait(&self,
664 tcx: TyCtxt<'a, 'tcx, 'tcx>)
665 -> Option<ty::TraitRef<'tcx>> {
666 self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx)))
669 /// Iterates over the language items in the given crate.
670 pub fn get_lang_items(&self) -> Vec<(DefId, usize)> {
674 .map(|(def_index, index)| (self.local_def_id(def_index), index))
678 /// Iterates over each child of the given item.
679 pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
680 where F: FnMut(def::Export)
682 if let Some(ref proc_macros) = self.proc_macros {
683 if id == CRATE_DEF_INDEX {
684 for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
685 let def = Def::Macro(
688 index: DefIndex::from_proc_macro_index(id),
692 let ident = Ident::with_empty_ctxt(name);
693 callback(def::Export {
696 vis: ty::Visibility::Public,
706 let item = match self.maybe_entry(id) {
708 Some(item) => item.decode((self, sess)),
711 // Iterate over all children.
712 let macros_only = self.dep_kind.lock().macros_only();
713 for child_index in item.children.decode((self, sess)) {
719 if let Some(child) = self.maybe_entry(child_index) {
720 let child = child.decode((self, sess));
722 EntryKind::MacroDef(..) => {}
723 _ if macros_only => continue,
727 // Hand off the item to the callback.
729 // FIXME(eddyb) Don't encode these in children.
730 EntryKind::ForeignMod => {
731 for child_index in child.children.decode((self, sess)) {
732 if let Some(def) = self.get_def(child_index) {
733 callback(def::Export {
735 ident: Ident::from_str(&self.item_name(child_index)),
736 vis: self.get_visibility(child_index),
737 span: self.entry(child_index).span.decode((self, sess)),
744 EntryKind::Impl(_) => continue,
749 let def_key = self.def_key(child_index);
750 let span = child.span.decode((self, sess));
751 if let (Some(def), Some(name)) =
752 (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
753 let ident = Ident::from_str(&name);
754 let vis = self.get_visibility(child_index);
755 let is_import = false;
756 callback(def::Export { def, ident, vis, span, is_import });
757 // For non-re-export structs and variants add their constructors to children.
758 // Re-export lists automatically contain constructors when necessary.
761 if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
762 let ctor_kind = self.get_ctor_kind(child_index);
763 let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
764 callback(def::Export {
766 vis: self.get_visibility(ctor_def_id.index),
767 ident, span, is_import,
771 Def::Variant(def_id) => {
772 // Braced variants, unlike structs, generate unusable names in
773 // value namespace, they are reserved for possible future use.
774 let ctor_kind = self.get_ctor_kind(child_index);
775 let ctor_def = Def::VariantCtor(def_id, ctor_kind);
776 let vis = self.get_visibility(child_index);
777 callback(def::Export { def: ctor_def, ident, vis, span, is_import });
785 if let EntryKind::Mod(data) = item.kind {
786 for exp in data.decode((self, sess)).reexports.decode((self, sess)) {
789 _ if macros_only => continue,
797 pub fn extern_const_body(&self,
798 tcx: TyCtxt<'a, 'tcx, 'tcx>,
800 -> ExternConstBody<'tcx> {
801 assert!(!self.is_proc_macro(id));
802 let ast = self.entry(id).ast.unwrap();
803 let def_id = self.local_def_id(id);
804 let ast = ast.decode((self, tcx));
805 let body = ast.body.decode((self, tcx));
807 body: tcx.hir.intern_inlined_body(def_id, body),
808 fingerprint: ast.stable_bodies_hash,
812 pub fn item_body_tables(&self,
814 tcx: TyCtxt<'a, 'tcx, 'tcx>)
815 -> &'tcx ty::TypeckTables<'tcx> {
816 let ast = self.entry(id).ast.unwrap().decode(self);
817 tcx.alloc_tables(ast.tables.decode((self, tcx)))
820 pub fn item_body_nested_bodies(&self,
821 tcx: TyCtxt<'a, 'tcx, 'tcx>,
823 -> ExternBodyNestedBodies {
824 if let Some(ref ast) = self.entry(id).ast {
825 let mut ast = ast.decode(self);
826 let nested_bodies: BTreeMap<_, _> = ast.nested_bodies
827 .decode((self, tcx.sess))
828 .map(|body| (body.id(), body))
830 ExternBodyNestedBodies {
831 nested_bodies: Lrc::new(nested_bodies),
832 fingerprint: ast.stable_bodies_hash,
835 ExternBodyNestedBodies {
836 nested_bodies: Lrc::new(BTreeMap::new()),
837 fingerprint: Fingerprint::ZERO,
842 pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool {
843 self.entry(id).ast.expect("const item missing `ast`")
844 .decode(self).rvalue_promotable_to_static
847 pub fn is_item_mir_available(&self, id: DefIndex) -> bool {
848 !self.is_proc_macro(id) &&
849 self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some()
852 pub fn maybe_get_optimized_mir(&self,
853 tcx: TyCtxt<'a, 'tcx, 'tcx>,
855 -> Option<Mir<'tcx>> {
856 match self.is_proc_macro(id) {
858 false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))),
862 pub fn mir_const_qualif(&self, id: DefIndex) -> u8 {
863 match self.entry(id).kind {
864 EntryKind::Const(qualif) |
865 EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif) |
866 EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif) => {
873 pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem {
874 let item = self.entry(id);
875 let def_key = self.def_key(id);
876 let parent = self.local_def_id(def_key.parent.unwrap());
877 let name = def_key.disambiguated_data.data.get_opt_name().unwrap();
879 let (kind, container, has_self) = match item.kind {
880 EntryKind::AssociatedConst(container, _) => {
881 (ty::AssociatedKind::Const, container, false)
883 EntryKind::Method(data) => {
884 let data = data.decode(self);
885 (ty::AssociatedKind::Method, data.container, data.has_self)
887 EntryKind::AssociatedType(container) => {
888 (ty::AssociatedKind::Type, container, false)
890 _ => bug!("cannot get associated-item of `{:?}`", def_key)
894 name: Symbol::intern(&name),
896 vis: item.visibility.decode(self),
897 defaultness: container.defaultness(),
898 def_id: self.local_def_id(id),
899 container: container.with_def_id(parent),
900 method_has_self_argument: has_self
904 pub fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> {
905 self.entry(id).variances.decode(self).collect()
908 pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
909 match self.entry(node_id).kind {
910 EntryKind::Struct(data, _) |
911 EntryKind::Union(data, _) |
912 EntryKind::Variant(data) => data.decode(self).ctor_kind,
913 _ => CtorKind::Fictive,
917 pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
918 match self.entry(node_id).kind {
919 EntryKind::Struct(data, _) => {
920 data.decode(self).struct_ctor.map(|index| self.local_def_id(index))
926 pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> {
927 let (node_as, node_index) =
928 (node_id.address_space().index(), node_id.as_array_index());
929 if self.is_proc_macro(node_id) {
933 if let Some(&Some(ref val)) =
934 self.attribute_cache.borrow()[node_as].get(node_index) {
938 // The attributes for a tuple struct are attached to the definition, not the ctor;
939 // we assume that someone passing in a tuple struct ctor is actually wanting to
940 // look at the definition
941 let mut item = self.entry(node_id);
942 let def_key = self.def_key(node_id);
943 if def_key.disambiguated_data.data == DefPathData::StructCtor {
944 item = self.entry(def_key.parent.unwrap());
946 let result: Lrc<[ast::Attribute]> = Lrc::from(self.get_attributes(&item, sess));
947 let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
948 if vec_.len() < node_index + 1 {
949 vec_.resize(node_index + 1, None);
951 // This can overwrite the result produced by another thread, but the value
952 // written should be the same
953 vec_[node_index] = Some(result.clone());
957 pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
961 .map(|index| Symbol::intern(&self.item_name(index)))
965 fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec<ast::Attribute> {
967 .decode((self, sess))
969 // Need new unique IDs: old thread-local IDs won't map to new threads.
970 attr.id = attr::mk_attr_id();
976 // Translate a DefId from the current compilation environment to a DefId
977 // for an external crate.
978 fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
979 for (local, &global) in self.cnum_map.borrow().iter_enumerated() {
980 if global == did.krate {
991 pub fn get_inherent_implementations_for_type(&self, id: DefIndex) -> Vec<DefId> {
995 .map(|index| self.local_def_id(index))
999 pub fn get_implementations_for_trait(&self,
1000 filter: Option<DefId>,
1001 result: &mut Vec<DefId>) {
1002 // Do a reverse lookup beforehand to avoid touching the crate_num
1003 // hash map in the loop below.
1004 let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
1005 Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
1006 Some(None) => return,
1007 None if self.proc_macros.is_some() => return,
1011 if let Some(filter) = filter {
1012 if let Some(impls) = self.trait_impls
1014 result.extend(impls.decode(self).map(|idx| self.local_def_id(idx)));
1017 for impls in self.trait_impls.values() {
1018 result.extend(impls.decode(self).map(|idx| self.local_def_id(idx)));
1023 pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
1024 self.def_key(id).parent.and_then(|parent_index| {
1025 match self.entry(parent_index).kind {
1026 EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
1033 pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
1034 self.root.native_libraries.decode((self, sess)).collect()
1037 pub fn get_foreign_modules(&self, sess: &Session) -> Vec<ForeignModule> {
1038 self.root.foreign_modules.decode((self, sess)).collect()
1041 pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> {
1043 .dylib_dependency_formats
1046 .flat_map(|(i, link)| {
1047 let cnum = CrateNum::new(i + 1);
1048 link.map(|link| (self.cnum_map.borrow()[cnum], link))
1053 pub fn get_missing_lang_items(&self) -> Vec<lang_items::LangItem> {
1060 pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec<ast::Name> {
1061 let arg_names = match self.entry(id).kind {
1062 EntryKind::Fn(data) |
1063 EntryKind::ForeignFn(data) => data.decode(self).arg_names,
1064 EntryKind::Method(data) => data.decode(self).fn_data.arg_names,
1065 _ => LazySeq::empty(),
1067 arg_names.decode(self).collect()
1070 pub fn exported_symbols(&self,
1071 tcx: TyCtxt<'a, 'tcx, 'tcx>)
1072 -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
1073 let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> =
1074 LazySeq::with_position_and_length(self.root.exported_symbols.position,
1075 self.root.exported_symbols.len);
1076 lazy_seq.decode((self, tcx)).collect()
1079 pub fn wasm_custom_sections(&self) -> Vec<DefId> {
1080 let sections = self.root
1081 .wasm_custom_sections
1083 .map(|def_index| self.local_def_id(def_index))
1084 .collect::<Vec<_>>();
1085 info!("loaded wasm sections {:?}", sections);
1089 pub fn get_macro(&self, id: DefIndex) -> (InternedString, MacroDef) {
1090 let entry = self.entry(id);
1092 EntryKind::MacroDef(macro_def) => (self.item_name(id), macro_def.decode(self)),
1097 pub fn is_const_fn(&self, id: DefIndex) -> bool {
1098 let constness = match self.entry(id).kind {
1099 EntryKind::Method(data) => data.decode(self).fn_data.constness,
1100 EntryKind::Fn(data) => data.decode(self).constness,
1101 _ => hir::Constness::NotConst,
1103 constness == hir::Constness::Const
1106 pub fn is_foreign_item(&self, id: DefIndex) -> bool {
1107 match self.entry(id).kind {
1108 EntryKind::ForeignImmStatic |
1109 EntryKind::ForeignMutStatic |
1110 EntryKind::ForeignFn(_) => true,
1115 pub fn fn_sig(&self,
1117 tcx: TyCtxt<'a, 'tcx, 'tcx>)
1118 -> ty::PolyFnSig<'tcx> {
1119 let sig = match self.entry(id).kind {
1120 EntryKind::Fn(data) |
1121 EntryKind::ForeignFn(data) => data.decode(self).sig,
1122 EntryKind::Method(data) => data.decode(self).fn_data.sig,
1123 EntryKind::Variant(data) |
1124 EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(),
1125 EntryKind::Closure(data) => data.decode(self).sig,
1128 sig.decode((self, tcx))
1132 pub fn def_key(&self, index: DefIndex) -> DefKey {
1133 if !self.is_proc_macro(index) {
1134 self.def_path_table.def_key(index)
1136 // FIXME(#49271) - It would be better if the DefIds were consistent
1137 // with the DefPathTable, but for proc-macro crates
1139 let name = self.proc_macros
1141 .unwrap()[index.to_proc_macro_index()].0;
1143 parent: Some(CRATE_DEF_INDEX),
1144 disambiguated_data: DisambiguatedDefPathData {
1145 data: DefPathData::MacroDef(name.as_str()),
1152 // Returns the path leading to the thing with this `id`.
1153 pub fn def_path(&self, id: DefIndex) -> DefPath {
1154 debug!("def_path(id={:?})", id);
1155 DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent))
1159 pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
1160 self.def_path_table.def_path_hash(index)
1163 /// Imports the codemap from an external crate into the codemap of the crate
1164 /// currently being compiled (the "local crate").
1166 /// The import algorithm works analogous to how AST items are inlined from an
1167 /// external crate's metadata:
1168 /// For every FileMap in the external codemap an 'inline' copy is created in the
1169 /// local codemap. The correspondence relation between external and local
1170 /// FileMaps is recorded in the `ImportedFileMap` objects returned from this
1171 /// function. When an item from an external crate is later inlined into this
1172 /// crate, this correspondence information is used to translate the span
1173 /// information of the inlined item so that it refers the correct positions in
1174 /// the local codemap (see `<decoder::DecodeContext as SpecializedDecoder<Span>>`).
1176 /// The import algorithm in the function below will reuse FileMaps already
1177 /// existing in the local codemap. For example, even if the FileMap of some
1178 /// source file of libstd gets imported many times, there will only ever be
1179 /// one FileMap object for the corresponding file in the local codemap.
1181 /// Note that imported FileMaps do not actually contain the source code of the
1182 /// file they represent, just information about length, line breaks, and
1183 /// multibyte characters. This information is enough to generate valid debuginfo
1184 /// for items inlined from other crates.
1185 pub fn imported_filemaps(&'a self,
1186 local_codemap: &codemap::CodeMap)
1187 -> ReadGuard<'a, Vec<cstore::ImportedFileMap>> {
1189 let filemaps = self.codemap_import_info.borrow();
1190 if !filemaps.is_empty() {
1195 // Lock the codemap_import_info to ensure this only happens once
1196 let mut codemap_import_info = self.codemap_import_info.borrow_mut();
1198 if !codemap_import_info.is_empty() {
1199 drop(codemap_import_info);
1200 return self.codemap_import_info.borrow();
1203 let external_codemap = self.root.codemap.decode(self);
1205 let imported_filemaps = external_codemap.map(|filemap_to_import| {
1206 // We can't reuse an existing FileMap, so allocate a new one
1207 // containing the information we need.
1208 let syntax_pos::FileMap { name,
1217 .. } = filemap_to_import;
1219 let source_length = (end_pos - start_pos).to_usize();
1221 // Translate line-start positions and multibyte character
1222 // position into frame of reference local to file.
1223 // `CodeMap::new_imported_filemap()` will then translate those
1224 // coordinates to their new global frame of reference when the
1225 // offset of the FileMap is known.
1226 let mut lines = lines.into_inner();
1227 for pos in &mut lines {
1228 *pos = *pos - start_pos;
1230 let mut multibyte_chars = multibyte_chars.into_inner();
1231 for mbc in &mut multibyte_chars {
1232 mbc.pos = mbc.pos - start_pos;
1234 let mut non_narrow_chars = non_narrow_chars.into_inner();
1235 for swc in &mut non_narrow_chars {
1236 *swc = *swc - start_pos;
1239 let local_version = local_codemap.new_imported_filemap(name,
1248 debug!("CrateMetaData::imported_filemaps alloc \
1249 filemap {:?} original (start_pos {:?} end_pos {:?}) \
1250 translated (start_pos {:?} end_pos {:?})",
1251 local_version.name, start_pos, end_pos,
1252 local_version.start_pos, local_version.end_pos);
1254 cstore::ImportedFileMap {
1255 original_start_pos: start_pos,
1256 original_end_pos: end_pos,
1257 translated_filemap: local_version,
1261 *codemap_import_info = imported_filemaps;
1262 drop(codemap_import_info);
1264 // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
1265 self.codemap_import_info.borrow()