]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/cstore.rs
Rollup merge of #31186 - gchp:contributing, r=alexcrichton
[rust.git] / src / librustc / middle / cstore.rs
index ee337f02ffc968a9a7b4173f26324b91092b32c0..973fd65beb3d88031936d271563ede90c60465e4 100644 (file)
 
 use back::svh::Svh;
 use front::map as hir_map;
-use middle::def;
+use middle::def::{self, Def};
 use middle::lang_items;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, VariantKind};
 use middle::def_id::{DefId, DefIndex};
+use mir::repr::Mir;
 use session::Session;
 use session::search_paths::PathKind;
 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
@@ -42,7 +43,7 @@
 use syntax::ptr::P;
 use rustc_back::target::Target;
 use rustc_front::hir;
-use rustc_front::visit::Visitor;
+use rustc_front::intravisit::Visitor;
 use rustc_front::util::IdVisitor;
 
 pub use self::DefLike::{DlDef, DlField, DlImpl};
@@ -83,7 +84,7 @@ pub enum NativeLibraryKind {
 // Something that a name can resolve to.
 #[derive(Copy, Clone, Debug)]
 pub enum DefLike {
-    DlDef(def::Def),
+    DlDef(Def),
     DlImpl(DefId),
     DlField
 }
@@ -100,6 +101,7 @@ pub enum InlinedItem {
 }
 
 /// A borrowed version of `hir::InlinedItem`.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub enum InlinedItemRef<'a> {
     Item(&'a hir::Item),
     TraitItem(DefId, &'a hir::TraitItem),
@@ -123,9 +125,17 @@ pub enum FoundAst<'ast> {
     NotFound,
 }
 
+/// A store of Rust crates, through with their metadata
+/// can be accessed.
+///
+/// The `: Any` bound is a temporary measure that allows access
+/// to the backing `rustc_metadata::cstore::CStore` object. It
+/// will be removed in the near future - if you need to access
+/// internal APIs, please tell us.
 pub trait CrateStore<'tcx> : Any {
     // item info
     fn stability(&self, def: DefId) -> Option<attr::Stability>;
+    fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>;
     fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
                     -> ty::ClosureKind;
     fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
@@ -135,6 +145,7 @@ fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
     fn item_type(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
                  -> ty::TypeScheme<'tcx>;
     fn item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
+    fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem>;
     fn item_name(&self, def: DefId) -> ast::Name;
     fn item_predicates(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
                        -> ty::GenericPredicates<'tcx>;
@@ -200,6 +211,8 @@ fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
 
     // resolve
     fn def_path(&self, def: DefId) -> hir_map::DefPath;
+    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind>;
+    fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>;
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>;
     fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
     fn item_children(&self, did: DefId) -> Vec<ChildItem>;
@@ -208,6 +221,8 @@ fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
     // misc. metadata
     fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId)
                           -> FoundAst<'tcx>;
+    fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                          -> Option<Mir<'tcx>>;
     // This is basically a 1-based range of ints, which is a little
     // silly - I may fix that.
     fn crates(&self) -> Vec<ast::CrateNum>;
@@ -227,6 +242,7 @@ fn encode_metadata(&self,
                        item_symbols: &RefCell<NodeMap<String>>,
                        link_meta: &LinkMeta,
                        reachable: &NodeSet,
+                       mir_map: &NodeMap<Mir<'tcx>>,
                        krate: &hir::Crate) -> Vec<u8>;
     fn metadata_encoding_version(&self) -> &[u8];
 }
@@ -244,34 +260,308 @@ pub fn visit<'ast,V>(&'ast self, visitor: &mut V)
     }
 
     pub fn visit_ids<O: IdVisitingOperation>(&self, operation: &mut O) {
-        let mut id_visitor = IdVisitor {
-            operation: operation,
-            pass_through_items: true,
-            visited_outermost: false,
-        };
+        let mut id_visitor = IdVisitor::new(operation);
         self.visit(&mut id_visitor);
     }
 }
 
 // FIXME: find a better place for this?
 pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
