]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_metadata/decoder.rs
Auto merge of #50271 - sinkuu:fix_ice, r=eddyb
[rust.git] / src / librustc_metadata / decoder.rs
index 3ea4ddc25226fffe80d39cbeba80b474ea18e2cd..57f92707ccfe332060a7ed943a7b9d4fa713f70b 100644 (file)
@@ -17,8 +17,7 @@
 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash,
                       DisambiguatedDefPathData};
 use rustc::hir;
-use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
-                            ExternBodyNestedBodies};
+use rustc::middle::cstore::LinkagePreference;
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
@@ -33,7 +32,6 @@
 use rustc::util::captures::Captures;
 use rustc::util::nodemap::FxHashMap;
 
-use std::collections::BTreeMap;
 use std::io;
 use std::mem;
 use std::u32;
@@ -42,7 +40,7 @@
 use syntax::attr;
 use syntax::ast::{self, Ident};
 use syntax::codemap;
-use syntax::symbol::{InternedString, Symbol};
+use syntax::symbol::InternedString;
 use syntax::ext::base::MacroKind;
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
 
@@ -59,9 +57,9 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
 
     // interpreter allocation cache
     interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>,
-    // a cache for sizes of interpreter allocations
-    // needed to skip already deserialized allocations
-    interpret_alloc_size: FxHashMap<usize, usize>,
+
+    // Read from the LazySeq CrateRoot::inpterpret_alloc_index on demand
+    interpret_alloc_index: Option<Vec<u32>>,
 }
 
 /// Abstract over the various ways one can create metadata decoders.
@@ -81,7 +79,7 @@ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
             last_filemap_index: 0,
             lazy_state: LazyState::NoNode,
             interpret_alloc_cache: FxHashMap::default(),
-            interpret_alloc_size: FxHashMap::default(),
+            interpret_alloc_index: None,
         }
     }
 }
@@ -180,6 +178,17 @@ fn read_lazy_distance(&mut self, min_size: usize) -> Result<usize, <Self as Deco
         self.lazy_state = LazyState::Previous(position + min_size);
         Ok(position)
     }
+
+    fn interpret_alloc(&mut self, idx: usize) -> usize {
+        if let Some(index) = self.interpret_alloc_index.as_mut() {
+            return index[idx] as usize;
+        }
+        let cdata = self.cdata();
+        let index: Vec<u32> = cdata.root.interpret_alloc_index.decode(cdata).collect();
+        let pos = index[idx];
+        self.interpret_alloc_index = Some(index);
+        pos as usize
+    }
 }
 
 impl<'a, 'tcx: 'a> TyDecoder<'a, 'tcx> for DecodeContext<'a, 'tcx> {
@@ -290,34 +299,22 @@ fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
 
 impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
-        let tcx = self.tcx.expect("need tcx for AllocId decoding");
-        let pos = self.position();
-        if let Some(cached) = self.interpret_alloc_cache.get(&pos).cloned() {
-            // if there's no end position we are currently deserializing a recursive
-            // allocation
-            if let Some(end) = self.interpret_alloc_size.get(&pos).cloned() {
-                trace!("{} already cached as {:?}", pos, cached);
-                // skip ahead
-                self.opaque.set_position(end);
-                return Ok(cached)
-            }
+        let tcx = self.tcx.unwrap();
+        let idx = usize::decode(self)?;
+
+        if let Some(cached) = self.interpret_alloc_cache.get(&idx).cloned() {
+            return Ok(cached);
         }
-        let id = interpret::specialized_decode_alloc_id(
-            self,
-            tcx,
-            pos,
-            |this, pos, alloc_id| { this.interpret_alloc_cache.insert(pos, alloc_id); },
-            |this, shorthand| {
-                // need to load allocation
-                this.with_position(shorthand, |this| interpret::AllocId::decode(this))
-            }
-        )?;
-        let end_pos = self.position();
-        assert!(self
-            .interpret_alloc_size
-            .insert(pos, end_pos)
-            .is_none());
-        Ok(id)
+        let pos = self.interpret_alloc(idx);
+        self.with_position(pos, |this| {
+            interpret::specialized_decode_alloc_id(
+                this,
+                tcx,
+                |this, alloc_id| {
+                    assert!(this.interpret_alloc_cache.insert(idx, alloc_id).is_none());
+                },
+            )
+        })
     }
 }
 
