about summary refs log tree commit diff
path: root/src/librustc_metadata/decoder.rs
diff options
context:
space:
mode:
authorBaoshan <pangbw@gmail.com>2019-08-29 09:29:23 -0700
committerGitHub <noreply@github.com>2019-08-29 09:29:23 -0700
commit043c19c69c0beac3696cb82d44476ba4298a6b07 (patch)
tree1813e5dd1e4efd5806f401968b4ed34b8c9c76ac /src/librustc_metadata/decoder.rs
parentcae6d66d9989857e321e0963142b08b1517dc723 (diff)
parent76f17219c71973fd4a58f2f8020eec4d8f5dcd11 (diff)
Merge branch 'master' into bpang-runtest
Diffstat (limited to 'src/librustc_metadata/decoder.rs')
-rw-r--r--src/librustc_metadata/decoder.rs235
1 files changed, 144 insertions, 91 deletions
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 935187dd066..da96728d2de 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1,16 +1,15 @@
 // Decoding metadata from a single crate's metadata
 
-use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule};
+use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule, FullProcMacro};
 use crate::schema::*;
 
 use rustc_data_structures::sync::{Lrc, ReadGuard};
-use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions};
+use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc::hir;
 use rustc::middle::cstore::LinkagePreference;
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc::hir::map::definitions::DefPathTable;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc::middle::lang_items;
 use rustc::mir::{self, interpret};
@@ -30,10 +29,11 @@ use syntax::attr;
 use syntax::ast::{self, Ident};
 use syntax::source_map;
 use syntax::symbol::{Symbol, sym};
-use syntax::ext::base::{MacroKind, SyntaxExtension};
-use syntax::ext::hygiene::ExpnId;
-use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
+use syntax::ext::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension};
+use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}};
 use log::debug;
+use proc_macro::bridge::client::ProcMacro;
+use syntax::ext::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro};
 
 pub struct DecodeContext<'a, 'tcx> {
     opaque: opaque::Decoder<'a>,
@@ -134,14 +134,14 @@ impl<'a, 'tcx, T: Decodable> Lazy<T> {
     }
 }
 
-impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> LazySeq<T> {
+impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> {
     pub fn decode<M: Metadata<'a, 'tcx>>(
         self,
         meta: M,
-    ) -> impl Iterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x {
+    ) -> impl ExactSizeIterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x {
         let mut dcx = meta.decoder(self.position);
         dcx.lazy_state = LazyState::NodeStart(self.position);
-        (0..self.len).map(move |_| T::decode(&mut dcx).unwrap())
+        (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap())
     }
 }
 
@@ -154,10 +154,14 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
         self.cdata.expect("missing CrateMetadata in DecodeContext")
     }
 
-    fn read_lazy_distance(&mut self, min_size: usize) -> Result<usize, <Self as Decoder>::Error> {
+    fn read_lazy_with_meta<T: ?Sized + LazyMeta>(
+        &mut self,
+        meta: T::Meta,
+    ) -> Result<Lazy<T>, <Self as Decoder>::Error> {
+        let min_size = T::min_size(meta);
         let distance = self.read_usize()?;
         let position = match self.lazy_state {
-            LazyState::NoNode => bug!("read_lazy_distance: outside of a metadata node"),
+            LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"),
             LazyState::NodeStart(start) => {
                 assert!(distance + min_size <= start);
                 start - distance - min_size
@@ -165,7 +169,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
             LazyState::Previous(last_min_end) => last_min_end + distance,
         };
         self.lazy_state = LazyState::Previous(position + min_size);
-        Ok(position)
+        Ok(Lazy::from_position_and_meta(position, meta))
     }
 }
 
@@ -230,19 +234,18 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
 
 impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
-        Ok(Lazy::with_position(self.read_lazy_distance(Lazy::<T>::min_size())?))
+        self.read_lazy_with_meta(())
     }
 }
 
-impl<'a, 'tcx, T> SpecializedDecoder<LazySeq<T>> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<LazySeq<T>, Self::Error> {
+impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a, 'tcx> {
+    fn specialized_decode(&mut self) -> Result<Lazy<[T]>, Self::Error> {
         let len = self.read_usize()?;
-        let position = if len == 0 {
-            0
+        if len == 0 {
+            Ok(Lazy::empty())
         } else {
-            self.read_lazy_distance(LazySeq::<T>::min_size(len))?
-        };
-        Ok(LazySeq::with_position_and_length(position, len))
+            self.read_lazy_with_meta(len)
+        }
     }
 }
 
