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};
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};
// Something that a name can resolve to.
#[derive(Copy, Clone, Debug)]
pub enum DefLike {
- DlDef(def::Def),
+ DlDef(Def),
DlImpl(DefId),
DlField
}
}
/// 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),
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)
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>;
// 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>;
// 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>;
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];
}
}
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)
+ })
}
}