@@ -434,7 +431,7 @@ pub fn list_crate_metadata(&self,
 impl<'tcx> EntryKind<'tcx> {
     fn to_def(&self, did: DefId) -> Option<Def> {
         Some(match *self {
-            EntryKind::Const(_) => Def::Const(did),
+            EntryKind::Const(..) => Def::Const(did),
             EntryKind::AssociatedConst(..) => Def::AssociatedConst(did),
             EntryKind::ImmStatic |
             EntryKind::ForeignImmStatic => Def::Static(did, false),
@@ -540,12 +537,12 @@ fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef {
 
         ty::VariantDef {
             did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
-            name: Symbol::intern(&self.item_name(index)),
+            name: self.item_name(index).as_symbol(),
             fields: item.children.decode(self).map(|index| {
                 let f = self.entry(index);
                 ty::FieldDef {
                     did: self.local_def_id(index),
-                    name: Symbol::intern(&self.item_name(index)),
+                    name: self.item_name(index).as_symbol(),
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
@@ -733,7 +730,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Sessio
                             if let Some(def) = self.get_def(child_index) {
                                 callback(def::Export {
                                     def,
-                                    ident: Ident::from_str(&self.item_name(child_index)),
+                                    ident: Ident::from_interned_str(self.item_name(child_index)),
                                     vis: self.get_visibility(child_index),
                                     span: self.entry(child_index).span.decode((self, sess)),
                                     is_import: false,
@@ -751,7 +748,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Sessio
                 let span = child.span.decode((self, sess));
                 if let (Some(def), Some(name)) =
                     (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
-                    let ident = Ident::from_str(&name);
+                    let ident = Ident::from_interned_str(name);
                     let vis = self.get_visibility(child_index);
                     let is_import = false;
                     callback(def::Export { def, ident, vis, span, is_import });
@@ -795,54 +792,12 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Sessio
         }
     }
 
-    pub fn extern_const_body(&self,
-                             tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             id: DefIndex)
-                             -> ExternConstBody<'tcx> {
-        assert!(!self.is_proc_macro(id));
-        let ast = self.entry(id).ast.unwrap();
-        let def_id = self.local_def_id(id);
-        let ast = ast.decode((self, tcx));
-        let body = ast.body.decode((self, tcx));
-        ExternConstBody {
-            body: tcx.hir.intern_inlined_body(def_id, body),
-            fingerprint: ast.stable_bodies_hash,
-        }
-    }
-
-    pub fn item_body_tables(&self,
-                            id: DefIndex,
-                            tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                            -> &'tcx ty::TypeckTables<'tcx> {
-        let ast = self.entry(id).ast.unwrap().decode(self);
-        tcx.alloc_tables(ast.tables.decode((self, tcx)))
-    }
-
-    pub fn item_body_nested_bodies(&self,
-                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   id: DefIndex)
-                                   -> ExternBodyNestedBodies {
-        if let Some(ref ast) = self.entry(id).ast {
-            let mut ast = ast.decode(self);
-            let nested_bodies: BTreeMap<_, _> = ast.nested_bodies
-                                                   .decode((self, tcx.sess))
-                                                   .map(|body| (body.id(), body))
-                                                   .collect();
-            ExternBodyNestedBodies {
-                nested_bodies: Lrc::new(nested_bodies),
-                fingerprint: ast.stable_bodies_hash,
-            }
-        } else {
-            ExternBodyNestedBodies {
-                nested_bodies: Lrc::new(BTreeMap::new()),
-                fingerprint: Fingerprint::ZERO,
-            }
-        }
-    }
-
     pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool {
-        self.entry(id).ast.expect("const item missing `ast`")
-            .decode(self).rvalue_promotable_to_static
+        match self.entry(id).kind {
+            EntryKind::AssociatedConst(_, data, _) |
+            EntryKind::Const(data, _) => data.ast_promotable,
+            _ => bug!(),
+        }
     }
 
     pub fn is_item_mir_available(&self, id: DefIndex) -> bool {
@@ -862,10 +817,10 @@ pub fn maybe_get_optimized_mir(&self,
 
     pub fn mir_const_qualif(&self, id: DefIndex) -> u8 {
         match self.entry(id).kind {
-            EntryKind::Const(qualif) |
-            EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif) |
-            EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif) => {
-                qualif
+            EntryKind::Const(qualif, _) |
+            EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif, _) |
+            EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif, _) => {
+                qualif.mir
             }
             _ => bug!(),
         }
@@ -878,7 +833,7 @@ pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem {
         let name = def_key.disambiguated_data.data.get_opt_name().unwrap();
 
         let (kind, container, has_self) = match item.kind {
-            EntryKind::AssociatedConst(container, _) => {
+            EntryKind::AssociatedConst(container, _, _) => {
                 (ty::AssociatedKind::Const, container, false)
             }
             EntryKind::Method(data) => {
@@ -892,7 +847,7 @@ pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem {
         };
 
         ty::AssociatedItem {
-            name: Symbol::intern(&name),
+            name: name.as_symbol(),
             kind,
             vis: item.visibility.decode(self),
             defaultness: container.defaultness(),
@@ -959,7 +914,7 @@ pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
         self.entry(id)
             .children
             .decode(self)
-            .map(|index| Symbol::intern(&self.item_name(index)))
+            .map(|index| self.item_name(index).as_symbol())
             .collect()
     }
 
@@ -1022,7 +977,13 @@ pub fn get_implementations_for_trait(&self,
     }
 
     pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
-        self.def_key(id).parent.and_then(|parent_index| {
+        let def_key = self.def_key(id);
+        match def_key.disambiguated_data.data {
+            DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (),
+            // Not an associated item
+            _ => return None,
+        }
+        def_key.parent.and_then(|parent_index| {
             match self.entry(parent_index).kind {
                 EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
                 _ => None,
@@ -1077,6 +1038,14 @@ pub fn exported_symbols(&self,
         lazy_seq.decode((self, tcx)).collect()
     }
 
+    pub fn get_rendered_const(&self, id: DefIndex) -> String {
+        match self.entry(id).kind {
+            EntryKind::Const(_, data) |
+            EntryKind::AssociatedConst(_, _, data) => data.decode(self).0,
+            _ => bug!(),
+        }
+    }
+
     pub fn wasm_custom_sections(&self) -> Vec<DefId> {
         let sections = self.root
             .wasm_custom_sections
@@ -1143,7 +1112,7 @@ pub fn def_key(&self, index: DefIndex) -> DefKey {
             DefKey {
                 parent: Some(CRATE_DEF_INDEX),
                 disambiguated_data: DisambiguatedDefPathData {
-                    data: DefPathData::MacroDef(name.as_str()),
+                    data: DefPathData::MacroDef(name.as_interned_str()),
                     disambiguator: 0,
                 }
             }