@@ -344,7 +347,15 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
         let hi = (hi + source_file.translated_source_file.start_pos)
                  - source_file.original_start_pos;
 
-        Ok(Span::new(lo, hi, NO_EXPANSION))
+        Ok(Span::with_root_ctxt(lo, hi))
+    }
+}
+
+impl SpecializedDecoder<Ident> for DecodeContext<'_, '_> {
+    fn specialized_decode(&mut self) -> Result<Ident, Self::Error> {
+        // FIXME(jseyfried): intercrate hygiene
+
+        Ok(Ident::with_dummy_span(Symbol::decode(self)?))
     }
 }
 
@@ -370,7 +381,7 @@ impl<'tcx> MetadataBlob {
     }
 
     pub fn get_rustc_version(&self) -> String {
-        Lazy::with_position(METADATA_HEADER.len() + 4).decode(self)
+        Lazy::<String>::from_position(METADATA_HEADER.len() + 4).decode(self)
     }
 
     pub fn get_root(&self) -> CrateRoot<'tcx> {
@@ -379,7 +390,7 @@ impl<'tcx> MetadataBlob {
         let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) |
                    ((slice[offset + 2] as u32) << 8) |
                    ((slice[offset + 3] as u32) << 0)) as usize;
-        Lazy::with_position(pos).decode(self)
+        Lazy::<CrateRoot<'tcx>>::from_position(pos).decode(self)
     }
 
     pub fn list_crate_metadata(&self,
@@ -434,46 +445,16 @@ impl<'tcx> EntryKind<'tcx> {
     }
 }
 
-/// Creates the "fake" DefPathTable for a given proc macro crate.
-///
-/// The DefPathTable is as follows:
-///
-/// CRATE_ROOT (DefIndex 0:0)
-///  |- GlobalMetaDataKind data (DefIndex 1:0 .. DefIndex 1:N)
-///  |- proc macro #0 (DefIndex 1:N)
-///  |- proc macro #1 (DefIndex 1:N+1)
-///  \- ...
-crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>,
-                                   proc_macros: &[(ast::Name, Lrc<SyntaxExtension>)])
-                                   -> DefPathTable
-{
-    let mut definitions = Definitions::default();
-
-    let name = crate_root.name.as_str();
-    let disambiguator = crate_root.disambiguator;
-    debug!("creating proc macro def path table for {:?}/{:?}", name, disambiguator);
-    let crate_root = definitions.create_root_def(&name, disambiguator);
-    for (index, (name, _)) in proc_macros.iter().enumerate() {
-        let def_index = definitions.create_def_with_parent(
-            crate_root,
-            ast::DUMMY_NODE_ID,
-            DefPathData::MacroNs(name.as_interned_str()),
-            ExpnId::root(),
-            DUMMY_SP);
-        debug!("definition for {:?} is {:?}", name, def_index);
-        assert_eq!(def_index, DefIndex::from_proc_macro_index(index));
-    }
-
-    definitions.def_path_table().clone()
-}
-
 impl<'a, 'tcx> CrateMetadata {
+    pub fn is_proc_macro_crate(&self) -> bool {
+        self.root.proc_macro_decls_static.is_some()
+    }
     fn is_proc_macro(&self, id: DefIndex) -> bool {
-        self.proc_macros.is_some() && id != CRATE_DEF_INDEX
+        self.is_proc_macro_crate() &&
+            self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some()
     }
 
     fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
-        assert!(!self.is_proc_macro(item_id));
         self.root.entries_index.lookup(self.blob.raw_bytes(), item_id)
     }
 
