]> 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 81375bd3a5a14bfed03c2bfccccc460224f1c966..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};
@@ -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),
@@ -133,6 +135,7 @@ pub enum FoundAst<'ast> {
 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)
@@ -142,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>;
@@ -207,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>;
@@ -215,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>;
@@ -234,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];
 }
@@ -258,24 +267,28 @@ pub fn visit_ids<O: IdVisitingOperation>(&self, operation: &mut O) {
 
 // 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));
     }
-    match sess {
-        Some(sess) => sess.abort_if_errors(),
-        None => {}
+
+    if err_count > 0 {
+        sess.unwrap().abort_if_errors();
     }
 }
 
@@ -286,6 +299,7 @@ pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
 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)
@@ -295,6 +309,7 @@ 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!() }
@@ -371,6 +386,9 @@ 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!() }
@@ -381,6 +399,9 @@ fn crate_top_level_items(&self, cnum: ast::CrateNum) -> Vec<ChildItem>
     // 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![] }
@@ -402,6 +423,145 @@ fn encode_metadata(&self,
                        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)
+        })
+    }
+}