-    let say = |s: &str| {
-        match (sp, sess) {
-            (_, None) => panic!("{}", s),
-            (Some(sp), Some(sess)) => sess.span_err(sp, s),
-            (None, Some(sess)) => sess.err(s),
+    let mut err_count = 0;
+    {
+        let mut say = |s: &str| {
+            match (sp, sess) {
+                (_, None) => panic!("{}", s),
+                (Some(sp), Some(sess)) => sess.span_err(sp, s),
+                (None, Some(sess)) => sess.err(s),
+            }
+            err_count += 1;
+        };
+        if s.is_empty() {
+            say("crate name must not be empty");
+        }
+        for c in s.chars() {
+            if c.is_alphanumeric() { continue }
+            if c == '_'  { continue }
+            say(&format!("invalid character `{}` in crate name: `{}`", c, s));
         }
-    };
-    if s.is_empty() {
-        say("crate name must not be empty");
     }
-    for c in s.chars() {
-        if c.is_alphanumeric() { continue }
-        if c == '_'  { continue }
-        say(&format!("invalid character `{}` in crate name: `{}`", c, s));
+
+    if err_count > 0 {
+        sess.unwrap().abort_if_errors();
     }
-    match sess {
-        Some(sess) => sess.abort_if_errors(),
-        None => {}
+}
+
+/// A dummy crate store that does not support any non-local crates,
+/// for test purposes.
+pub struct DummyCrateStore;
+#[allow(unused_variables)]
+impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
+    // item info
+    fn stability(&self, def: DefId) -> Option<attr::Stability> { unimplemented!() }
+    fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { unimplemented!() }
+    fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
+                    -> ty::ClosureKind  { unimplemented!() }
+    fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
+                  -> ty::ClosureTy<'tcx>  { unimplemented!() }
+    fn item_variances(&self, def: DefId) -> ty::ItemVariances { unimplemented!() }
+    fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { unimplemented!() }
+    fn item_type(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                 -> ty::TypeScheme<'tcx> { unimplemented!() }
+    fn item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
+    fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
+    fn item_name(&self, def: DefId) -> ast::Name { unimplemented!() }
+    fn item_predicates(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                       -> ty::GenericPredicates<'tcx> { unimplemented!() }
+    fn item_super_predicates(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                             -> ty::GenericPredicates<'tcx> { unimplemented!() }
+    fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { unimplemented!() }
+    fn item_symbol(&self, def: DefId) -> String { unimplemented!() }
+    fn trait_def(&self, tcx: &ty::ctxt<'tcx>, def: DefId)-> ty::TraitDef<'tcx>
+        { unimplemented!() }
+    fn adt_def(&self, tcx: &ty::ctxt<'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>
+        { unimplemented!() }
+    fn method_arg_names(&self, did: DefId) -> Vec<String> { unimplemented!() }
+    fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId> { vec![] }
+
+    // trait info
+    fn implementations_of_trait(&self, def_id: DefId) -> Vec<DefId> { vec![] }
+    fn provided_trait_methods(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                              -> Vec<Rc<ty::Method<'tcx>>> { unimplemented!() }
+    fn trait_item_def_ids(&self, def: DefId)
+                          -> Vec<ty::ImplOrTraitItemId> { unimplemented!() }
+
+    // impl info
+    fn impl_items(&self, impl_def_id: DefId) -> Vec<ty::ImplOrTraitItemId>
+        { unimplemented!() }
+    fn impl_trait_ref(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                      -> Option<ty::TraitRef<'tcx>> { unimplemented!() }
+    fn impl_polarity(&self, def: DefId) -> Option<hir::ImplPolarity> { unimplemented!() }
+    fn custom_coerce_unsized_kind(&self, def: DefId)
+                                  -> Option<ty::adjustment::CustomCoerceUnsized>
+        { unimplemented!() }
+    fn associated_consts(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                         -> Vec<Rc<ty::AssociatedConst<'tcx>>> { unimplemented!() }
+
+    // trait/impl-item info
+    fn trait_of_item(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
+                     -> Option<DefId> { unimplemented!() }
+    fn impl_or_trait_item(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                          -> ty::ImplOrTraitItem<'tcx> { unimplemented!() }
+
+    // flags
+    fn is_const_fn(&self, did: DefId) -> bool { unimplemented!() }
+    fn is_defaulted_trait(&self, did: DefId) -> bool { unimplemented!() }
+    fn is_impl(&self, did: DefId) -> bool { unimplemented!() }
+    fn is_default_impl(&self, impl_did: DefId) -> bool { unimplemented!() }
+    fn is_extern_fn(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool { unimplemented!() }
+    fn is_static(&self, did: DefId) -> bool { unimplemented!() }
+    fn is_static_method(&self, did: DefId) -> bool { unimplemented!() }
+    fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false }
+    fn is_typedef(&self, did: DefId) -> bool { unimplemented!() }
+
+    // crate metadata
+    fn dylib_dependency_formats(&self, cnum: ast::CrateNum)
+                                    -> Vec<(ast::CrateNum, LinkagePreference)>
+        { unimplemented!() }
+    fn lang_items(&self, cnum: ast::CrateNum) -> Vec<(DefIndex, usize)>
+        { unimplemented!() }
+    fn missing_lang_items(&self, cnum: ast::CrateNum) -> Vec<lang_items::LangItem>
+        { unimplemented!() }
+    fn is_staged_api(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
+    fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
+    fn is_allocator(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
+    fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec<ast::Attribute>
+        { unimplemented!() }
+    fn crate_name(&self, cnum: ast::CrateNum) -> String { unimplemented!() }
+    fn crate_hash(&self, cnum: ast::CrateNum) -> Svh { unimplemented!() }
+    fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
+                                -> FnvHashMap<DefId, Vec<ast::Attribute>>
+        { unimplemented!() }
+    fn plugin_registrar_fn(&self, cnum: ast::CrateNum) -> Option<DefId>
+        { unimplemented!() }
+    fn native_libraries(&self, cnum: ast::CrateNum) -> Vec<(NativeLibraryKind, String)>
+        { unimplemented!() }
+    fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId> { unimplemented!() }
+
+    // resolve
+    fn def_path(&self, def: DefId) -> hir_map::DefPath { unimplemented!() }
+    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> { unimplemented!() }
+    fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
+        { unimplemented!() }
+    fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>
+        { unimplemented!() }
+    fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { unimplemented!() }
+    fn item_children(&self, did: DefId) -> Vec<ChildItem> { unimplemented!() }
+    fn crate_top_level_items(&self, cnum: ast::CrateNum) -> Vec<ChildItem>
+        { unimplemented!() }
+
+    // misc. metadata
+    fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                          -> FoundAst<'tcx> { unimplemented!() }
+    fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId)
+                          -> Option<Mir<'tcx>> { unimplemented!() }
+
+    // This is basically a 1-based range of ints, which is a little
+    // silly - I may fix that.
+    fn crates(&self) -> Vec<ast::CrateNum> { vec![] }
+    fn used_libraries(&self) -> Vec<(String, NativeLibraryKind)> { vec![] }
+    fn used_link_args(&self) -> Vec<String> { vec![] }
+
+    // utility functions
+    fn metadata_filename(&self) -> &str { unimplemented!() }
+    fn metadata_section_name(&self, target: &Target) -> &str { unimplemented!() }
+    fn encode_type(&self, tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Vec<u8>
+        { unimplemented!() }
+    fn used_crates(&self, prefer: LinkagePreference) -> Vec<(ast::CrateNum, Option<PathBuf>)>
+        { vec![] }
+    fn used_crate_source(&self, cnum: ast::CrateNum) -> CrateSource { unimplemented!() }
+    fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<ast::CrateNum> { None }
+    fn encode_metadata(&self,
+                       tcx: &ty::ctxt<'tcx>,
+                       reexports: &def::ExportMap,
+                       item_symbols: &RefCell<NodeMap<String>>,
+                       link_meta: &LinkMeta,
+                       reachable: &NodeSet,
+                       mir_map: &NodeMap<Mir<'tcx>>,
+                       krate: &hir::Crate) -> Vec<u8> { vec![] }
+    fn metadata_encoding_version(&self) -> &[u8] { unimplemented!() }
+}
+
+
+/// Metadata encoding and decoding can make use of thread-local encoding and
+/// decoding contexts. These allow implementers of serialize::Encodable and
+/// Decodable to access information and datastructures that would otherwise not
+/// be available to them. For example, we can automatically translate def-id and
+/// span information during decoding because the decoding context knows which
+/// crate the data is decoded from. Or it allows to make ty::Ty decodable
+/// because the context has access to the ty::ctxt that is needed for creating
+/// ty::Ty instances.
+///
+/// Note, however, that this only works for RBML-based encoding and decoding at
+/// the moment.
+pub mod tls {
+    use rbml::opaque::Encoder as OpaqueEncoder;
+    use rbml::opaque::Decoder as OpaqueDecoder;
+    use serialize;
+    use std::mem;
+    use middle::ty::{self, Ty};
+    use middle::subst::Substs;
+    use middle::def_id::DefId;
+
+    pub trait EncodingContext<'tcx> {
+        fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
+        fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: Ty<'tcx>);
+        fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>);
+    }
+
+    /// Marker type used for the scoped TLS slot.
+    /// The type context cannot be used directly because the scoped TLS
+    /// in libstd doesn't allow types generic over lifetimes.
+    struct TlsPayload;
+
+    scoped_thread_local!(static TLS_ENCODING: TlsPayload);
+
+    /// Execute f after pushing the given EncodingContext onto the TLS stack.
+    pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>,
+                                              encoder: &mut OpaqueEncoder,
+                                              f: F) -> R
+        where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R
+    {
+        let tls_payload = (ecx as *const _, encoder as *mut _);
+        let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
+        TLS_ENCODING.set(unsafe { &*tls_ptr }, || f(ecx, encoder))
+    }
+
+    /// Execute f with access to the thread-local encoding context and
+    /// rbml encoder. This function will panic if the encoder passed in and the
+    /// context encoder are not the same.
+    ///
+    /// Note that this method is 'practically' safe due to its checking that the
+    /// encoder passed in is the same as the one in TLS, but it would still be
+    /// possible to construct cases where the EncodingContext is exchanged
+    /// while the same encoder is used, thus working with a wrong context.
+    pub fn with_encoding_context<'tcx, E, F, R>(encoder: &mut E, f: F) -> R
+        where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R,
+              E: serialize::Encoder
+    {
+        unsafe {
+            unsafe_with_encoding_context(|ecx, tls_encoder| {
+                assert!(encoder as *mut _ as usize == tls_encoder as *mut _ as usize);
+
+                let ecx: &EncodingContext<'tcx> = mem::transmute(ecx);
+
+                f(ecx, tls_encoder)
+            })
+        }
+    }
+
+    /// Execute f with access to the thread-local encoding context and
+    /// rbml encoder.
+    pub unsafe fn unsafe_with_encoding_context<F, R>(f: F) -> R
+        where F: FnOnce(&EncodingContext, &mut OpaqueEncoder) -> R
+    {
+        TLS_ENCODING.with(|tls| {
+            let tls_payload = (tls as *const TlsPayload)
+                                   as *mut (&EncodingContext, &mut OpaqueEncoder);
+            f((*tls_payload).0, (*tls_payload).1)
+        })
+    }
+
+    pub trait DecodingContext<'tcx> {
+        fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
+        fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>;
+        fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx>;
+        fn translate_def_id(&self, def_id: DefId) -> DefId;
+    }
+
+    scoped_thread_local!(static TLS_DECODING: TlsPayload);
+
+    /// Execute f after pushing the given DecodingContext onto the TLS stack.
+    pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>,
+                                              decoder: &mut OpaqueDecoder,
+                                              f: F) -> R
+        where F: FnOnce(&DecodingContext<'tcx>, &mut OpaqueDecoder) -> R
+    {
+        let tls_payload = (dcx as *const _, decoder as *mut _);
+        let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
+        TLS_DECODING.set(unsafe { &*tls_ptr }, || f(dcx, decoder))
+    }
+
+    /// Execute f with access to the thread-local decoding context and
+    /// rbml decoder. This function will panic if the decoder passed in and the
+    /// context decoder are not the same.
+    ///
+    /// Note that this method is 'practically' safe due to its checking that the
+    /// decoder passed in is the same as the one in TLS, but it would still be
+    /// possible to construct cases where the DecodingContext is exchanged
+    /// while the same decoder is used, thus working with a wrong context.
+    pub fn with_decoding_context<'decoder, 'tcx, D, F, R>(d: &'decoder mut D, f: F) -> R
+        where D: serialize::Decoder,
+              F: FnOnce(&DecodingContext<'tcx>,
+                        &mut OpaqueDecoder) -> R,
+              'tcx: 'decoder
+    {
+        unsafe {
+            unsafe_with_decoding_context(|dcx, decoder| {
+                assert!((d as *mut _ as usize) == (decoder as *mut _ as usize));
+
+                let dcx: &DecodingContext<'tcx> = mem::transmute(dcx);
+
+                f(dcx, decoder)
+            })
+        }
+    }
+
+    /// Execute f with access to the thread-local decoding context and
+    /// rbml decoder.
+    pub unsafe fn unsafe_with_decoding_context<F, R>(f: F) -> R
+        where F: FnOnce(&DecodingContext, &mut OpaqueDecoder) -> R
+    {
+        TLS_DECODING.with(|tls| {
+            let tls_payload = (tls as *const TlsPayload)
+                                   as *mut (&DecodingContext, &mut OpaqueDecoder);
+            f((*tls_payload).0, (*tls_payload).1)
+        })
     }
 }