@@ -496,13 +477,24 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
+    fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
+        // DefIndex's in root.proc_macro_data have a one-to-one correspondence
+        // with items in 'raw_proc_macros'
+        let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap();
+        &self.raw_proc_macros.unwrap()[pos]
+    }
+
     pub fn item_name(&self, item_index: DefIndex) -> Symbol {
-        self.def_key(item_index)
-            .disambiguated_data
-            .data
-            .get_opt_name()
-            .expect("no name in item_name")
-            .as_symbol()
+        if !self.is_proc_macro(item_index) {
+            self.def_key(item_index)
+                .disambiguated_data
+                .data
+                .get_opt_name()
+                .expect("no name in item_name")
+                .as_symbol()
+        } else {
+            Symbol::intern(self.raw_proc_macro(item_index).name())
+        }
     }
 
     pub fn def_kind(&self, index: DefIndex) -> Option<DefKind> {
@@ -510,15 +502,64 @@ impl<'a, 'tcx> CrateMetadata {
             self.entry(index).kind.def_kind()
         } else {
             Some(DefKind::Macro(
-                self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.macro_kind()
+                macro_kind(self.raw_proc_macro(index))
             ))
         }
     }
 
     pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
-        match self.is_proc_macro(index) {
-            true => DUMMY_SP,
-            false => self.entry(index).span.decode((self, sess)),
+        self.entry(index).span.decode((self, sess))
+    }
+
+
+    pub fn get_proc_macro(&self, id: DefIndex, sess: &Session) -> FullProcMacro {
+        if sess.opts.debugging_opts.dual_proc_macros {
+            let host_lib = self.host_lib.as_ref().unwrap();
+            self.load_proc_macro(
+                &host_lib.metadata.get_root(),
+                id,
+                sess
+            )
+        } else {
+            self.load_proc_macro(&self.root, id, sess)
+        }
+    }
+
+    fn load_proc_macro(&self, root: &CrateRoot<'_>,
+                        id: DefIndex,
+                        sess: &Session)
+                        -> FullProcMacro {
+
+        let raw_macro = self.raw_proc_macro(id);
+        let (name, kind, helper_attrs) = match *raw_macro {
+            ProcMacro::CustomDerive { trait_name, attributes, client } => {
+                let helper_attrs =
+                    attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
+                (
+                    trait_name,
+                    SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive {
+                        client, attrs: helper_attrs.clone()
+                    })),
+                    helper_attrs,
+                )
+            }
+            ProcMacro::Attr { name, client } => (
+                name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()
+            ),
+            ProcMacro::Bang { name, client } => (
+                name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
+            )
+        };
+
+        let span = self.get_span(id, sess);
+
+        FullProcMacro {
+            name: Symbol::intern(name),
+            ext: Lrc::new(SyntaxExtension {
+                span,
+                helper_attrs,
+                ..SyntaxExtension::default(kind, root.edition)
+            })
         }
     }
 
@@ -569,7 +610,7 @@ impl<'a, 'tcx> CrateMetadata {
 
         ty::VariantDef::new(
             tcx,
-            Ident::with_empty_ctxt(self.item_name(index)),
+            Ident::with_dummy_span(self.item_name(index)),
             variant_did,
             ctor_did,
             data.discr,
@@ -577,7 +618,7 @@ impl<'a, 'tcx> CrateMetadata {
                 let f = self.entry(index);
                 ty::FieldDef {
                     did: self.local_def_id(index),
-                    ident: Ident::with_empty_ctxt(self.item_name(index)),
+                    ident: Ident::with_dummy_span(self.item_name(index)),
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
@@ -715,7 +756,7 @@ impl<'a, 'tcx> CrateMetadata {
 
     /// Iterates over the language items in the given crate.
     pub fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
-        if self.proc_macros.is_some() {
+        if self.is_proc_macro_crate() {
             // Proc macro crates do not export any lang-items to the target.
             &[]
         } else {
@@ -730,18 +771,18 @@ impl<'a, 'tcx> CrateMetadata {
     pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
         where F: FnMut(def::Export<hir::HirId>)
     {
-        if let Some(ref proc_macros) = self.proc_macros {
+        if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) {
             /* If we are loading as a proc macro, we want to return the view of this crate
-             * as a proc macro crate, not as a Rust crate. See `proc_macro_def_path_table`
-             * for the DefPathTable we are corresponding to.
+             * as a proc macro crate.
              */
             if id == CRATE_DEF_INDEX {
-                for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
+                for def_index in proc_macros_ids {
+                    let raw_macro = self.raw_proc_macro(def_index);
                     let res = Res::Def(
-                        DefKind::Macro(ext.macro_kind()),
-                        self.local_def_id(DefIndex::from_proc_macro_index(id)),
+                        DefKind::Macro(macro_kind(raw_macro)),
+                        self.local_def_id(def_index),
                     );
-                    let ident = Ident::with_empty_ctxt(name);
+                    let ident = Ident::from_str(raw_macro.name());
                     callback(def::Export {
                         ident: ident,
                         res: res,
@@ -783,7 +824,7 @@ impl<'a, 'tcx> CrateMetadata {
                             if let Some(kind) = self.def_kind(child_index) {
                                 callback(def::Export {
                                     res: Res::Def(kind, self.local_def_id(child_index)),
-                                    ident: Ident::with_empty_ctxt(self.item_name(child_index)),
+                                    ident: Ident::with_dummy_span(self.item_name(child_index)),
                                     vis: self.get_visibility(child_index),
                                     span: self.entry(child_index).span.decode((self, sess)),
                                 });
@@ -952,11 +993,8 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> {
-        if self.is_proc_macro(node_id) {
-            return Lrc::new([]);
-        }
 
+    pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> {
         // The attributes for a tuple struct/variant are attached to the definition, not the ctor;
         // we assume that someone passing in a tuple struct ctor is actually wanting to
         // look at the definition
@@ -1014,7 +1052,7 @@ impl<'a, 'tcx> CrateMetadata {
         tcx: TyCtxt<'tcx>,
         filter: Option<DefId>,
     ) -> &'tcx [DefId] {
-        if self.proc_macros.is_some() {
+        if self.is_proc_macro_crate() {
             // proc-macro crates export no trait impls.
             return &[]
         }
@@ -1058,7 +1096,7 @@ impl<'a, 'tcx> CrateMetadata {
 
 
     pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
-        if self.proc_macros.is_some() {
+        if self.is_proc_macro_crate() {
             // Proc macro crates do not have any *target* native libraries.
             vec![]
         } else {
@@ -1067,7 +1105,7 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     pub fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] {
-        if self.proc_macros.is_some() {
+        if self.is_proc_macro_crate() {
             // Proc macro crates do not have any *target* foreign modules.
             &[]
         } else {
@@ -1090,7 +1128,7 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     pub fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
-        if self.proc_macros.is_some() {
+        if self.is_proc_macro_crate() {
             // Proc macro crates do not depend on any target weak lang-items.
             &[]
         } else {
@@ -1105,7 +1143,7 @@ impl<'a, 'tcx> CrateMetadata {
             EntryKind::Fn(data) |
             EntryKind::ForeignFn(data) => data.decode(self).arg_names,
             EntryKind::Method(data) => data.decode(self).fn_data.arg_names,
-            _ => LazySeq::empty(),
+            _ => Lazy::empty(),
         };
         arg_names.decode(self).collect()
     }
@@ -1114,7 +1152,7 @@ impl<'a, 'tcx> CrateMetadata {
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
-        if self.proc_macros.is_some() {
+        if self.is_proc_macro_crate() {
             // If this crate is a custom derive crate, then we're not even going to
             // link those in so we skip those crates.
             vec![]
@@ -1183,13 +1221,18 @@ impl<'a, 'tcx> CrateMetadata {
 
     #[inline]
     pub fn def_key(&self, index: DefIndex) -> DefKey {
-        self.def_path_table.def_key(index)
+        let mut key = self.def_path_table.def_key(index);
+        if self.is_proc_macro(index) {
+            let name = self.raw_proc_macro(index).name();
+            key.disambiguated_data.data = DefPathData::MacroNs(InternedString::intern(name));
+        }
+        key
     }
 
     // Returns the path leading to the thing with this `id`.
     pub fn def_path(&self, id: DefIndex) -> DefPath {
         debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
-        DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent))
+        DefPath::make(self.cnum, id, |parent| self.def_key(parent))
     }
 
     #[inline]
@@ -1302,3 +1345,13 @@ impl<'a, 'tcx> CrateMetadata {
         self.source_map_import_info.borrow()
     }
 }
+
+// Cannot be implemented on 'ProcMacro', as libproc_macro
+// does not depend on libsyntax
+fn macro_kind(raw: &ProcMacro) -> MacroKind {
+    match raw {
+        ProcMacro::CustomDerive { .. } => MacroKind::Derive,
+        ProcMacro::Attr { .. } => MacroKind::Attr,
+        ProcMacro::Bang { .. } => MacroKind::Bang
+    }
+}