diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index c438944cf0131..caa912c7c8baf 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -511,8 +511,8 @@ define_dep_nodes!( <'tcx> [] ParamEnv(DefId), [] DescribeDef(DefId), [] DefSpan(DefId), - [] Stability(DefId), - [] Deprecation(DefId), + [] LookupStability(DefId), + [] LookupDeprecationEntry(DefId), [] ItemBodyNestedBodies(DefId), [] ConstIsRvaluePromotableToStatic(DefId), [] ImplParent(DefId), @@ -521,16 +521,60 @@ define_dep_nodes!( <'tcx> [] IsMirAvailable(DefId), [] ItemAttrs(DefId), [] FnArgNames(DefId), - [] DylibDepFormats(DefId), - [] IsAllocator(DefId), - [] IsPanicRuntime(DefId), - [] IsCompilerBuiltins(DefId), - [] HasGlobalAllocator(DefId), + [] DylibDepFormats(CrateNum), + [] IsPanicRuntime(CrateNum), + [] IsCompilerBuiltins(CrateNum), + [] HasGlobalAllocator(CrateNum), [] ExternCrate(DefId), [] LintLevels, [] Specializes { impl1: DefId, impl2: DefId }, [] InScopeTraits(HirId), [] ModuleExports(HirId), + [] IsSanitizerRuntime(CrateNum), + [] IsProfilerRuntime(CrateNum), + [] GetPanicStrategy(CrateNum), + [] IsNoBuiltins(CrateNum), + [] ImplDefaultness(DefId), + [] ExportedSymbols(CrateNum), + [] NativeLibraries(CrateNum), + [] PluginRegistrarFn(CrateNum), + [] DeriveRegistrarFn(CrateNum), + [] CrateDisambiguator(CrateNum), + [] CrateHash(CrateNum), + [] OriginalCrateName(CrateNum), + + [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId }, + [] AllTraitImplementations(CrateNum), + + [] IsDllimportForeignItem(DefId), + [] IsStaticallyIncludedForeignItem(DefId), + [] NativeLibraryKind(DefId), + [] LinkArgs, + + [] NamedRegion(HirId), + [] IsLateBound(HirId), + [] ObjectLifetimeDefaults(HirId), + + [] Visibility(DefId), + [] DepKind(CrateNum), + [] CrateName(CrateNum), + [] ItemChildren(DefId), + [] ExternModStmtCnum(HirId), + [] GetLangItems, + [] DefinedLangItems(CrateNum), + [] MissingLangItems(CrateNum), + [] ExternConstBody(DefId), + [] VisibleParentMap, + [] IsDirectExternCrate(CrateNum), + [] MissingExternCrateItem(CrateNum), + [] UsedCrateSource(CrateNum), + [] PostorderCnums, + + [] Freevars(HirId), + [] MaybeUnusedTraitImport(HirId), + [] MaybeUnusedExternCrates, + [] StabilityIndex, + [] AllCrateNums, ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index c487fc963ca14..34cb1d2a6d795 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -235,10 +235,13 @@ impl DepGraph { debug_str_gen: F) where F: FnOnce() -> String { - let mut dep_node_debug = self.data.as_ref().unwrap().dep_node_debug.borrow_mut(); + let dep_node_debug = &self.data.as_ref().unwrap().dep_node_debug; - dep_node_debug.entry(dep_node) - .or_insert_with(debug_str_gen); + if dep_node_debug.borrow().contains_key(&dep_node) { + return + } + let debug_str = debug_str_gen(); + dep_node_debug.borrow_mut().insert(dep_node, debug_str); } pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 0f69c06c417a1..db86c4f93ee52 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -787,7 +787,7 @@ impl<'a> LoweringContext<'a> { return n; } assert!(!def_id.is_local()); - let n = self.sess.cstore.item_generics_cloned(def_id).regions.len(); + let n = self.sess.cstore.item_generics_cloned_untracked(def_id).regions.len(); self.type_def_lifetime_params.insert(def_id, n); n }); @@ -2863,7 +2863,7 @@ impl<'a> LoweringContext<'a> { let parent_def = self.parent_def.unwrap(); let def_id = { let defs = self.resolver.definitions(); - let def_path_data = DefPathData::Binding(name); + let def_path_data = DefPathData::Binding(name.as_str()); let def_index = defs.create_def_with_parent(parent_def, node_id, def_path_data, diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index d348a5db05170..af027e321c6a1 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -104,14 +104,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { DefPathData::Impl, ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => - DefPathData::TypeNs(i.ident.name), + DefPathData::TypeNs(i.ident.name.as_str()), ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { return visit::walk_item(self, i); } - ItemKind::Mod(..) => DefPathData::Module(i.ident.name), + ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()), ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => - DefPathData::ValueNs(i.ident.name), - ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name), + DefPathData::ValueNs(i.ident.name.as_str()), + ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()), ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false), ItemKind::GlobalAsm(..) => DefPathData::Misc, ItemKind::Use(ref view_path) => { @@ -139,13 +139,15 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { for v in &enum_definition.variants { let variant_def_index = this.create_def(v.node.data.id(), - DefPathData::EnumVariant(v.node.name.name), + DefPathData::EnumVariant(v.node.name.name.as_str()), REGULAR_SPACE); this.with_parent(variant_def_index, |this| { for (index, field) in v.node.data.fields().iter().enumerate() { let name = field.ident.map(|ident| ident.name) .unwrap_or_else(|| Symbol::intern(&index.to_string())); - this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE); + this.create_def(field.id, + DefPathData::Field(name.as_str()), + REGULAR_SPACE); } if let Some(ref expr) = v.node.disr_expr { @@ -165,7 +167,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { for (index, field) in struct_def.fields().iter().enumerate() { let name = field.ident.map(|ident| ident.name) .unwrap_or_else(|| Symbol::intern(&index.to_string())); - this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE); + this.create_def(field.id, DefPathData::Field(name.as_str()), REGULAR_SPACE); } } _ => {} @@ -176,7 +178,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { let def = self.create_def(foreign_item.id, - DefPathData::ValueNs(foreign_item.ident.name), + DefPathData::ValueNs(foreign_item.ident.name.as_str()), REGULAR_SPACE); self.with_parent(def, |this| { @@ -187,7 +189,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_generics(&mut self, generics: &'a Generics) { for ty_param in generics.ty_params.iter() { self.create_def(ty_param.id, - DefPathData::TypeParam(ty_param.ident.name), + DefPathData::TypeParam(ty_param.ident.name.as_str()), REGULAR_SPACE); } @@ -197,8 +199,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_trait_item(&mut self, ti: &'a TraitItem) { let def_data = match ti.node { TraitItemKind::Method(..) | TraitItemKind::Const(..) => - DefPathData::ValueNs(ti.ident.name), - TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name), + DefPathData::ValueNs(ti.ident.name.as_str()), + TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()), TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false), }; @@ -215,8 +217,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { let def_data = match ii.node { ImplItemKind::Method(..) | ImplItemKind::Const(..) => - DefPathData::ValueNs(ii.ident.name), - ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name), + DefPathData::ValueNs(ii.ident.name.as_str()), + ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()), ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false), }; @@ -237,7 +239,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false), PatKind::Ident(_, id, _) => { let def = self.create_def(pat.id, - DefPathData::Binding(id.node.name), + DefPathData::Binding(id.node.name.as_str()), REGULAR_SPACE); self.parent_def = Some(def); } @@ -282,7 +284,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) { self.create_def(def.lifetime.id, - DefPathData::LifetimeDef(def.lifetime.ident.name), + DefPathData::LifetimeDef(def.lifetime.ident.name.as_str()), REGULAR_SPACE); } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index b371366bc5d55..7bd2e5eceaec6 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -80,8 +80,10 @@ impl DefPathTable { #[inline(always)] pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { - self.def_path_hashes[index.address_space().index()] - [index.as_array_index()] + let ret = self.def_path_hashes[index.address_space().index()] + [index.as_array_index()]; + debug!("def_path_hash({:?}) = {:?}", index, ret); + return ret } pub fn add_def_path_hashes_to(&self, @@ -213,7 +215,7 @@ impl DefKey { DefPathData::Binding(name) | DefPathData::Field(name) | DefPathData::GlobalMetaData(name) => { - (*name.as_str()).hash(&mut hasher); + name.hash(&mut hasher); } DefPathData::Impl | @@ -347,31 +349,31 @@ pub enum DefPathData { /// An impl Impl, /// Something in the type NS - TypeNs(Symbol), + TypeNs(InternedString), /// Something in the value NS - ValueNs(Symbol), + ValueNs(InternedString), /// A module declaration - Module(Symbol), + Module(InternedString), /// A macro rule - MacroDef(Symbol), + MacroDef(InternedString), /// A closure expression ClosureExpr, // Subportions of items /// A type parameter (generic parameter) - TypeParam(Symbol), + TypeParam(InternedString), /// A lifetime definition - LifetimeDef(Symbol), + LifetimeDef(InternedString), /// A variant of a enum - EnumVariant(Symbol), + EnumVariant(InternedString), /// A struct field - Field(Symbol), + Field(InternedString), /// Implicit ctor for a tuple-like struct StructCtor, /// Initializer for a const Initializer, /// Pattern binding - Binding(Symbol), + Binding(InternedString), /// An `impl Trait` type node. ImplTrait, /// A `typeof` type node. @@ -380,7 +382,7 @@ pub enum DefPathData { /// GlobalMetaData identifies a piece of crate metadata that is global to /// a whole crate (as opposed to just one item). GlobalMetaData components /// are only supposed to show up right below the crate root. - GlobalMetaData(Symbol) + GlobalMetaData(InternedString) } #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, @@ -601,7 +603,7 @@ impl Definitions { } impl DefPathData { - pub fn get_opt_name(&self) -> Option { + pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { TypeNs(name) | @@ -639,7 +641,7 @@ impl DefPathData { Binding(name) | Field(name) | GlobalMetaData(name) => { - return name.as_str(); + return name } // note that this does not show up in user printouts @@ -684,7 +686,7 @@ macro_rules! define_global_metadata_kind { definitions.create_def_with_parent( CRATE_DEF_INDEX, ast::DUMMY_NODE_ID, - DefPathData::GlobalMetaData(instance.name()), + DefPathData::GlobalMetaData(instance.name().as_str()), GLOBAL_MD_ADDRESS_SPACE, Mark::root() ); @@ -698,7 +700,7 @@ macro_rules! define_global_metadata_kind { let def_key = DefKey { parent: Some(CRATE_DEF_INDEX), disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::GlobalMetaData(self.name()), + data: DefPathData::GlobalMetaData(self.name().as_str()), disambiguator: 0, } }; diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index e54df2d50d8eb..d043d8346e6a8 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -878,7 +878,17 @@ impl<'hir> Map<'hir> { Some(RootCrate(_)) => self.forest.krate.span, Some(NotPresent) | None => { - bug!("hir::map::Map::span: id not in map: {:?}", id) + // Some nodes, notably macro definitions, are not + // present in the map for whatever reason, but + // they *do* have def-ids. So if we encounter an + // empty hole, check for that case. + if let Some(def_index) = self.definitions.opt_def_index(id) { + let def_path_hash = self.definitions.def_path_hash(def_index); + self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); + DUMMY_SP + } else { + bug!("hir::map::Map::span: id not in map: {:?}", id) + } } } } diff --git a/src/librustc/infer/error_reporting/anon_anon_conflict.rs b/src/librustc/infer/error_reporting/anon_anon_conflict.rs index c80ce3c96f1a9..d3fff4c66af07 100644 --- a/src/librustc/infer/error_reporting/anon_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/anon_anon_conflict.rs @@ -209,18 +209,19 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> { match arg.node { hir::TyRptr(ref lifetime, _) => { - match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) { + let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id); + match self.infcx.tcx.named_region(hir_id) { // the lifetime of the TyRptr - Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => { + Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)) => { if debruijn_index.depth == 1 && anon_index == br_index { self.found_type = Some(arg); return; // we can stop visiting now } } - Some(&rl::Region::Static) | - Some(&rl::Region::EarlyBound(_, _)) | - Some(&rl::Region::LateBound(_, _)) | - Some(&rl::Region::Free(_, _)) | + Some(rl::Region::Static) | + Some(rl::Region::EarlyBound(_, _)) | + Some(rl::Region::LateBound(_, _)) | + Some(rl::Region::Free(_, _)) | None => { debug!("no arg found"); } @@ -272,17 +273,18 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> { _ => return, }; - match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) { + let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id); + match self.infcx.tcx.named_region(hir_id) { // the lifetime of the TyPath! - Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => { + Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)) => { if debruijn_index.depth == 1 && anon_index == br_index { self.found_it = true; } } - Some(&rl::Region::Static) | - Some(&rl::Region::EarlyBound(_, _)) | - Some(&rl::Region::LateBound(_, _)) | - Some(&rl::Region::Free(_, _)) | + Some(rl::Region::Static) | + Some(rl::Region::EarlyBound(_, _)) | + Some(rl::Region::LateBound(_, _)) | + Some(rl::Region::Free(_, _)) | None => { debug!("no arg found"); } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 476bf94714268..ff52f1e4e39ff 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -357,7 +357,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // for imported and non-imported crates if exp_path == found_path || exp_abs_path == found_abs_path { - let crate_name = self.tcx.sess.cstore.crate_name(did1.krate); + let crate_name = self.tcx.crate_name(did1.krate); err.span_note(sp, &format!("Perhaps two different versions \ of crate `{}` are being used?", crate_name)); diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 288390cb5e7c1..a7d874386d1c9 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -23,16 +23,15 @@ //! probably get a better home if someone can find one. use hir::def; -use hir::def_id::{CrateNum, DefId, DefIndex}; +use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use hir::map as hir_map; use hir::map::definitions::{Definitions, DefKey, DefPathTable}; use hir::svh::Svh; use ich; -use middle::lang_items; use ty::{self, TyCtxt}; use session::Session; use session::search_paths::PathKind; -use util::nodemap::{NodeSet, DefIdMap}; +use util::nodemap::NodeSet; use std::any::Any; use std::path::{Path, PathBuf}; @@ -43,8 +42,6 @@ use syntax::ext::base::SyntaxExtension; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_back::target::Target; -use hir; -use rustc_back::PanicStrategy; pub use self::NativeLibraryKind::*; @@ -223,75 +220,44 @@ pub trait MetadataLoader { /// A store of Rust crates, through with their metadata /// can be accessed. +/// +/// Note that this trait should probably not be expanding today. All new +/// functionality should be driven through queries instead! +/// +/// If you find a method on this trait named `{name}_untracked` it signifies +/// that it's *not* tracked for dependency information throughout compilation +/// (it'd break incremental compilation) and should only be called pre-HIR (e.g. +/// during resolve) pub trait CrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc; // access to the metadata loader fn metadata_loader(&self) -> &MetadataLoader; - // item info - fn visibility(&self, def: DefId) -> ty::Visibility; - fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefIdMap>; - fn item_generics_cloned(&self, def: DefId) -> ty::Generics; - - // trait info - fn implementations_of_trait(&self, filter: Option) -> Vec; - - // impl info - fn impl_defaultness(&self, def: DefId) -> hir::Defaultness; - - // trait/impl-item info - fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem; - - // flags - fn is_dllimport_foreign_item(&self, def: DefId) -> bool; - fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool; - - // crate metadata - fn dep_kind(&self, cnum: CrateNum) -> DepKind; - fn export_macros(&self, cnum: CrateNum); - fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>; - fn missing_lang_items(&self, cnum: CrateNum) -> Vec; - fn is_compiler_builtins(&self, cnum: CrateNum) -> bool; - fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool; - fn is_profiler_runtime(&self, cnum: CrateNum) -> bool; - fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy; - /// The name of the crate as it is referred to in source code of the current - /// crate. - fn crate_name(&self, cnum: CrateNum) -> Symbol; - /// The name of the crate as it is stored in the crate's metadata. - fn original_crate_name(&self, cnum: CrateNum) -> Symbol; - fn crate_hash(&self, cnum: CrateNum) -> Svh; - fn crate_disambiguator(&self, cnum: CrateNum) -> Symbol; - fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option; - fn derive_registrar_fn(&self, cnum: CrateNum) -> Option; - fn native_libraries(&self, cnum: CrateNum) -> Vec; - fn exported_symbols(&self, cnum: CrateNum) -> Vec; - fn is_no_builtins(&self, cnum: CrateNum) -> bool; - // resolve fn def_key(&self, def: DefId) -> DefKey; fn def_path(&self, def: DefId) -> hir_map::DefPath; fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash; fn def_path_table(&self, cnum: CrateNum) -> Rc; - fn struct_field_names(&self, def: DefId) -> Vec; - fn item_children(&self, did: DefId, sess: &Session) -> Vec; - fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro; - // misc. metadata - fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> &'tcx hir::Body; + // "queries" used in resolve that aren't tracked for incremental compilation + fn visibility_untracked(&self, def: DefId) -> ty::Visibility; + fn export_macros_untracked(&self, cnum: CrateNum); + fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind; + fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; + fn struct_field_names_untracked(&self, def: DefId) -> Vec; + fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec; + fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro; + fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option; + fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics; + fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem; + fn postorder_cnums_untracked(&self) -> Vec; // This is basically a 1-based range of ints, which is a little // silly - I may fix that. - fn crates(&self) -> Vec; - fn used_libraries(&self) -> Vec; - fn used_link_args(&self) -> Vec; + fn crates_untracked(&self) -> Vec; // utility functions - fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>; - fn used_crate_source(&self, cnum: CrateNum) -> CrateSource; - fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &LinkMeta, @@ -336,57 +302,18 @@ impl CrateStore for DummyCrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc { bug!("crate_data_as_rc_any") } // item info - fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") } - fn visible_parent_map<'a>(&'a self, session: &Session) - -> ::std::cell::Ref<'a, DefIdMap> - { - bug!("visible_parent_map") - } - fn item_generics_cloned(&self, def: DefId) -> ty::Generics + fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") } + fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics { bug!("item_generics_cloned") } - // trait info - fn implementations_of_trait(&self, filter: Option) -> Vec { vec![] } - - // impl info - fn impl_defaultness(&self, def: DefId) -> hir::Defaultness { bug!("impl_defaultness") } - // trait/impl-item info - fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem + fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem { bug!("associated_item_cloned") } - // flags - fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false } - fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false } - // crate metadata - fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> - { bug!("lang_items") } - fn missing_lang_items(&self, cnum: CrateNum) -> Vec - { bug!("missing_lang_items") } - fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") } - fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") } - fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") } - fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { bug!("is_profiler_runtime") } - fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") } - fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { - bug!("panic_strategy") - } - fn crate_name(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") } - fn original_crate_name(&self, cnum: CrateNum) -> Symbol { - bug!("original_crate_name") - } - fn crate_hash(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") } - fn crate_disambiguator(&self, cnum: CrateNum) - -> Symbol { bug!("crate_disambiguator") } - fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option - { bug!("plugin_registrar_fn") } - fn derive_registrar_fn(&self, cnum: CrateNum) -> Option - { bug!("derive_registrar_fn") } - fn native_libraries(&self, cnum: CrateNum) -> Vec - { bug!("native_libraries") } - fn exported_symbols(&self, cnum: CrateNum) -> Vec { bug!("exported_symbols") } - fn is_no_builtins(&self, cnum: CrateNum) -> bool { bug!("is_no_builtins") } + fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") } + fn export_macros_untracked(&self, cnum: CrateNum) { bug!("export_macros") } + fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") } // resolve fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") } @@ -399,29 +326,18 @@ impl CrateStore for DummyCrateStore { fn def_path_table(&self, cnum: CrateNum) -> Rc { bug!("def_path_table") } - fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } - fn item_children(&self, did: DefId, sess: &Session) -> Vec { + fn struct_field_names_untracked(&self, def: DefId) -> Vec { + bug!("struct_field_names") + } + fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec { bug!("item_children") } - fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") } + fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") } - // misc. metadata - fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> &'tcx hir::Body { - bug!("item_body") - } - - // This is basically a 1-based range of ints, which is a little - // silly - I may fix that. - fn crates(&self) -> Vec { vec![] } - fn used_libraries(&self) -> Vec { vec![] } - fn used_link_args(&self) -> Vec { vec![] } + fn crates_untracked(&self) -> Vec { vec![] } // utility functions - fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> - { vec![] } - fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") } - fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { None } + fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option { None } fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &LinkMeta, @@ -430,6 +346,7 @@ impl CrateStore for DummyCrateStore { bug!("encode_metadata") } fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } + fn postorder_cnums_untracked(&self) -> Vec { bug!("postorder_cnums_untracked") } // access to the metadata loader fn metadata_loader(&self) -> &MetadataLoader { bug!("metadata_loader") } @@ -439,3 +356,47 @@ pub trait CrateLoader { fn process_item(&mut self, item: &ast::Item, defs: &Definitions); fn postprocess(&mut self, krate: &ast::Crate); } + +// This method is used when generating the command line to pass through to +// system linker. The linker expects undefined symbols on the left of the +// command line to be defined in libraries on the right, not the other way +// around. For more info, see some comments in the add_used_library function +// below. +// +// In order to get this left-to-right dependency ordering, we perform a +// topological sort of all crates putting the leaves at the right-most +// positions. +pub fn used_crates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> { + let mut libs = tcx.crates() + .iter() + .cloned() + .filter_map(|cnum| { + if tcx.dep_kind(cnum).macros_only() { + return None + } + let source = tcx.used_crate_source(cnum); + let path = match prefer { + LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0), + LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0), + }; + let path = match path { + Some(p) => LibSource::Some(p), + None => { + if source.rmeta.is_some() { + LibSource::MetadataOnly + } else { + LibSource::None + } + } + }; + Some((cnum, path)) + }) + .collect::>(); + let mut ordering = tcx.postorder_cnums(LOCAL_CRATE); + Rc::make_mut(&mut ordering).reverse(); + libs.sort_by_key(|&(a, _)| { + ordering.iter().position(|x| *x == a) + }); + libs +} diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index b8624722692e9..d79e90690cac2 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -469,7 +469,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool { let field_type = self.tcx.type_of(self.tcx.hir.local_def_id(field.id)); let is_marker_field = match field_type.ty_to_def_id() { - Some(def_id) => self.tcx.lang_items.items().iter().any(|item| *item == Some(def_id)), + Some(def_id) => self.tcx.lang_items().items().iter().any(|item| *item == Some(def_id)), _ => false }; !field.is_positional() diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 837ab4fd4a3cc..1c7d0b76a643e 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -66,7 +66,7 @@ use hir::def_id::CrateNum; use session; use session::config; use ty::TyCtxt; -use middle::cstore::DepKind; +use middle::cstore::{self, DepKind}; use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic}; use util::nodemap::FxHashMap; use rustc_back::PanicStrategy; @@ -132,12 +132,12 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let Some(v) = attempt_static(tcx) { return v; } - for cnum in sess.cstore.crates() { - if sess.cstore.dep_kind(cnum).macros_only() { continue } - let src = sess.cstore.used_crate_source(cnum); + for &cnum in tcx.crates().iter() { + if tcx.dep_kind(cnum).macros_only() { continue } + let src = tcx.used_crate_source(cnum); if src.rlib.is_some() { continue } sess.err(&format!("dependency `{}` not found in rlib format", - sess.cstore.crate_name(cnum))); + tcx.crate_name(cnum))); } return Vec::new(); } @@ -165,24 +165,23 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Sweep all crates for found dylibs. Add all dylibs, as well as their // dependencies, ensuring there are no conflicts. The only valid case for a // dependency to be relied upon twice is for both cases to rely on a dylib. - for cnum in sess.cstore.crates() { - if sess.cstore.dep_kind(cnum).macros_only() { continue } - let name = sess.cstore.crate_name(cnum); - let src = sess.cstore.used_crate_source(cnum); + for &cnum in tcx.crates().iter() { + if tcx.dep_kind(cnum).macros_only() { continue } + let name = tcx.crate_name(cnum); + let src = tcx.used_crate_source(cnum); if src.dylib.is_some() { info!("adding dylib: {}", name); - add_library(sess, cnum, RequireDynamic, &mut formats); - let deps = tcx.dylib_dependency_formats(cnum.as_def_id()); + add_library(tcx, cnum, RequireDynamic, &mut formats); + let deps = tcx.dylib_dependency_formats(cnum); for &(depnum, style) in deps.iter() { - info!("adding {:?}: {}", style, - sess.cstore.crate_name(depnum)); - add_library(sess, depnum, style, &mut formats); + info!("adding {:?}: {}", style, tcx.crate_name(depnum)); + add_library(tcx, depnum, style, &mut formats); } } } // Collect what we've got so far in the return vector. - let last_crate = sess.cstore.crates().len(); + let last_crate = tcx.crates().len(); let mut ret = (1..last_crate+1).map(|cnum| { match formats.get(&CrateNum::new(cnum)) { Some(&RequireDynamic) => Linkage::Dynamic, @@ -196,14 +195,14 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // // If the crate hasn't been included yet and it's not actually required // (e.g. it's an allocator) then we skip it here as well. - for cnum in sess.cstore.crates() { - let src = sess.cstore.used_crate_source(cnum); + for &cnum in tcx.crates().iter() { + let src = tcx.used_crate_source(cnum); if src.dylib.is_none() && !formats.contains_key(&cnum) && - sess.cstore.dep_kind(cnum) == DepKind::Explicit { + tcx.dep_kind(cnum) == DepKind::Explicit { assert!(src.rlib.is_some() || src.rmeta.is_some()); - info!("adding staticlib: {}", sess.cstore.crate_name(cnum)); - add_library(sess, cnum, RequireStatic, &mut formats); + info!("adding staticlib: {}", tcx.crate_name(cnum)); + add_library(tcx, cnum, RequireStatic, &mut formats); ret[cnum.as_usize() - 1] = Linkage::Static; } } @@ -215,7 +214,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Things like allocators and panic runtimes may not have been activated // quite yet, so do so here. activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret, - &|cnum| tcx.is_panic_runtime(cnum.as_def_id())); + &|cnum| tcx.is_panic_runtime(cnum)); activate_injected_allocator(sess, &mut ret); // When dylib B links to dylib A, then when using B we must also link to A. @@ -226,7 +225,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // making sure that everything is available in the requested format. for (cnum, kind) in ret.iter().enumerate() { let cnum = CrateNum::new(cnum + 1); - let src = sess.cstore.used_crate_source(cnum); + let src = tcx.used_crate_source(cnum); match *kind { Linkage::NotLinked | Linkage::IncludedFromDylib => {} @@ -237,7 +236,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Linkage::Static => "rlib", _ => "dylib", }; - let name = sess.cstore.crate_name(cnum); + let name = tcx.crate_name(cnum); sess.err(&format!("crate `{}` required to be available in {}, \ but it was not available in this form", name, kind)); @@ -248,7 +247,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return ret; } -fn add_library(sess: &session::Session, +fn add_library(tcx: TyCtxt, cnum: CrateNum, link: LinkagePreference, m: &mut FxHashMap) { @@ -262,8 +261,8 @@ fn add_library(sess: &session::Session, // This error is probably a little obscure, but I imagine that it // can be refined over time. if link2 != link || link == RequireStatic { - sess.struct_err(&format!("cannot satisfy dependencies so `{}` only \ - shows up once", sess.cstore.crate_name(cnum))) + tcx.sess.struct_err(&format!("cannot satisfy dependencies so `{}` only \ + shows up once", tcx.crate_name(cnum))) .help("having upstream crates all available in one format \ will likely make this go away") .emit(); @@ -275,16 +274,16 @@ fn add_library(sess: &session::Session, fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { let sess = &tcx.sess; - let crates = sess.cstore.used_crates(RequireStatic); + let crates = cstore::used_crates(tcx, RequireStatic); if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) { return None } // All crates are available in an rlib format, so we're just going to link // everything in explicitly so long as it's actually required. - let last_crate = sess.cstore.crates().len(); + let last_crate = tcx.crates().len(); let mut ret = (1..last_crate+1).map(|cnum| { - if sess.cstore.dep_kind(CrateNum::new(cnum)) == DepKind::Explicit { + if tcx.dep_kind(CrateNum::new(cnum)) == DepKind::Explicit { Linkage::Static } else { Linkage::NotLinked @@ -295,7 +294,7 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { } let cnum = CrateNum::new(i + 1); - if tcx.is_panic_runtime(cnum.as_def_id()) { + if tcx.is_panic_runtime(cnum) { if let Some((prev, _)) = panic_runtime { - let prev_name = sess.cstore.crate_name(prev); - let cur_name = sess.cstore.crate_name(cnum); + let prev_name = tcx.crate_name(prev); + let cur_name = tcx.crate_name(cnum); sess.err(&format!("cannot link together two \ panic runtimes: {} and {}", prev_name, cur_name)); } - panic_runtime = Some((cnum, sess.cstore.panic_strategy(cnum))); + panic_runtime = Some((cnum, tcx.panic_strategy(cnum))); } } @@ -379,7 +378,7 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { sess.err(&format!("the linked panic runtime `{}` is \ not compiled with this crate's \ panic strategy `{}`", - sess.cstore.crate_name(cnum), + tcx.crate_name(cnum), desired_strategy.desc())); } @@ -395,8 +394,8 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { continue } let cnum = CrateNum::new(i + 1); - let found_strategy = sess.cstore.panic_strategy(cnum); - let is_compiler_builtins = sess.cstore.is_compiler_builtins(cnum); + let found_strategy = tcx.panic_strategy(cnum); + let is_compiler_builtins = tcx.is_compiler_builtins(cnum); if is_compiler_builtins || desired_strategy == found_strategy { continue } @@ -405,7 +404,7 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { panic strategy `{}` which is \ incompatible with this crate's \ strategy of `{}`", - sess.cstore.crate_name(cnum), + tcx.crate_name(cnum), found_strategy.desc(), desired_strategy.desc())); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 374b02125a1d0..73f78477b0a3f 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -211,9 +211,9 @@ enum OverloadedCallType { impl OverloadedCallType { fn from_trait_id(tcx: TyCtxt, trait_id: DefId) -> OverloadedCallType { for &(maybe_function_trait, overloaded_call_type) in &[ - (tcx.lang_items.fn_once_trait(), FnOnceOverloadedCall), - (tcx.lang_items.fn_mut_trait(), FnMutOverloadedCall), - (tcx.lang_items.fn_trait(), FnOverloadedCall) + (tcx.lang_items().fn_once_trait(), FnOnceOverloadedCall), + (tcx.lang_items().fn_mut_trait(), FnMutOverloadedCall), + (tcx.lang_items().fn_trait(), FnOverloadedCall) ] { match maybe_function_trait { Some(function_trait) if function_trait == trait_id => { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index ae3e3a30f371e..cb59d9870faac 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -21,10 +21,8 @@ pub use self::LangItem::*; -use hir::map as hir_map; -use session::Session; use hir::def_id::DefId; -use ty; +use ty::{self, TyCtxt}; use middle::weak_lang_items; use util::nodemap::FxHashMap; @@ -116,9 +114,7 @@ impl LanguageItems { struct LanguageItemCollector<'a, 'tcx: 'a> { items: LanguageItems, - hir_map: &'a hir_map::Map<'tcx>, - - session: &'a Session, + tcx: TyCtxt<'a, 'tcx, 'tcx>, item_refs: FxHashMap<&'static str, usize>, } @@ -129,10 +125,11 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { let item_index = self.item_refs.get(&*value.as_str()).cloned(); if let Some(item_index) = item_index { - self.collect_item(item_index, self.hir_map.local_def_id(item.id)) + let def_id = self.tcx.hir.local_def_id(item.id); + self.collect_item(item_index, def_id); } else { - let span = self.hir_map.span(item.id); - span_err!(self.session, span, E0522, + let span = self.tcx.hir.span(item.id); + span_err!(self.tcx.sess, span, E0522, "definition of an unknown language item: `{}`.", value); } @@ -149,45 +146,41 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { } impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { - pub fn new(session: &'a Session, hir_map: &'a hir_map::Map<'tcx>) - -> LanguageItemCollector<'a, 'tcx> { + fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItemCollector<'a, 'tcx> { let mut item_refs = FxHashMap(); $( item_refs.insert($name, $variant as usize); )* LanguageItemCollector { - session, - hir_map, + tcx, items: LanguageItems::new(), item_refs, } } - pub fn collect_item(&mut self, item_index: usize, - item_def_id: DefId) { + fn collect_item(&mut self, item_index: usize, item_def_id: DefId) { // Check for duplicates. match self.items.items[item_index] { Some(original_def_id) if original_def_id != item_def_id => { - let cstore = &self.session.cstore; let name = LanguageItems::item_name(item_index); - let mut err = match self.hir_map.span_if_local(item_def_id) { + let mut err = match self.tcx.hir.span_if_local(item_def_id) { Some(span) => struct_span_err!( - self.session, + self.tcx.sess, span, E0152, "duplicate lang item found: `{}`.", name), - None => self.session.struct_err(&format!( + None => self.tcx.sess.struct_err(&format!( "duplicate lang item in crate `{}`: `{}`.", - cstore.crate_name(item_def_id.krate), + self.tcx.crate_name(item_def_id.krate), name)), }; - if let Some(span) = self.hir_map.span_if_local(original_def_id) { + if let Some(span) = self.tcx.hir.span_if_local(original_def_id) { span_note!(&mut err, span, "first defined here."); } else { err.note(&format!("first defined in crate `{}`.", - cstore.crate_name(original_def_id.krate))); + self.tcx.crate_name(original_def_id.krate))); } err.emit(); } @@ -199,26 +192,6 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { // Matched. self.items.items[item_index] = Some(item_def_id); } - - pub fn collect_local_language_items(&mut self, krate: &hir::Crate) { - krate.visit_all_item_likes(self); - } - - pub fn collect_external_language_items(&mut self) { - let cstore = &self.session.cstore; - - for cnum in cstore.crates() { - for (index, item_index) in cstore.lang_items(cnum) { - let def_id = DefId { krate: cnum, index: index }; - self.collect_item(item_index, def_id); - } - } - } - - pub fn collect(&mut self, krate: &hir::Crate) { - self.collect_external_language_items(); - self.collect_local_language_items(krate); - } } pub fn extract(attrs: &[ast::Attribute]) -> Option { @@ -233,14 +206,17 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option { return None; } -pub fn collect_language_items(session: &Session, - map: &hir_map::Map) - -> LanguageItems { - let krate: &hir::Crate = map.krate(); - let mut collector = LanguageItemCollector::new(session, map); - collector.collect(krate); +pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems { + let mut collector = LanguageItemCollector::new(tcx); + for &cnum in tcx.crates().iter() { + for &(index, item_index) in tcx.defined_lang_items(cnum).iter() { + let def_id = DefId { krate: cnum, index: index }; + collector.collect_item(item_index, def_id); + } + } + tcx.hir.krate().visit_all_item_likes(&mut collector); let LanguageItemCollector { mut items, .. } = collector; - weak_lang_items::check_crate(krate, session, &mut items); + weak_lang_items::check_crate(tcx, &mut items); items } @@ -366,7 +342,7 @@ language_item_table! { impl<'a, 'tcx, 'gcx> ty::TyCtxt<'a, 'tcx, 'gcx> { pub fn require_lang_item(&self, lang_item: LangItem) -> DefId { - self.lang_items.require(lang_item).unwrap_or_else(|msg| { + self.lang_items().require(lang_item).unwrap_or_else(|msg| { self.sess.fatal(&msg) }) } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 3efc696f2a50a..33f4d4093fe17 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -392,7 +392,7 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> for (id, _) in &access_levels.map { reachable_context.worklist.push(*id); } - for item in tcx.lang_items.items().iter() { + for item in tcx.lang_items().items().iter() { if let Some(did) = *item { if let Some(node_id) = tcx.hir.as_local_node_id(did) { reachable_context.worklist.push(node_id); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index a8e98e53db394..c53e255f0cdab 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -978,7 +978,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } else { let cstore = &self.sess.cstore; self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| { - cstore.item_generics_cloned(def_id).types.into_iter().map(|def| { + cstore.item_generics_cloned_untracked(def_id).types.into_iter().map(|def| { def.object_lifetime_default }).collect() }) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index d2ed29a3a0ff6..ecf3aab05d858 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -15,20 +15,19 @@ pub use self::StabilityLevel::*; use lint; use hir::def::Def; -use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE}; +use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use ty::{self, TyCtxt}; use middle::privacy::AccessLevels; -use session::Session; use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; use syntax::ast; use syntax::ast::{NodeId, Attribute}; use syntax::feature_gate::{GateIssue, emit_feature_err, find_lang_feature_accepted_version}; use syntax::attr::{self, Stability, Deprecation}; -use util::nodemap::{DefIdMap, FxHashSet, FxHashMap}; +use util::nodemap::{FxHashSet, FxHashMap}; use hir; -use hir::{Item, Generics, StructField, Variant}; +use hir::{Item, Generics, StructField, Variant, HirId}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use std::mem::replace; @@ -63,19 +62,18 @@ pub struct DeprecationEntry { pub attr: Deprecation, /// The def id where the attr was originally attached. `None` for non-local /// `DefId`'s. - origin: Option, + origin: Option, } impl DeprecationEntry { - fn local(attr: Deprecation, id: DefId) -> DeprecationEntry { - assert!(id.is_local()); + fn local(attr: Deprecation, id: HirId) -> DeprecationEntry { DeprecationEntry { attr, - origin: Some(id.index), + origin: Some(id), } } - fn external(attr: Deprecation) -> DeprecationEntry { + pub fn external(attr: Deprecation) -> DeprecationEntry { DeprecationEntry { attr, origin: None, @@ -94,17 +92,14 @@ impl DeprecationEntry { pub struct Index<'tcx> { /// This is mostly a cache, except the stabilities of local items /// are filled by the annotator. - stab_map: DefIdMap>, - depr_map: DefIdMap>, + stab_map: FxHashMap, + depr_map: FxHashMap, /// Maps for each crate whether it is part of the staged API. staged_api: FxHashMap, /// Features enabled for this crate. active_features: FxHashSet, - - /// Features used by this crate. Updated before and during typeck. - used_features: FxHashMap } // A private tree-walker for producing an Index. @@ -178,8 +173,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } } - let def_id = self.tcx.hir.local_def_id(id); - self.index.stab_map.insert(def_id, Some(stab)); + let hir_id = self.tcx.hir.node_to_hir_id(id); + self.index.stab_map.insert(hir_id, stab); let orig_parent_stab = replace(&mut self.parent_stab, Some(stab)); visit_children(self); @@ -188,8 +183,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { debug!("annotate: not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { if stab.level.is_unstable() { - let def_id = self.tcx.hir.local_def_id(id); - self.index.stab_map.insert(def_id, Some(stab)); + let hir_id = self.tcx.hir.node_to_hir_id(id); + self.index.stab_map.insert(hir_id, stab); } } visit_children(self); @@ -209,8 +204,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { // -Zforce-unstable-if-unmarked is set. if let Some(stab) = self.parent_stab { if stab.level.is_unstable() { - let def_id = self.tcx.hir.local_def_id(id); - self.index.stab_map.insert(def_id, Some(stab)); + let hir_id = self.tcx.hir.node_to_hir_id(id); + self.index.stab_map.insert(hir_id, stab); } } @@ -220,16 +215,17 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } // `Deprecation` is just two pointers, no need to intern it - let def_id = self.tcx.hir.local_def_id(id); - let depr_entry = Some(DeprecationEntry::local(depr, def_id)); - self.index.depr_map.insert(def_id, depr_entry.clone()); + let hir_id = self.tcx.hir.node_to_hir_id(id); + let depr_entry = DeprecationEntry::local(depr, hir_id); + self.index.depr_map.insert(hir_id, depr_entry.clone()); - let orig_parent_depr = replace(&mut self.parent_depr, depr_entry); + let orig_parent_depr = replace(&mut self.parent_depr, + Some(depr_entry)); visit_children(self); self.parent_depr = orig_parent_depr; - } else if let parent_depr @ Some(_) = self.parent_depr.clone() { - let def_id = self.tcx.hir.local_def_id(id); - self.index.depr_map.insert(def_id, parent_depr); + } else if let Some(parent_depr) = self.parent_depr.clone() { + let hir_id = self.tcx.hir.node_to_hir_id(id); + self.index.depr_map.insert(hir_id, parent_depr); visit_children(self); } else { visit_children(self); @@ -322,10 +318,10 @@ struct MissingStabilityAnnotations<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> MissingStabilityAnnotations<'a, 'tcx> { fn check_missing_stability(&self, id: NodeId, span: Span) { - let def_id = self.tcx.hir.local_def_id(id); - let stab = self.tcx.stability.borrow().stab_map.get(&def_id).cloned(); + let hir_id = self.tcx.hir.node_to_hir_id(id); + let stab = self.tcx.stability().local_stability(hir_id); let is_error = !self.tcx.sess.opts.test && - (stab == None || stab == Some(None)) && + stab.is_none() && self.access_levels.is_reachable(id); if is_error { self.tcx.sess.span_err(span, "This node does not have a stability attribute"); @@ -386,60 +382,70 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } impl<'a, 'tcx> Index<'tcx> { - /// Construct the stability index for a crate being compiled. - pub fn build(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> { + let is_staged_api = + tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || + tcx.sess.features.borrow().staged_api; + let mut staged_api = FxHashMap(); + staged_api.insert(LOCAL_CRATE, is_staged_api); + let mut index = Index { + staged_api, + stab_map: FxHashMap(), + depr_map: FxHashMap(), + active_features: FxHashSet(), + }; + let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features; // Put the active features into a map for quick lookup - self.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect(); + index.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect(); + + { + let krate = tcx.hir.krate(); + let mut annotator = Annotator { + tcx, + index: &mut index, + parent_stab: None, + parent_depr: None, + in_trait_impl: false, + }; - let krate = tcx.hir.krate(); - let mut annotator = Annotator { - tcx, - index: self, - parent_stab: None, - parent_depr: None, - in_trait_impl: false, - }; + // If the `-Z force-unstable-if-unmarked` flag is passed then we provide + // a parent stability annotation which indicates that this is private + // with the `rustc_private` feature. This is intended for use when + // compiling librustc crates themselves so we can leverage crates.io + // while maintaining the invariant that all sysroot crates are unstable + // by default and are unable to be used. + if tcx.sess.opts.debugging_opts.force_unstable_if_unmarked { + let reason = "this crate is being loaded from the sysroot, and \ + unstable location; did you mean to load this crate \ + from crates.io via `Cargo.toml` instead?"; + let stability = tcx.intern_stability(Stability { + level: attr::StabilityLevel::Unstable { + reason: Some(Symbol::intern(reason)), + issue: 27812, + }, + feature: Symbol::intern("rustc_private"), + rustc_depr: None, + }); + annotator.parent_stab = Some(stability); + } - // If the `-Z force-unstable-if-unmarked` flag is passed then we provide - // a parent stability annotation which indicates that this is private - // with the `rustc_private` feature. This is intended for use when - // compiling librustc crates themselves so we can leverage crates.io - // while maintaining the invariant that all sysroot crates are unstable - // by default and are unable to be used. - if tcx.sess.opts.debugging_opts.force_unstable_if_unmarked { - let reason = "this crate is being loaded from the sysroot, and \ - unstable location; did you mean to load this crate \ - from crates.io via `Cargo.toml` instead?"; - let stability = tcx.intern_stability(Stability { - level: attr::StabilityLevel::Unstable { - reason: Some(Symbol::intern(reason)), - issue: 27812, - }, - feature: Symbol::intern("rustc_private"), - rustc_depr: None, - }); - annotator.parent_stab = Some(stability); + annotator.annotate(ast::CRATE_NODE_ID, + &krate.attrs, + krate.span, + AnnotationKind::Required, + |v| intravisit::walk_crate(v, krate)); } + return index + } - annotator.annotate(ast::CRATE_NODE_ID, &krate.attrs, krate.span, AnnotationKind::Required, - |v| intravisit::walk_crate(v, krate)); + pub fn local_stability(&self, id: HirId) -> Option<&'tcx Stability> { + self.stab_map.get(&id).cloned() } - pub fn new(sess: &Session) -> Index<'tcx> { - let is_staged_api = - sess.opts.debugging_opts.force_unstable_if_unmarked || - sess.features.borrow().staged_api; - let mut staged_api = FxHashMap(); - staged_api.insert(LOCAL_CRATE, is_staged_api); - Index { - staged_api, - stab_map: DefIdMap(), - depr_map: DefIdMap(), - active_features: FxHashSet(), - used_features: FxHashMap(), - } + pub fn local_deprecation_entry(&self, id: HirId) -> Option { + self.depr_map.get(&id).cloned() } } @@ -476,7 +482,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { _ => {} } - let visibility = self.sess.cstore.visibility(def_id); + let visibility = self.visibility(def_id); match visibility { // must check stability for pub items. @@ -547,10 +553,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return } - if let Some(&Stability { ref level, ref feature, .. }) = stability { - self.stability.borrow_mut().used_features.insert(feature.clone(), level.clone()); - } - // Issue 38412: private items lack stability markers. if self.skip_stability_check_due_to_privacy(def_id) { return @@ -558,7 +560,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match stability { Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => { - if self.stability.borrow().active_features.contains(feature) { + if self.stability().active_features.contains(feature) { return } @@ -610,7 +612,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // compiler-generated `extern crate` items have a dummy span. if item.span == DUMMY_SP { return } - let cnum = match self.tcx.sess.cstore.extern_mod_stmt_cnum(item.id) { + let hir_id = self.tcx.hir.node_to_hir_id(item.id); + let cnum = match self.tcx.extern_mod_stmt_cnum(hir_id) { Some(cnum) => cnum, None => return, }; @@ -671,49 +674,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - /// Lookup the stability for a node, loading external crate - /// metadata as necessary. - pub fn lookup_stability(self, id: DefId) -> Option<&'gcx Stability> { - if let Some(st) = self.stability.borrow().stab_map.get(&id) { - return *st; - } - - let st = self.lookup_stability_uncached(id); - self.stability.borrow_mut().stab_map.insert(id, st); - st - } - pub fn lookup_deprecation(self, id: DefId) -> Option { self.lookup_deprecation_entry(id).map(|depr| depr.attr) } - - pub fn lookup_deprecation_entry(self, id: DefId) -> Option { - if let Some(depr) = self.stability.borrow().depr_map.get(&id) { - return depr.clone(); - } - - let depr = self.lookup_deprecation_uncached(id); - self.stability.borrow_mut().depr_map.insert(id, depr.clone()); - depr - } - - fn lookup_stability_uncached(self, id: DefId) -> Option<&'gcx Stability> { - debug!("lookup(id={:?})", id); - if id.is_local() { - None // The stability cache is filled partially lazily - } else { - self.stability(id).map(|st| self.intern_stability(st)) - } - } - - fn lookup_deprecation_uncached(self, id: DefId) -> Option { - debug!("lookup(id={:?})", id); - if id.is_local() { - None // The stability cache is filled partially lazily - } else { - self.deprecation(id).map(DeprecationEntry::external) - } - } } /// Given the list of enabled features that were not language features (i.e. that @@ -724,7 +687,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); - if tcx.stability.borrow().staged_api[&LOCAL_CRATE] { + if tcx.stability().staged_api[&LOCAL_CRATE] { let krate = tcx.hir.krate(); let mut missing = MissingStabilityAnnotations { tcx, @@ -740,10 +703,6 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { = declared_lib_features.clone().into_iter().collect(); remaining_lib_features.remove(&Symbol::intern("proc_macro")); - fn format_stable_since_msg(version: &str) -> String { - format!("this feature has been stable since {}. Attribute no longer needed", version) - } - for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features { let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str()) .expect("unexpectedly couldn't find version feature was stabilized"); @@ -753,25 +712,23 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { &format_stable_since_msg(version)); } - let index = tcx.stability.borrow(); - for (used_lib_feature, level) in &index.used_features { - match remaining_lib_features.remove(used_lib_feature) { - Some(span) => { - if let &attr::StabilityLevel::Stable { since: ref version } = level { - tcx.lint_node(lint::builtin::STABLE_FEATURES, - ast::CRATE_NODE_ID, - span, - &format_stable_since_msg(&version.as_str())); - } - } - None => ( /* used but undeclared, handled during the previous ast visit */ ) - } - } + // FIXME(#44232) the `used_features` table no longer exists, so we don't + // lint about unknown or unused features. We should reenable + // this one day! + // + // let index = tcx.stability(); + // for (used_lib_feature, level) in &index.used_features { + // remaining_lib_features.remove(used_lib_feature); + // } + // + // for &span in remaining_lib_features.values() { + // tcx.lint_node(lint::builtin::UNUSED_FEATURES, + // ast::CRATE_NODE_ID, + // span, + // "unused or unknown feature"); + // } +} - for &span in remaining_lib_features.values() { - tcx.lint_node(lint::builtin::UNUSED_FEATURES, - ast::CRATE_NODE_ID, - span, - "unused or unknown feature"); - } +fn format_stable_since_msg(version: &str) -> String { + format!("this feature has been stable since {}. Attribute no longer needed", version) } diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index acb506878e6b6..50fb584070262 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -11,7 +11,6 @@ //! Validity checking for weak lang items use session::config; -use session::Session; use middle::lang_items; use rustc_back::PanicStrategy; @@ -21,38 +20,38 @@ use syntax_pos::Span; use hir::intravisit::{Visitor, NestedVisitorMap}; use hir::intravisit; use hir; +use ty::TyCtxt; use std::collections::HashSet; macro_rules! weak_lang_items { ($($name:ident, $item:ident, $sym:ident;)*) => ( -struct Context<'a> { - sess: &'a Session, +struct Context<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, items: &'a mut lang_items::LanguageItems, } /// Checks the crate for usage of weak lang items, returning a vector of all the /// language items required by this crate, but not defined yet. -pub fn check_crate(krate: &hir::Crate, - sess: &Session, - items: &mut lang_items::LanguageItems) { +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + items: &mut lang_items::LanguageItems) { // These are never called by user code, they're generated by the compiler. // They will never implicitly be added to the `missing` array unless we do // so here. if items.eh_personality().is_none() { items.missing.push(lang_items::EhPersonalityLangItem); } - if sess.target.target.options.custom_unwind_resume & + if tcx.sess.target.target.options.custom_unwind_resume & items.eh_unwind_resume().is_none() { items.missing.push(lang_items::EhUnwindResumeLangItem); } { - let mut cx = Context { sess: sess, items: items }; - krate.visit_all_item_likes(&mut cx.as_deep_visitor()); + let mut cx = Context { tcx, items }; + tcx.hir.krate().visit_all_item_likes(&mut cx.as_deep_visitor()); } - verify(sess, items); + verify(tcx, items); } pub fn link_name(attrs: &[ast::Attribute]) -> Option { @@ -65,10 +64,11 @@ pub fn link_name(attrs: &[ast::Attribute]) -> Option { }) } -fn verify(sess: &Session, items: &lang_items::LanguageItems) { +fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + items: &lang_items::LanguageItems) { // We only need to check for the presence of weak lang items if we're // emitting something that's not an rlib. - let needs_check = sess.crate_types.borrow().iter().any(|kind| { + let needs_check = tcx.sess.crate_types.borrow().iter().any(|kind| { match *kind { config::CrateTypeDylib | config::CrateTypeProcMacro | @@ -83,8 +83,8 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { } let mut missing = HashSet::new(); - for cnum in sess.cstore.crates() { - for item in sess.cstore.missing_lang_items(cnum) { + for &cnum in tcx.crates().iter() { + for &item in tcx.missing_lang_items(cnum).iter() { missing.insert(item); } } @@ -93,7 +93,7 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { // symbols. Other panic runtimes ensure that the relevant symbols are // available to link things together, but they're never exercised. let mut whitelisted = HashSet::new(); - if sess.panic_strategy() != PanicStrategy::Unwind { + if tcx.sess.panic_strategy() != PanicStrategy::Unwind { whitelisted.insert(lang_items::EhPersonalityLangItem); whitelisted.insert(lang_items::EhUnwindResumeLangItem); } @@ -102,28 +102,28 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { if missing.contains(&lang_items::$item) && !whitelisted.contains(&lang_items::$item) && items.$name().is_none() { - sess.err(&format!("language item required, but not found: `{}`", - stringify!($name))); + tcx.sess.err(&format!("language item required, but not found: `{}`", + stringify!($name))); } )* } -impl<'a> Context<'a> { +impl<'a, 'tcx> Context<'a, 'tcx> { fn register(&mut self, name: &str, span: Span) { $(if name == stringify!($name) { if self.items.$name().is_none() { self.items.missing.push(lang_items::$item); } } else)* { - span_err!(self.sess, span, E0264, + span_err!(self.tcx.sess, span, E0264, "unknown external lang item: `{}`", name); } } } -impl<'a, 'v> Visitor<'v> for Context<'a> { +impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { NestedVisitorMap::None } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index ce6da55fec36b..cfbd4ba055e3c 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -348,7 +348,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // // Currently I'm leaving it for what I need for `try`. if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { - method = self.tcx.item_name(item).as_str(); + method = self.tcx.item_name(item); flags.push(("from_method", None)); flags.push(("from_method", Some(&*method))); } @@ -919,7 +919,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // anyway. In that case, why inundate the user. if !self.tcx.sess.has_errors() { if - self.tcx.lang_items.sized_trait() + self.tcx.lang_items().sized_trait() .map_or(false, |sized_id| sized_id == trait_ref.def_id()) { self.need_type_info(body_id, span, self_ty); diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 9c04c013c4b1a..fd6d5a86a7fd1 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } fn generics_require_sized_self(self, def_id: DefId) -> bool { - let sized_def_id = match self.lang_items.sized_trait() { + let sized_def_id = match self.lang_items().sized_trait() { Some(def_id) => def_id, None => { return false; /* No Sized trait, can't require it! */ } }; diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 7dd3fc70b1e3f..94f6efcad4adc 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -227,7 +227,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { span: Span) -> Result<(), ErrorReported> { - let name = tcx.item_name(trait_def_id).as_str(); + let name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(trait_def_id); let parser = Parser::new(&self.0); let types = &generics.types; @@ -272,7 +272,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { trait_ref: ty::TraitRef<'tcx>) -> String { - let name = tcx.item_name(trait_ref.def_id).as_str(); + let name = tcx.item_name(trait_ref.def_id); let trait_str = tcx.item_path_str(trait_ref.def_id); let generics = tcx.generics_of(trait_ref.def_id); let generic_map = generics.types.iter().map(|param| { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 512cfee12b05f..1088ada667fbb 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1155,7 +1155,7 @@ fn confirm_generator_candidate<'cx, 'gcx, 'tcx>( let tcx = selcx.tcx(); - let gen_def_id = tcx.lang_items.gen_trait().unwrap(); + let gen_def_id = tcx.lang_items().gen_trait().unwrap(); // Note: we unwrap the binder here but re-create it below (1) let ty::Binder((trait_ref, yield_ty, return_ty)) = @@ -1252,7 +1252,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( fn_sig); // the `Output` associated type is declared on `FnOnce` - let fn_once_def_id = tcx.lang_items.fn_once_trait().unwrap(); + let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap(); // Note: we unwrap the binder here but re-create it below (1) let ty::Binder((trait_ref, ret_type)) = diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 726e5d83428ca..201395e6f9024 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1235,7 +1235,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // and applicable impls. There is a certain set of precedence rules here. let def_id = obligation.predicate.def_id(); - if self.tcx().lang_items.copy_trait() == Some(def_id) { + let lang_items = self.tcx().lang_items(); + if lang_items.copy_trait() == Some(def_id) { debug!("obligation self ty is {:?}", obligation.predicate.0.self_ty()); @@ -1246,16 +1247,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // For other types, we'll use the builtin rules. let copy_conditions = self.copy_conditions(obligation); self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?; - } else if self.tcx().lang_items.sized_trait() == Some(def_id) { + } else if lang_items.sized_trait() == Some(def_id) { // Sized is never implementable by end-users, it is // always automatically computed. let sized_conditions = self.sized_conditions(obligation); self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates)?; - } else if self.tcx().lang_items.unsize_trait() == Some(def_id) { + } else if lang_items.unsize_trait() == Some(def_id) { self.assemble_candidates_for_unsizing(obligation, &mut candidates); } else { - if self.tcx().lang_items.clone_trait() == Some(def_id) { + if lang_items.clone_trait() == Some(def_id) { // Same builtin conditions as `Copy`, i.e. every type which has builtin support // for `Copy` also has builtin support for `Clone`, + tuples and arrays of `Clone` // types have builtin support for `Clone`. @@ -1453,7 +1454,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { - if self.tcx().lang_items.gen_trait() != Some(obligation.predicate.def_id()) { + if self.tcx().lang_items().gen_trait() != Some(obligation.predicate.def_id()) { return Ok(()); } @@ -1490,7 +1491,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { - let kind = match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) { + let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.0.def_id()) { Some(k) => k, None => { return Ok(()); } }; @@ -1532,7 +1533,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { -> Result<(),SelectionError<'tcx>> { // We provide impl of all fn traits for fn pointers. - if self.tcx().lang_items.fn_trait_kind(obligation.predicate.def_id()).is_none() { + if self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()).is_none() { return Ok(()); } @@ -2266,16 +2267,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("confirm_builtin_candidate({:?}, {:?})", obligation, has_nested); + let lang_items = self.tcx().lang_items(); let obligations = if has_nested { let trait_def = obligation.predicate.def_id(); let conditions = match trait_def { - _ if Some(trait_def) == self.tcx().lang_items.sized_trait() => { + _ if Some(trait_def) == lang_items.sized_trait() => { self.sized_conditions(obligation) } - _ if Some(trait_def) == self.tcx().lang_items.copy_trait() => { + _ if Some(trait_def) == lang_items.copy_trait() => { self.copy_conditions(obligation) } - _ if Some(trait_def) == self.tcx().lang_items.clone_trait() => { + _ if Some(trait_def) == lang_items.clone_trait() => { self.copy_conditions(obligation) } _ => bug!("unexpected builtin trait {:?}", trait_def) @@ -2578,7 +2580,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("confirm_closure_candidate({:?})", obligation); - let kind = match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) { + let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.0.def_id()) { Some(k) => k, None => bug!("closure candidate for non-fn trait {:?}", obligation) }; diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 28abd1577dade..b0d6f4d5a3130 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -538,8 +538,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } None => { self.global_tcx() - .sess - .cstore .impl_defaultness(node_item_def_id) .is_default() } diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 5143666077955..349d77cfc1b24 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -110,8 +110,8 @@ impl<'a, 'gcx, 'tcx> OverloadedDeref<'tcx> { pub fn method_call(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, source: Ty<'tcx>) -> (DefId, &'tcx Substs<'tcx>) { let trait_def_id = match self.mutbl { - hir::MutImmutable => tcx.lang_items.deref_trait(), - hir::MutMutable => tcx.lang_items.deref_mut_trait() + hir::MutImmutable => tcx.lang_items().deref_trait(), + hir::MutMutable => tcx.lang_items().deref_mut_trait() }; let method_def_id = tcx.associated_items(trait_def_id.unwrap()) .find(|m| m.kind == ty::AssociatedKind::Method).unwrap().def_id; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f475baf19949f..18f286ebf5576 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -23,7 +23,7 @@ use lint::{self, Lint}; use ich::{self, StableHashingContext, NodeIdHashingMode}; use middle::free_region::FreeRegionMap; use middle::lang_items; -use middle::resolve_lifetime; +use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use middle::stability; use mir::Mir; use mir::transform::Passes; @@ -33,7 +33,6 @@ use traits; use ty::{self, Ty, TypeAndMut}; use ty::{TyS, TypeVariants, Slice}; use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region}; -use hir::FreevarMap; use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; use ty::RegionKind; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; @@ -822,7 +821,7 @@ pub struct GlobalCtxt<'tcx> { /// Export map produced by name resolution. export_map: FxHashMap>>, - pub named_region_map: resolve_lifetime::NamedRegionMap, + named_region_map: NamedRegionMap, pub hir: hir_map::Map<'tcx>, @@ -837,11 +836,11 @@ pub struct GlobalCtxt<'tcx> { // Records the free variables refrenced by every closure // expression. Do not track deps for this, just recompute it from // scratch every time. - pub freevars: RefCell, + freevars: FxHashMap>>, - pub maybe_unused_trait_imports: NodeSet, + maybe_unused_trait_imports: FxHashSet, - pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, + maybe_unused_extern_crates: Vec<(HirId, Span)>, // Internal cache for metadata decoding. No need to track deps on this. pub rcache: RefCell>>, @@ -851,16 +850,11 @@ pub struct GlobalCtxt<'tcx> { pub inhabitedness_cache: RefCell, DefIdForest>>, - pub lang_items: middle::lang_items::LanguageItems, - /// Set of nodes which mark locals as mutable which end up getting used at /// some point. Local variable definitions not in this set can be warned /// about. pub used_mut_nodes: RefCell, - /// Maps any item's def-id to its stability index. - pub stability: RefCell>, - /// Caches the results of trait selection. This cache is used /// for things that do not have to do with the parameters in scope. pub selection_cache: traits::SelectionCache<'tcx>, @@ -909,30 +903,6 @@ impl<'tcx> GlobalCtxt<'tcx> { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn crate_name(self, cnum: CrateNum) -> Symbol { - if cnum == LOCAL_CRATE { - self.crate_name - } else { - self.sess.cstore.crate_name(cnum) - } - } - - pub fn original_crate_name(self, cnum: CrateNum) -> Symbol { - if cnum == LOCAL_CRATE { - self.crate_name.clone() - } else { - self.sess.cstore.original_crate_name(cnum) - } - } - - pub fn crate_disambiguator(self, cnum: CrateNum) -> Symbol { - if cnum == LOCAL_CRATE { - self.sess.local_crate_disambiguator() - } else { - self.sess.cstore.crate_disambiguator(cnum) - } - } - pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics { self.global_arenas.generics.alloc(generics) } @@ -1016,8 +986,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { resolutions: ty::Resolutions, named_region_map: resolve_lifetime::NamedRegionMap, hir: hir_map::Map<'tcx>, - lang_items: middle::lang_items::LanguageItems, - stability: stability::Index<'tcx>, crate_name: &str, f: F) -> R where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R @@ -1026,14 +994,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let interners = CtxtInterners::new(arena); let common_types = CommonTypes::new(&interners); let dep_graph = hir.dep_graph.clone(); - let max_cnum = s.cstore.crates().iter().map(|c| c.as_usize()).max().unwrap_or(0); + let max_cnum = s.cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0); let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); providers[LOCAL_CRATE] = local_providers; let def_path_hash_to_def_id = if s.opts.build_dep_graph() { let upstream_def_path_tables: Vec<(CrateNum, Rc<_>)> = s .cstore - .crates() + .crates_untracked() .iter() .map(|&cnum| (cnum, s.cstore.def_path_table(cnum))) .collect(); @@ -1070,26 +1038,50 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { global_interners: interners, dep_graph: dep_graph.clone(), types: common_types, - named_region_map, + named_region_map: NamedRegionMap { + defs: + named_region_map.defs + .into_iter() + .map(|(k, v)| (hir.node_to_hir_id(k), v)) + .collect(), + late_bound: + named_region_map.late_bound + .into_iter() + .map(|k| hir.node_to_hir_id(k)) + .collect(), + object_lifetime_defaults: + named_region_map.object_lifetime_defaults + .into_iter() + .map(|(k, v)| (hir.node_to_hir_id(k), Rc::new(v))) + .collect(), + }, trait_map: resolutions.trait_map.into_iter().map(|(k, v)| { (hir.node_to_hir_id(k), Rc::new(v)) }).collect(), export_map: resolutions.export_map.into_iter().map(|(k, v)| { (hir.node_to_hir_id(k), Rc::new(v)) }).collect(), + freevars: resolutions.freevars.into_iter().map(|(k, v)| { + (hir.node_to_hir_id(k), Rc::new(v)) + }).collect(), + maybe_unused_trait_imports: + resolutions.maybe_unused_trait_imports + .into_iter() + .map(|id| hir.node_to_hir_id(id)) + .collect(), + maybe_unused_extern_crates: + resolutions.maybe_unused_extern_crates + .into_iter() + .map(|(id, sp)| (hir.node_to_hir_id(id), sp)) + .collect(), hir, def_path_hash_to_def_id, maps: maps::Maps::new(providers), mir_passes, - freevars: RefCell::new(resolutions.freevars), - maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports, - maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates, rcache: RefCell::new(FxHashMap()), normalized_cache: RefCell::new(FxHashMap()), inhabitedness_cache: RefCell::new(FxHashMap()), - lang_items, used_mut_nodes: RefCell::new(NodeSet()), - stability: RefCell::new(stability), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), rvalue_promotable_to_static: RefCell::new(NodeMap()), @@ -1107,6 +1099,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let cname = self.crate_name(LOCAL_CRATE).as_str(); self.sess.consider_optimizing(&cname, msg) } + + pub fn lang_items(self) -> Rc { + // FIXME(#42293) Right now we insert a `with_ignore` node in the dep + // graph here to ignore the fact that `get_lang_items` below depends on + // the entire crate. For now this'll prevent false positives of + // recompiling too much when anything changes. + // + // Once red/green incremental compilation lands we should be able to + // remove this because while the crate changes often the lint level map + // will change rarely. + self.dep_graph.with_ignore(|| { + self.get_lang_items(LOCAL_CRATE) + }) + } + + pub fn stability(self) -> Rc> { + // FIXME(#42293) we should actually track this, but fails too many tests + // today. + self.dep_graph.with_ignore(|| { + self.stability_index(LOCAL_CRATE) + }) + } + + pub fn crates(self) -> Rc> { + self.all_crate_nums(LOCAL_CRATE) + } } impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { @@ -1994,19 +2012,52 @@ impl InternIteratorElement for Result { } } -fn in_scope_traits<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: HirId) - -> Option>> -{ - tcx.gcx.trait_map.get(&id).cloned() -} - -fn module_exports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: HirId) - -> Option>> -{ - tcx.gcx.export_map.get(&id).cloned() +struct NamedRegionMap { + defs: FxHashMap, + late_bound: FxHashSet, + object_lifetime_defaults: FxHashMap>>, } pub fn provide(providers: &mut ty::maps::Providers) { - providers.in_scope_traits = in_scope_traits; - providers.module_exports = module_exports; + // FIXME(#44234) - almost all of these queries have no sub-queries and + // therefore no actual inputs, they're just reading tables calculated in + // resolve! Does this work? Unsure! That's what the issue is about + providers.in_scope_traits = |tcx, id| tcx.gcx.trait_map.get(&id).cloned(); + providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned(); + providers.named_region = |tcx, id| tcx.gcx.named_region_map.defs.get(&id).cloned(); + providers.is_late_bound = |tcx, id| tcx.gcx.named_region_map.late_bound.contains(&id); + providers.object_lifetime_defaults = |tcx, id| { + tcx.gcx.named_region_map.object_lifetime_defaults.get(&id).cloned() + }; + providers.crate_name = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + tcx.crate_name + }; + providers.get_lang_items = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + Rc::new(middle::lang_items::collect(tcx)) + }; + providers.freevars = |tcx, id| tcx.gcx.freevars.get(&id).cloned(); + providers.maybe_unused_trait_import = |tcx, id| { + tcx.maybe_unused_trait_imports.contains(&id) + }; + providers.maybe_unused_extern_crates = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Rc::new(tcx.maybe_unused_extern_crates.clone()) + }; + + providers.stability_index = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Rc::new(stability::Index::new(tcx)) + }; + providers.lookup_stability = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + let id = tcx.hir.definitions().def_index_to_hir_id(id.index); + tcx.stability().local_stability(id) + }; + providers.lookup_deprecation_entry = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + let id = tcx.hir.definitions().def_index_to_hir_id(id.index); + tcx.stability().local_deprecation_entry(id) + }; } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index eadf80871fc95..d9d311b14a36e 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -13,6 +13,7 @@ use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use ty::{self, Ty, TyCtxt}; use syntax::ast; use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use std::cell::Cell; @@ -128,9 +129,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn try_push_visible_item_path(self, buffer: &mut T, external_def_id: DefId) -> bool where T: ItemPathBuffer { - let visible_parent_map = self.sess.cstore.visible_parent_map(self.sess); + let visible_parent_map = self.visible_parent_map(LOCAL_CRATE); - let (mut cur_def, mut cur_path) = (external_def_id, Vec::::new()); + let (mut cur_def, mut cur_path) = (external_def_id, Vec::::new()); loop { // If `cur_def` is a direct or injected extern crate, push the path to the crate // followed by the path to the item within the crate and return. @@ -138,12 +139,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match *self.extern_crate(cur_def) { Some(ref extern_crate) if extern_crate.direct => { self.push_item_path(buffer, extern_crate.def_id); - cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count(); + cur_path.iter().rev().map(|segment| buffer.push(&segment)).count(); return true; } None => { buffer.push(&self.crate_name(cur_def.krate).as_str()); - cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count(); + cur_path.iter().rev().map(|segment| buffer.push(&segment)).count(); return true; } _ => {}, @@ -152,7 +153,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { cur_path.push(self.sess.cstore.def_key(cur_def) .disambiguated_data.data.get_opt_name().unwrap_or_else(|| - Symbol::intern(""))); + Symbol::intern("").as_str())); match visible_parent_map.get(&cur_def) { Some(&def) => cur_def = def, None => return false, diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index cf21a66d51538..2348c4ae76731 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1344,7 +1344,7 @@ impl<'a, 'tcx> Layout { } else { let st = Struct::new(dl, &fields, &def.repr, kind, ty)?; - let non_zero = Some(def.did) == tcx.lang_items.non_zero(); + let non_zero = Some(def.did) == tcx.lang_items().non_zero(); Univariant { variant: st, non_zero: non_zero } }; return success(layout); @@ -2043,7 +2043,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 { return Ok(SizeSkeleton::Pointer { non_zero: non_zero || - Some(def.did) == tcx.lang_items.non_zero(), + Some(def.did) == tcx.lang_items().non_zero(), tail, }); } else { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 5a372dbf89fbf..48b92d101edb3 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -10,14 +10,19 @@ use dep_graph::{DepConstructor, DepNode, DepNodeIndex}; use errors::{Diagnostic, DiagnosticBuilder}; -use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex}; use hir::def::{Def, Export}; use hir::{self, TraitCandidate, HirId}; +use hir::svh::Svh; use lint; use middle::const_val; -use middle::cstore::{ExternCrate, LinkagePreference}; +use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary}; +use middle::cstore::{NativeLibraryKind, DepKind, CrateSource}; use middle::privacy::AccessLevels; use middle::region; +use middle::resolve_lifetime::{Region, ObjectLifetimeDefault}; +use middle::stability::{self, DeprecationEntry}; +use middle::lang_items::{LanguageItems, LangItem}; use mir; use mir::transform::{MirSuite, MirPassIndex}; use session::CompileResult; @@ -28,10 +33,11 @@ use ty::item_path; use ty::steal::Steal; use ty::subst::Substs; use ty::fast_reject::SimplifiedType; -use util::nodemap::{DefIdSet, NodeSet}; +use util::nodemap::{DefIdSet, NodeSet, DefIdMap}; use util::common::{profq_msg, ProfileQueriesMsg}; use rustc_data_structures::indexed_set::IdxSetBuf; +use rustc_back::PanicStrategy; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashMap; use std::cell::{RefCell, RefMut, Cell}; @@ -428,13 +434,13 @@ impl<'tcx> QueryDescription for queries::def_span<'tcx> { } -impl<'tcx> QueryDescription for queries::stability<'tcx> { +impl<'tcx> QueryDescription for queries::lookup_stability<'tcx> { fn describe(_: TyCtxt, _: DefId) -> String { bug!("stability") } } -impl<'tcx> QueryDescription for queries::deprecation<'tcx> { +impl<'tcx> QueryDescription for queries::lookup_deprecation_entry<'tcx> { fn describe(_: TyCtxt, _: DefId) -> String { bug!("deprecation") } @@ -509,31 +515,25 @@ impl<'tcx> QueryDescription for queries::is_const_fn<'tcx> { } impl<'tcx> QueryDescription for queries::dylib_dependency_formats<'tcx> { - fn describe(_: TyCtxt, _: DefId) -> String { + fn describe(_: TyCtxt, _: CrateNum) -> String { "dylib dependency formats of crate".to_string() } } -impl<'tcx> QueryDescription for queries::is_allocator<'tcx> { - fn describe(_: TyCtxt, _: DefId) -> String { - "checking if the crate is_allocator".to_string() - } -} - impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> { - fn describe(_: TyCtxt, _: DefId) -> String { + fn describe(_: TyCtxt, _: CrateNum) -> String { "checking if the crate is_panic_runtime".to_string() } } impl<'tcx> QueryDescription for queries::is_compiler_builtins<'tcx> { - fn describe(_: TyCtxt, _: DefId) -> String { + fn describe(_: TyCtxt, _: CrateNum) -> String { "checking if the crate is_compiler_builtins".to_string() } } impl<'tcx> QueryDescription for queries::has_global_allocator<'tcx> { - fn describe(_: TyCtxt, _: DefId) -> String { + fn describe(_: TyCtxt, _: CrateNum) -> String { "checking if the crate has_global_allocator".to_string() } } @@ -568,6 +568,198 @@ impl<'tcx> QueryDescription for queries::module_exports<'tcx> { } } +impl<'tcx> QueryDescription for queries::is_no_builtins<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("test whether a crate has #![no_builtins]") + } +} + +impl<'tcx> QueryDescription for queries::panic_strategy<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("query a crate's configured panic strategy") + } +} + +impl<'tcx> QueryDescription for queries::is_profiler_runtime<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("query a crate is #![profiler_runtime]") + } +} + +impl<'tcx> QueryDescription for queries::is_sanitizer_runtime<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("query a crate is #![sanitizer_runtime]") + } +} + +impl<'tcx> QueryDescription for queries::exported_symbols<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up the exported symbols of a crate") + } +} + +impl<'tcx> QueryDescription for queries::native_libraries<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up the native libraries of a linked crate") + } +} + +impl<'tcx> QueryDescription for queries::plugin_registrar_fn<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up the plugin registrar for a crate") + } +} + +impl<'tcx> QueryDescription for queries::derive_registrar_fn<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up the derive registrar for a crate") + } +} + +impl<'tcx> QueryDescription for queries::crate_disambiguator<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up the disambiguator a crate") + } +} + +impl<'tcx> QueryDescription for queries::crate_hash<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up the hash a crate") + } +} + +impl<'tcx> QueryDescription for queries::original_crate_name<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up the original name a crate") + } +} + +impl<'tcx> QueryDescription for queries::implementations_of_trait<'tcx> { + fn describe(_tcx: TyCtxt, _: (CrateNum, DefId)) -> String { + format!("looking up implementations of a trait in a crate") + } +} + +impl<'tcx> QueryDescription for queries::all_trait_implementations<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up all (?) trait implementations") + } +} + +impl<'tcx> QueryDescription for queries::link_args<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up link arguments for a crate") + } +} + +impl<'tcx> QueryDescription for queries::named_region<'tcx> { + fn describe(_tcx: TyCtxt, _: HirId) -> String { + format!("fetching info about a named region") + } +} + +impl<'tcx> QueryDescription for queries::is_late_bound<'tcx> { + fn describe(_tcx: TyCtxt, _: HirId) -> String { + format!("testing whether a lifetime is late bound") + } +} + +impl<'tcx> QueryDescription for queries::object_lifetime_defaults<'tcx> { + fn describe(_tcx: TyCtxt, _: HirId) -> String { + format!("fetching a list of ObjectLifetimeDefault for a lifetime") + } +} + +impl<'tcx> QueryDescription for queries::dep_kind<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("fetching what a dependency looks like") + } +} + +impl<'tcx> QueryDescription for queries::crate_name<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("fetching what a crate is named") + } +} + +impl<'tcx> QueryDescription for queries::extern_mod_stmt_cnum<'tcx> { + fn describe(_tcx: TyCtxt, _: HirId) -> String { + format!("looking up the CrateNum for an `extern mod` statement") + } +} + +impl<'tcx> QueryDescription for queries::get_lang_items<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("calculating the lang items map") + } +} + +impl<'tcx> QueryDescription for queries::defined_lang_items<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("calculating the lang items defined in a crate") + } +} + +impl<'tcx> QueryDescription for queries::missing_lang_items<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("calculating the missing lang items in a crate") + } +} + +impl<'tcx> QueryDescription for queries::visible_parent_map<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("calculating the visible parent map") + } +} + +impl<'tcx> QueryDescription for queries::missing_extern_crate_item<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("seeing if we're missing an `extern crate` item for this crate") + } +} + +impl<'tcx> QueryDescription for queries::used_crate_source<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking at the source for a crate") + } +} + +impl<'tcx> QueryDescription for queries::postorder_cnums<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("generating a postorder list of CrateNums") + } +} + +impl<'tcx> QueryDescription for queries::freevars<'tcx> { + fn describe(_tcx: TyCtxt, _: HirId) -> String { + format!("looking up free variables for a node") + } +} + +impl<'tcx> QueryDescription for queries::maybe_unused_trait_import<'tcx> { + fn describe(_tcx: TyCtxt, _: HirId) -> String { + format!("testing if a trait import is unused") + } +} + +impl<'tcx> QueryDescription for queries::maybe_unused_extern_crates<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up all possibly unused extern crates") + } +} + +impl<'tcx> QueryDescription for queries::stability_index<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("calculating the stability index for the local crate") + } +} + +impl<'tcx> QueryDescription for queries::all_crate_nums<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("fetching all foreign CrateNum instances") + } +} + // If enabled, send a message to the profile-queries thread macro_rules! profq_msg { ($tcx:expr, $msg:expr) => { @@ -1092,8 +1284,8 @@ define_maps! { <'tcx> [] fn describe_def: DescribeDef(DefId) -> Option, [] fn def_span: DefSpan(DefId) -> Span, - [] fn stability: Stability(DefId) -> Option, - [] fn deprecation: Deprecation(DefId) -> Option, + [] fn lookup_stability: LookupStability(DefId) -> Option<&'tcx attr::Stability>, + [] fn lookup_deprecation_entry: LookupDeprecationEntry(DefId) -> Option, [] fn item_attrs: ItemAttrs(DefId) -> Rc<[ast::Attribute]>, [] fn fn_arg_names: FnArgNames(DefId) -> Vec, [] fn impl_parent: ImplParent(DefId) -> Option, @@ -1125,21 +1317,72 @@ define_maps! { <'tcx> [] fn layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<&'tcx Layout, LayoutError<'tcx>>, - [] fn dylib_dependency_formats: DylibDepFormats(DefId) + [] fn dylib_dependency_formats: DylibDepFormats(CrateNum) -> Rc>, - [] fn is_allocator: IsAllocator(DefId) -> bool, - [] fn is_panic_runtime: IsPanicRuntime(DefId) -> bool, - [] fn is_compiler_builtins: IsCompilerBuiltins(DefId) -> bool, - [] fn has_global_allocator: HasGlobalAllocator(DefId) -> bool, + [] fn is_panic_runtime: IsPanicRuntime(CrateNum) -> bool, + [] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool, + [] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool, + [] fn is_sanitizer_runtime: IsSanitizerRuntime(CrateNum) -> bool, + [] fn is_profiler_runtime: IsProfilerRuntime(CrateNum) -> bool, + [] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy, + [] fn is_no_builtins: IsNoBuiltins(CrateNum) -> bool, [] fn extern_crate: ExternCrate(DefId) -> Rc>, - [] fn lint_levels: lint_levels(CrateNum) -> Rc, - [] fn specializes: specializes_node((DefId, DefId)) -> bool, [] fn in_scope_traits: InScopeTraits(HirId) -> Option>>, [] fn module_exports: ModuleExports(HirId) -> Option>>, + [] fn lint_levels: lint_levels_node(CrateNum) -> Rc, + + [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness, + [] fn exported_symbols: ExportedSymbols(CrateNum) -> Rc>, + [] fn native_libraries: NativeLibraries(CrateNum) -> Rc>, + [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option, + [] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option, + [] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> Symbol, + [] fn crate_hash: CrateHash(CrateNum) -> Svh, + [] fn original_crate_name: OriginalCrateName(CrateNum) -> Symbol, + + [] fn implementations_of_trait: implementations_of_trait_node((CrateNum, DefId)) + -> Rc>, + [] fn all_trait_implementations: AllTraitImplementations(CrateNum) + -> Rc>, + + [] fn is_dllimport_foreign_item: IsDllimportForeignItem(DefId) -> bool, + [] fn is_statically_included_foreign_item: IsStaticallyIncludedForeignItem(DefId) -> bool, + [] fn native_library_kind: NativeLibraryKind(DefId) + -> Option, + [] fn link_args: link_args_node(CrateNum) -> Rc>, + + [] fn named_region: NamedRegion(HirId) -> Option, + [] fn is_late_bound: IsLateBound(HirId) -> bool, + [] fn object_lifetime_defaults: ObjectLifetimeDefaults(HirId) + -> Option>>, + + [] fn visibility: Visibility(DefId) -> ty::Visibility, + [] fn dep_kind: DepKind(CrateNum) -> DepKind, + [] fn crate_name: CrateName(CrateNum) -> Symbol, + [] fn item_children: ItemChildren(DefId) -> Rc>, + [] fn extern_mod_stmt_cnum: ExternModStmtCnum(HirId) -> Option, + + [] fn get_lang_items: get_lang_items_node(CrateNum) -> Rc, + [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc>, + [] fn missing_lang_items: MissingLangItems(CrateNum) -> Rc>, + [] fn extern_const_body: ExternConstBody(DefId) -> &'tcx hir::Body, + [] fn visible_parent_map: visible_parent_map_node(CrateNum) + -> Rc>, + [] fn missing_extern_crate_item: MissingExternCrateItem(CrateNum) -> bool, + [] fn used_crate_source: UsedCrateSource(CrateNum) -> Rc, + [] fn postorder_cnums: postorder_cnums_node(CrateNum) -> Rc>, + + [] fn freevars: Freevars(HirId) -> Option>>, + [] fn maybe_unused_trait_import: MaybeUnusedTraitImport(HirId) -> bool, + [] fn maybe_unused_extern_crates: maybe_unused_extern_crates_node(CrateNum) + -> Rc>, + + [] fn stability_index: stability_index_node(CrateNum) -> Rc>, + [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Rc>, } fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { @@ -1212,10 +1455,44 @@ fn layout_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<' DepConstructor::Layout } -fn lint_levels<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { +fn lint_levels_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { DepConstructor::LintLevels } fn specializes_node<'tcx>((a, b): (DefId, DefId)) -> DepConstructor<'tcx> { DepConstructor::Specializes { impl1: a, impl2: b } } + +fn implementations_of_trait_node<'tcx>((krate, trait_id): (CrateNum, DefId)) + -> DepConstructor<'tcx> +{ + DepConstructor::ImplementationsOfTrait { krate, trait_id } +} + +fn link_args_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::LinkArgs +} + +fn get_lang_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::GetLangItems +} + +fn visible_parent_map_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::VisibleParentMap +} + +fn postorder_cnums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::PostorderCnums +} + +fn maybe_unused_extern_crates_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::MaybeUnusedExternCrates +} + +fn stability_index_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::StabilityIndex +} + +fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::AllCrateNums +} diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 1851e1b8d34bb..ef0d844be957f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1447,10 +1447,10 @@ impl<'a, 'gcx, 'tcx> AdtDef { if attr::contains_name(&attrs, "fundamental") { flags = flags | AdtFlags::IS_FUNDAMENTAL; } - if Some(did) == tcx.lang_items.phantom_data() { + if Some(did) == tcx.lang_items().phantom_data() { flags = flags | AdtFlags::IS_PHANTOM_DATA; } - if Some(did) == tcx.lang_items.owned_box() { + if Some(did) == tcx.lang_items().owned_box() { flags = flags | AdtFlags::IS_BOX; } match kind { @@ -1746,7 +1746,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { // we know that `T` is Sized and do not need to check // it on the impl. - let sized_trait = match tcx.lang_items.sized_trait() { + let sized_trait = match tcx.lang_items().sized_trait() { Some(x) => x, _ => return vec![ty] }; @@ -2206,11 +2206,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn item_name(self, id: DefId) -> ast::Name { + pub fn item_name(self, id: DefId) -> InternedString { if let Some(id) = self.hir.as_local_node_id(id) { - self.hir.name(id) + self.hir.name(id).as_str() } else if id.index == CRATE_DEF_INDEX { - self.sess.cstore.original_crate_name(id.krate) + self.original_crate_name(id.krate).as_str() } else { let def_key = self.sess.cstore.def_key(id); // The name of a StructCtor is that of its struct parent. @@ -2315,7 +2315,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let node_id = self.hir.as_local_node_id(impl_did).unwrap(); Ok(self.hir.span(node_id)) } else { - Err(self.sess.cstore.crate_name(impl_did.krate)) + Err(self.crate_name(impl_did.krate)) } } @@ -2340,9 +2340,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn with_freevars(self, fid: NodeId, f: F) -> T where F: FnOnce(&[hir::Freevar]) -> T, { - match self.freevars.borrow().get(&fid) { + let hir_id = self.hir.node_to_hir_id(fid); + match self.freevars(hir_id) { None => f(&[]), - Some(d) => f(&d[..]) + Some(d) => f(&d), } } } @@ -2510,6 +2511,18 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) } +fn crate_disambiguator<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + crate_num: CrateNum) -> Symbol { + assert_eq!(crate_num, LOCAL_CRATE); + tcx.sess.local_crate_disambiguator() +} + +fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + crate_num: CrateNum) -> Symbol { + assert_eq!(crate_num, LOCAL_CRATE); + tcx.crate_name.clone() +} + pub fn provide(providers: &mut ty::maps::Providers) { util::provide(providers); context::provide(providers); @@ -2521,6 +2534,8 @@ pub fn provide(providers: &mut ty::maps::Providers) { def_span, param_env, trait_of_item, + crate_disambiguator, + original_crate_name, trait_impls_of: trait_def::trait_impls_of_provider, ..*providers }; diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 9990472c6b4ca..3aadacfe826fd 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -141,13 +141,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_id: DefId) -> Rc { - let remote_impls = if trait_id.is_local() { - // Traits defined in the current crate can't have impls in upstream - // crates, so we don't bother querying the cstore. - Vec::new() - } else { - tcx.sess.cstore.implementations_of_trait(Some(trait_id)) - }; + let mut remote_impls = Vec::new(); + + // Traits defined in the current crate can't have impls in upstream + // crates, so we don't bother querying the cstore. + if !trait_id.is_local() { + for &cnum in tcx.crates().iter() { + let impls = tcx.implementations_of_trait((cnum, trait_id)); + remote_impls.extend(impls.iter().cloned()); + } + } let mut blanket_impls = Vec::new(); let mut non_blanket_impls = FxHashMap(); diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 4e4c7b107c429..f21fc8414e78b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -418,7 +418,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { adt_did: DefId, validate: &mut FnMut(Self, DefId) -> Result<(), ErrorReported> ) -> Option { - let drop_trait = if let Some(def_id) = self.lang_items.drop_trait() { + let drop_trait = if let Some(def_id) = self.lang_items().drop_trait() { def_id } else { return None; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index cc581b07de5fc..c48bd5ac5be26 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -159,7 +159,7 @@ pub fn parameterized(f: &mut fmt::Formatter, } write!(f, "{}", tcx.item_path_str(path_def_id))?; - Ok(tcx.lang_items.fn_trait_kind(path_def_id)) + Ok(tcx.lang_items().fn_trait_kind(path_def_id)) })?; if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { @@ -802,7 +802,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { for predicate in bounds.predicates { if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() { + if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() { is_sized = true; continue; } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c7def0b834cfd..ea6e1d4cddcca 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -327,7 +327,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, ConstEvalErr { span: e.span, kind: LayoutError(err) } }) }; - match &tcx.item_name(def_id).as_str()[..] { + match &tcx.item_name(def_id)[..] { "size_of" => { let size = layout_of(substs.type_at(0))?.size(tcx); return Ok(Integral(Usize(ConstUsize::new(size.bytes(), @@ -354,7 +354,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, } } else { if tcx.is_const_fn(def_id) { - tcx.sess.cstore.item_body(tcx, def_id) + tcx.extern_const_body(def_id) } else { signal!(e, TypeckError) } @@ -774,7 +774,7 @@ fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.mir_const_qualif(def_id); tcx.hir.body(tcx.hir.body_owned_by(id)) } else { - tcx.sess.cstore.item_body(tcx, def_id) + tcx.extern_const_body(def_id) }; ConstContext::new(tcx, key.param_env.and(substs), tables).eval(&body.value) } diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index ba79f775ef73d..5e1fbbc9ca2cf 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -609,7 +609,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { self.tcx.hir.body(self.tcx.hir.body_owned_by(id)) } else { - self.tcx.sess.cstore.item_body(self.tcx, def_id) + self.tcx.extern_const_body(def_id) }; let pat = self.lower_const_expr(&body.value, pat_id, span); self.tables = old_tables; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 000d89241a427..b4dde2120a840 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -694,7 +694,6 @@ pub fn phase_2_configure_and_expand(sess: &Session, // this back at some point. let _ignore = sess.dep_graph.in_ignore(); let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name); - crate_loader.preprocess(&krate); let resolver_arenas = Resolver::arenas(); let mut resolver = Resolver::new(sess, &krate, @@ -914,12 +913,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let time_passes = sess.time_passes(); - let lang_items = time(time_passes, "language item collection", || { - sess.track_errors(|| { - middle::lang_items::collect_language_items(&sess, &hir_map) - }) - })?; - let named_region_map = time(time_passes, "lifetime resolution", || middle::resolve_lifetime::krate(sess, &hir_map))?; @@ -941,8 +934,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, "static item recursion checking", || static_recursion::check_crate(sess, &hir_map))?; - let index = stability::Index::new(&sess); - let mut local_providers = ty::maps::Providers::default(); borrowck::provide(&mut local_providers); mir::provide(&mut local_providers); @@ -1029,8 +1020,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, resolutions, named_region_map, hir_map, - lang_items, - index, name, |tcx| { let incremental_hashes_map = @@ -1042,10 +1031,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, "load_dep_graph", || rustc_incremental::load_dep_graph(tcx, &incremental_hashes_map)); - time(time_passes, "stability index", || { - tcx.stability.borrow_mut().build(tcx) - }); - time(time_passes, "stability checking", || stability::check_unstable_api_usage(tcx)); diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 552130e8a4703..de710942ca189 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -15,11 +15,9 @@ use rustc::dep_graph::DepGraph; use rustc_lint; use rustc_resolve::MakeGlobMap; use rustc_trans; -use rustc::middle::lang_items; use rustc::middle::free_region::FreeRegionMap; use rustc::middle::region; use rustc::middle::resolve_lifetime; -use rustc::middle::stability; use rustc::ty::subst::{Kind, Subst}; use rustc::traits::{ObligationCause, Reveal}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -140,9 +138,7 @@ fn test_env(source_string: &str, let hir_map = hir_map::map_crate(&mut hir_forest, defs); // run just enough stuff to build a tcx: - let lang_items = lang_items::collect_language_items(&sess, &hir_map); let named_region_map = resolve_lifetime::krate(&sess, &hir_map); - let index = stability::Index::new(&sess); TyCtxt::create_and_enter(&sess, ty::maps::Providers::default(), ty::maps::Providers::default(), @@ -152,8 +148,6 @@ fn test_env(source_string: &str, resolutions, named_region_map.unwrap(), hir_map, - lang_items, - index, "test_crate", |tcx| { tcx.infer_ctxt().enter(|infcx| { diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 28d33d9528692..434c82095bd9a 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -632,7 +632,7 @@ pub fn find_metadata_hashes_for(tcx: TyCtxt, cnum: CrateNum) -> Option } }; - let target_svh = tcx.sess.cstore.crate_hash(cnum); + let target_svh = tcx.crate_hash(cnum); let target_svh = base_n::encode(target_svh.as_u64(), INT_ENCODE_BASE); let sub_dir = find_metadata_hashes_iter(&target_svh, dir_entries.filter_map(|e| { diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index 9d762a74bfe67..44d6788c77365 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { fn load_data(&mut self, cnum: CrateNum) { debug!("load_data(cnum={})", cnum); - let svh = self.tcx.sess.cstore.crate_hash(cnum); + let svh = self.tcx.crate_hash(cnum); let old = self.crate_hashes.insert(cnum, svh); debug!("load_data: svh={}", svh); assert!(old.is_none(), "loaded data for crate {:?} twice", cnum); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 780d34d570170..e0d82f3dafc0d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -547,7 +547,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { _ => return, } - let debug = match cx.tcx.lang_items.debug_trait() { + let debug = match cx.tcx.lang_items().debug_trait() { Some(debug) => debug, None => return, }; @@ -1063,8 +1063,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PluginAsLibrary { _ => return, }; - let prfn = match cx.sess().cstore.extern_mod_stmt_cnum(it.id) { - Some(cnum) => cx.sess().cstore.plugin_registrar_fn(cnum), + let hir_id = cx.tcx.hir.node_to_hir_id(it.id); + let prfn = match cx.tcx.extern_mod_stmt_cnum(hir_id) { + Some(cnum) => cx.tcx.plugin_registrar_fn(cnum), None => { // Probably means we aren't linking the crate for some reason. // diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 4c25d03b441ea..7f018a7f5a6d5 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -12,6 +12,7 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use locator::{self, CratePaths}; +use native_libs::relevant_lib; use schema::{CrateRoot, Tracked}; use rustc::hir::def_id::{CrateNum, DefIndex}; @@ -23,10 +24,9 @@ use rustc::session::config::{Sanitizer, self}; use rustc_back::PanicStrategy; use rustc::session::search_paths::PathKind; use rustc::middle; -use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate}; +use rustc::middle::cstore::{validate_crate_name, ExternCrate}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; -use rustc::middle::cstore::NativeLibrary; use rustc::hir::map::Definitions; use std::cell::{RefCell, Cell}; @@ -36,10 +36,8 @@ use std::rc::Rc; use std::{cmp, fs}; use syntax::ast; -use syntax::abi::Abi; use syntax::attr; use syntax::ext::base::SyntaxExtension; -use syntax::feature_gate::{self, GateIssue}; use syntax::symbol::Symbol; use syntax::visit; use syntax_pos::{Span, DUMMY_SP}; @@ -81,56 +79,6 @@ struct ExternCrateInfo { dep_kind: DepKind, } -fn register_native_lib(sess: &Session, - cstore: &CStore, - span: Option, - lib: NativeLibrary) { - if lib.name.as_str().is_empty() { - match span { - Some(span) => { - struct_span_err!(sess, span, E0454, - "#[link(name = \"\")] given with empty name") - .span_label(span, "empty name given") - .emit(); - } - None => { - sess.err("empty library name given via `-l`"); - } - } - return - } - let is_osx = sess.target.target.options.is_like_osx; - if lib.kind == cstore::NativeFramework && !is_osx { - let msg = "native frameworks are only available on macOS targets"; - match span { - Some(span) => span_err!(sess, span, E0455, "{}", msg), - None => sess.err(msg), - } - } - if lib.cfg.is_some() && !sess.features.borrow().link_cfg { - feature_gate::emit_feature_err(&sess.parse_sess, - "link_cfg", - span.unwrap(), - GateIssue::Language, - "is feature gated"); - } - if lib.kind == cstore::NativeStaticNobundle && !sess.features.borrow().static_nobundle { - feature_gate::emit_feature_err(&sess.parse_sess, - "static_nobundle", - span.unwrap(), - GateIssue::Language, - "kind=\"static-nobundle\" is feature gated"); - } - cstore.add_used_library(lib); -} - -fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { - match lib.cfg { - Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None), - None => true, - } -} - // Extra info about a crate loaded for plugins or exported macros. struct ExtensionCrate { metadata: PMDSource, @@ -218,7 +166,7 @@ impl<'a> CrateLoader<'a> { // We're also sure to compare *paths*, not actual byte slices. The // `source` stores paths which are normalized which may be different // from the strings on the command line. - let source = self.cstore.used_crate_source(cnum); + let source = &self.cstore.get_crate_data(cnum).source; if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) { let found = locs.iter().any(|l| { let l = fs::canonicalize(l).ok(); @@ -721,33 +669,6 @@ impl<'a> CrateLoader<'a> { } } - fn get_foreign_items_of_kind(&self, kind: cstore::NativeLibraryKind) -> Vec { - let mut items = vec![]; - let libs = self.cstore.get_used_libraries(); - for lib in libs.borrow().iter() { - if relevant_lib(self.sess, lib) && lib.kind == kind { - items.extend(&lib.foreign_items); - } - } - items - } - - fn register_statically_included_foreign_items(&mut self) { - for id in self.get_foreign_items_of_kind(cstore::NativeStatic) { - self.cstore.add_statically_included_foreign_item(id); - } - for id in self.get_foreign_items_of_kind(cstore::NativeStaticNobundle) { - self.cstore.add_statically_included_foreign_item(id); - } - } - - fn register_dllimport_foreign_items(&mut self) { - let mut dllimports = self.cstore.dllimport_foreign_items.borrow_mut(); - for id in self.get_foreign_items_of_kind(cstore::NativeUnknown) { - dllimports.insert(id); - } - } - fn inject_panic_runtime(&mut self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. @@ -1152,84 +1073,6 @@ impl<'a> CrateLoader<'a> { } } -impl<'a> CrateLoader<'a> { - pub fn preprocess(&mut self, krate: &ast::Crate) { - for attr in &krate.attrs { - if attr.path == "link_args" { - if let Some(linkarg) = attr.value_str() { - self.cstore.add_used_link_args(&linkarg.as_str()); - } - } - } - } - - fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod, - definitions: &Definitions) { - if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic { - return; - } - - // First, add all of the custom #[link_args] attributes - for m in i.attrs.iter().filter(|a| a.check_name("link_args")) { - if let Some(linkarg) = m.value_str() { - self.cstore.add_used_link_args(&linkarg.as_str()); - } - } - - // Next, process all of the #[link(..)]-style arguments - for m in i.attrs.iter().filter(|a| a.check_name("link")) { - let items = match m.meta_item_list() { - Some(item) => item, - None => continue, - }; - let kind = items.iter().find(|k| { - k.check_name("kind") - }).and_then(|a| a.value_str()).map(Symbol::as_str); - let kind = match kind.as_ref().map(|s| &s[..]) { - Some("static") => cstore::NativeStatic, - Some("static-nobundle") => cstore::NativeStaticNobundle, - Some("dylib") => cstore::NativeUnknown, - Some("framework") => cstore::NativeFramework, - Some(k) => { - struct_span_err!(self.sess, m.span, E0458, - "unknown kind: `{}`", k) - .span_label(m.span, "unknown kind").emit(); - cstore::NativeUnknown - } - None => cstore::NativeUnknown - }; - let n = items.iter().find(|n| { - n.check_name("name") - }).and_then(|a| a.value_str()); - let n = match n { - Some(n) => n, - None => { - struct_span_err!(self.sess, m.span, E0459, - "#[link(...)] specified without `name = \"foo\"`") - .span_label(m.span, "missing `name` argument").emit(); - Symbol::intern("foo") - } - }; - let cfg = items.iter().find(|k| { - k.check_name("cfg") - }).and_then(|a| a.meta_item_list()); - let cfg = cfg.map(|list| { - list[0].meta_item().unwrap().clone() - }); - let foreign_items = fm.items.iter() - .map(|it| definitions.opt_def_index(it.id).unwrap()) - .collect(); - let lib = NativeLibrary { - name: n, - kind, - cfg, - foreign_items, - }; - register_native_lib(self.sess, self.cstore, Some(m.span), lib); - } - } -} - impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { fn postprocess(&mut self, krate: &ast::Crate) { // inject the sanitizer runtime before the allocator runtime because all @@ -1242,72 +1085,10 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { if log_enabled!(log::LogLevel::Info) { dump_crates(&self.cstore); } - - // Process libs passed on the command line - // First, check for errors - let mut renames = FxHashSet(); - for &(ref name, ref new_name, _) in &self.sess.opts.libs { - if let &Some(ref new_name) = new_name { - if new_name.is_empty() { - self.sess.err( - &format!("an empty renaming target was specified for library `{}`",name)); - } else if !self.cstore.get_used_libraries().borrow().iter() - .any(|lib| lib.name == name as &str) { - self.sess.err(&format!("renaming of the library `{}` was specified, \ - however this crate contains no #[link(...)] \ - attributes referencing this library.", name)); - } else if renames.contains(name) { - self.sess.err(&format!("multiple renamings were specified for library `{}` .", - name)); - } else { - renames.insert(name); - } - } - } - // Update kind and, optionally, the name of all native libaries - // (there may be more than one) with the specified name. - for &(ref name, ref new_name, kind) in &self.sess.opts.libs { - let mut found = false; - for lib in self.cstore.get_used_libraries().borrow_mut().iter_mut() { - if lib.name == name as &str { - let mut changed = false; - if let Some(k) = kind { - lib.kind = k; - changed = true; - } - if let &Some(ref new_name) = new_name { - lib.name = Symbol::intern(new_name); - changed = true; - } - if !changed { - self.sess.warn(&format!("redundant linker flag specified for library `{}`", - name)); - } - - found = true; - } - } - if !found { - // Add if not found - let new_name = new_name.as_ref().map(|s| &**s); // &Option -> Option<&str> - let lib = NativeLibrary { - name: Symbol::intern(new_name.unwrap_or(name)), - kind: if let Some(k) = kind { k } else { cstore::NativeUnknown }, - cfg: None, - foreign_items: Vec::new(), - }; - register_native_lib(self.sess, self.cstore, None, lib); - } - } - self.register_statically_included_foreign_items(); - self.register_dllimport_foreign_items(); } fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) { match item.node { - ast::ItemKind::ForeignMod(ref fm) => { - self.process_foreign_mod(item, fm, definitions) - }, ast::ItemKind::ExternCrate(_) => { let info = self.extract_crate_info(item).unwrap(); let (cnum, ..) = self.resolve_crate( diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 0ed8ab2bc5596..2d10dadaf6415 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -14,13 +14,13 @@ use schema::{self, Tracked}; use rustc::dep_graph::DepGraph; -use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId}; use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::hir::svh::Svh; use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader}; use rustc_back::PanicStrategy; use rustc_data_structures::indexed_vec::IndexVec; -use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap, DefIdMap}; +use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap}; use std::cell::{RefCell, Cell}; use std::rc::Rc; @@ -95,11 +95,6 @@ pub struct CStore { metas: RefCell>>, /// Map from NodeId's of local extern crate statements to crate numbers extern_mod_crate_map: RefCell>, - used_libraries: RefCell>, - used_link_args: RefCell>, - statically_included_foreign_items: RefCell>, - pub dllimport_foreign_items: RefCell>, - pub visible_parent_map: RefCell>, pub metadata_loader: Box, } @@ -109,11 +104,6 @@ impl CStore { dep_graph: dep_graph.clone(), metas: RefCell::new(FxHashMap()), extern_mod_crate_map: RefCell::new(FxHashMap()), - used_libraries: RefCell::new(Vec::new()), - used_link_args: RefCell::new(Vec::new()), - statically_included_foreign_items: RefCell::new(FxHashSet()), - dllimport_foreign_items: RefCell::new(FxHashSet()), - visible_parent_map: RefCell::new(FxHashMap()), metadata_loader, } } @@ -126,10 +116,6 @@ impl CStore { self.metas.borrow().get(&cnum).unwrap().clone() } - pub fn get_crate_hash(&self, cnum: CrateNum) -> Svh { - self.get_crate_data(cnum).hash() - } - pub fn set_crate_data(&self, cnum: CrateNum, data: Rc) { self.metas.borrow_mut().insert(cnum, data); } @@ -164,86 +150,18 @@ impl CStore { ordering.push(krate); } - // This method is used when generating the command line to pass through to - // system linker. The linker expects undefined symbols on the left of the - // command line to be defined in libraries on the right, not the other way - // around. For more info, see some comments in the add_used_library function - // below. - // - // In order to get this left-to-right dependency ordering, we perform a - // topological sort of all crates putting the leaves at the right-most - // positions. - pub fn do_get_used_crates(&self, - prefer: LinkagePreference) - -> Vec<(CrateNum, LibSource)> { + pub fn do_postorder_cnums_untracked(&self) -> Vec { let mut ordering = Vec::new(); for (&num, _) in self.metas.borrow().iter() { self.push_dependencies_in_postorder(&mut ordering, num); } - info!("topological ordering: {:?}", ordering); - ordering.reverse(); - let mut libs = self.metas - .borrow() - .iter() - .filter_map(|(&cnum, data)| { - if data.dep_kind.get().macros_only() { return None; } - let path = match prefer { - LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0), - LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0), - }; - let path = match path { - Some(p) => LibSource::Some(p), - None => { - if data.source.rmeta.is_some() { - LibSource::MetadataOnly - } else { - LibSource::None - } - } - }; - Some((cnum, path)) - }) - .collect::>(); - libs.sort_by(|&(a, _), &(b, _)| { - let a = ordering.iter().position(|x| *x == a); - let b = ordering.iter().position(|x| *x == b); - a.cmp(&b) - }); - libs - } - - pub fn add_used_library(&self, lib: NativeLibrary) { - assert!(!lib.name.as_str().is_empty()); - self.used_libraries.borrow_mut().push(lib); - } - - pub fn get_used_libraries(&self) -> &RefCell> { - &self.used_libraries - } - - pub fn add_used_link_args(&self, args: &str) { - for s in args.split(' ').filter(|s| !s.is_empty()) { - self.used_link_args.borrow_mut().push(s.to_string()); - } - } - - pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell> { - &self.used_link_args + return ordering } pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) { self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum); } - pub fn add_statically_included_foreign_item(&self, id: DefIndex) { - self.statically_included_foreign_items.borrow_mut().insert(id); - } - - pub fn do_is_statically_included_foreign_item(&self, def_id: DefId) -> bool { - assert!(def_id.krate == LOCAL_CRATE); - self.statically_included_foreign_items.borrow().contains(&def_id.index) - } - pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { self.extern_mod_crate_map.borrow().get(&emod_id).cloned() } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 537e12086141c..776fd35829000 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -10,24 +10,25 @@ use cstore; use encoder; +use link_args; +use native_libs; use schema; use rustc::ty::maps::QueryConfig; -use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, - NativeLibrary, MetadataLoader, LinkMeta, - LinkagePreference, LoadedMacro, EncodedMetadata, - EncodedMetadataHashes}; +use rustc::middle::cstore::{CrateStore, DepKind, + MetadataLoader, LinkMeta, + LoadedMacro, EncodedMetadata, + EncodedMetadataHashes, NativeLibraryKind}; +use rustc::middle::stability::DeprecationEntry; use rustc::hir::def; -use rustc::middle::lang_items; use rustc::session::Session; use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::Providers; -use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; use rustc::hir::map::{DefKey, DefPath, DefPathHash}; use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::util::nodemap::{NodeSet, DefIdMap}; -use rustc_back::PanicStrategy; use std::any::Any; use std::rc::Rc; @@ -39,15 +40,19 @@ use syntax::parse::filemap_to_stream; use syntax::symbol::Symbol; use syntax_pos::{Span, NO_EXPANSION}; use rustc_data_structures::indexed_set::IdxSetBuf; -use rustc::hir::svh::Svh; use rustc::hir; macro_rules! provide { - (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident, $($name:ident => $compute:block)*) => { + (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, + $($name:ident => $compute:block)*) => { pub fn provide<$lt>(providers: &mut Providers<$lt>) { - $(fn $name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId) + $(fn $name<'a, $lt:$lt, T>($tcx: TyCtxt<'a, $lt, $lt>, def_id_arg: T) -> as - QueryConfig>::Value { + QueryConfig>::Value + where T: IntoArgs, + { + #[allow(unused_variables)] + let ($def_id, $other) = def_id_arg.into_args(); assert!(!$def_id.is_local()); let def_path_hash = $tcx.def_path_hash($def_id); @@ -69,7 +74,25 @@ macro_rules! provide { } } -provide! { <'tcx> tcx, def_id, cdata, +// small trait to work around different signature queries all being defined via +// the macro above. +trait IntoArgs { + fn into_args(self) -> (DefId, DefId); +} + +impl IntoArgs for DefId { + fn into_args(self) -> (DefId, DefId) { (self, self) } +} + +impl IntoArgs for CrateNum { + fn into_args(self) -> (DefId, DefId) { (self.as_def_id(), self.as_def_id()) } +} + +impl IntoArgs for (CrateNum, DefId) { + fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) } +} + +provide! { <'tcx> tcx, def_id, other, cdata, type_of => { cdata.get_type(def_id.index, tcx) } generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) } predicates_of => { cdata.get_predicates(def_id.index, tcx) } @@ -119,8 +142,12 @@ provide! { <'tcx> tcx, def_id, cdata, is_default_impl => { cdata.is_default_impl(def_id.index) } describe_def => { cdata.get_def(def_id.index) } def_span => { cdata.get_span(def_id.index, &tcx.sess) } - stability => { cdata.get_stability(def_id.index) } - deprecation => { cdata.get_deprecation(def_id.index) } + lookup_stability => { + cdata.get_stability(def_id.index).map(|s| tcx.intern_stability(s)) + } + lookup_deprecation_entry => { + cdata.get_deprecation(def_id.index).map(DeprecationEntry::external) + } item_attrs => { cdata.get_item_attrs(def_id.index, &tcx.dep_graph) } // FIXME(#38501) We've skipped a `read` on the `HirBody` of // a `fn` when encoding, so the dep-tracking wouldn't work. @@ -143,7 +170,68 @@ provide! { <'tcx> tcx, def_id, cdata, is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) } is_compiler_builtins => { cdata.is_compiler_builtins(&tcx.dep_graph) } has_global_allocator => { cdata.has_global_allocator(&tcx.dep_graph) } + is_sanitizer_runtime => { cdata.is_sanitizer_runtime(&tcx.dep_graph) } + is_profiler_runtime => { cdata.is_profiler_runtime(&tcx.dep_graph) } + panic_strategy => { cdata.panic_strategy(&tcx.dep_graph) } extern_crate => { Rc::new(cdata.extern_crate.get()) } + is_no_builtins => { cdata.is_no_builtins(&tcx.dep_graph) } + impl_defaultness => { cdata.get_impl_defaultness(def_id.index) } + exported_symbols => { Rc::new(cdata.get_exported_symbols(&tcx.dep_graph)) } + native_libraries => { Rc::new(cdata.get_native_libraries(&tcx.dep_graph)) } + plugin_registrar_fn => { + cdata.root.plugin_registrar_fn.map(|index| { + DefId { krate: def_id.krate, index } + }) + } + derive_registrar_fn => { + cdata.root.macro_derive_registrar.map(|index| { + DefId { krate: def_id.krate, index } + }) + } + crate_disambiguator => { cdata.disambiguator() } + crate_hash => { cdata.hash() } + original_crate_name => { cdata.name() } + + implementations_of_trait => { + let mut result = vec![]; + let filter = Some(other); + cdata.get_implementations_for_trait(filter, &tcx.dep_graph, &mut result); + Rc::new(result) + } + + all_trait_implementations => { + let mut result = vec![]; + cdata.get_implementations_for_trait(None, &tcx.dep_graph, &mut result); + Rc::new(result) + } + + is_dllimport_foreign_item => { + cdata.is_dllimport_foreign_item(def_id.index, &tcx.dep_graph) + } + visibility => { cdata.get_visibility(def_id.index) } + dep_kind => { cdata.dep_kind.get() } + crate_name => { cdata.name } + item_children => { + let mut result = vec![]; + cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess); + Rc::new(result) + } + defined_lang_items => { Rc::new(cdata.get_lang_items(&tcx.dep_graph)) } + missing_lang_items => { Rc::new(cdata.get_missing_lang_items(&tcx.dep_graph)) } + + extern_const_body => { + debug!("item_body({:?}): inlining item", def_id); + cdata.extern_const_body(tcx, def_id.index) + } + + missing_extern_crate_item => { + match cdata.extern_crate.get() { + Some(extern_crate) if !extern_crate.direct => true, + _ => false, + } + } + + used_crate_source => { Rc::new(cdata.source.clone()) } } pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) { @@ -158,8 +246,108 @@ pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) { } } + // FIXME(#44234) - almost all of these queries have no sub-queries and + // therefore no actual inputs, they're just reading tables calculated in + // resolve! Does this work? Unsure! That's what the issue is about *providers = Providers { is_const_fn, + is_dllimport_foreign_item: |tcx, id| { + tcx.native_library_kind(id) == Some(NativeLibraryKind::NativeUnknown) + }, + is_statically_included_foreign_item: |tcx, id| { + match tcx.native_library_kind(id) { + Some(NativeLibraryKind::NativeStatic) | + Some(NativeLibraryKind::NativeStaticNobundle) => true, + _ => false, + } + }, + native_library_kind: |tcx, id| { + tcx.native_libraries(id.krate) + .iter() + .filter(|lib| native_libs::relevant_lib(&tcx.sess, lib)) + .find(|l| l.foreign_items.contains(&id.index)) + .map(|l| l.kind) + }, + native_libraries: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Rc::new(native_libs::collect(tcx)) + }, + link_args: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Rc::new(link_args::collect(tcx)) + }, + extern_mod_stmt_cnum: |tcx, id| { + let id = tcx.hir.definitions().find_node_for_hir_id(id); + tcx.sess.cstore.extern_mod_stmt_cnum_untracked(id) + }, + + all_crate_nums: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Rc::new(tcx.sess.cstore.crates_untracked()) + }, + + // Returns a map from a sufficiently visible external item (i.e. an + // external item that is visible from at least one local module) to a + // sufficiently visible parent (considering modules that re-export the + // external item to be parents). + visible_parent_map: |tcx, cnum| { + use std::collections::vec_deque::VecDeque; + use std::collections::hash_map::Entry; + + assert_eq!(cnum, LOCAL_CRATE); + let mut visible_parent_map: DefIdMap = DefIdMap(); + + for &cnum in tcx.crates().iter() { + // Ignore crates without a corresponding local `extern crate` item. + if tcx.missing_extern_crate_item(cnum) { + continue + } + + let bfs_queue = &mut VecDeque::new(); + let visible_parent_map = &mut visible_parent_map; + let mut add_child = |bfs_queue: &mut VecDeque<_>, + child: &def::Export, + parent: DefId| { + let child = child.def.def_id(); + + if tcx.visibility(child) != ty::Visibility::Public { + return; + } + + match visible_parent_map.entry(child) { + Entry::Occupied(mut entry) => { + // If `child` is defined in crate `cnum`, ensure + // that it is mapped to a parent in `cnum`. + if child.krate == cnum && entry.get().krate != cnum { + entry.insert(parent); + } + } + Entry::Vacant(entry) => { + entry.insert(parent); + bfs_queue.push_back(child); + } + } + }; + + bfs_queue.push_back(DefId { + krate: cnum, + index: CRATE_DEF_INDEX + }); + while let Some(def) = bfs_queue.pop_front() { + for child in tcx.item_children(def).iter() { + add_child(bfs_queue, child, def); + } + } + } + + Rc::new(visible_parent_map) + }, + + postorder_cnums: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Rc::new(tcx.sess.cstore.postorder_cnums_untracked()) + }, + ..*providers }; } @@ -173,53 +361,23 @@ impl CrateStore for cstore::CStore { &*self.metadata_loader } - fn visibility(&self, def: DefId) -> ty::Visibility { + fn visibility_untracked(&self, def: DefId) -> ty::Visibility { self.read_dep_node(def); self.get_crate_data(def.krate).get_visibility(def.index) } - fn item_generics_cloned(&self, def: DefId) -> ty::Generics { + fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics { self.read_dep_node(def); self.get_crate_data(def.krate).get_generics(def.index) } - fn implementations_of_trait(&self, filter: Option) -> Vec - { - let mut result = vec![]; - - self.iter_crate_data(|_, cdata| { - cdata.get_implementations_for_trait(filter, &self.dep_graph, &mut result) - }); - result - } - - fn impl_defaultness(&self, def: DefId) -> hir::Defaultness - { - self.read_dep_node(def); - self.get_crate_data(def.krate).get_impl_defaultness(def.index) - } - - fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem + fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem { self.read_dep_node(def); self.get_crate_data(def.krate).get_associated_item(def.index) } - fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool - { - self.do_is_statically_included_foreign_item(def_id) - } - - fn is_dllimport_foreign_item(&self, def_id: DefId) -> bool { - if def_id.krate == LOCAL_CRATE { - self.dllimport_foreign_items.borrow().contains(&def_id.index) - } else { - self.get_crate_data(def_id.krate) - .is_dllimport_foreign_item(def_id.index, &self.dep_graph) - } - } - - fn dep_kind(&self, cnum: CrateNum) -> DepKind + fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { let data = self.get_crate_data(cnum); let dep_node = data.metadata_dep_node(GlobalMetaDataKind::CrateDeps); @@ -227,7 +385,7 @@ impl CrateStore for cstore::CStore { data.dep_kind.get() } - fn export_macros(&self, cnum: CrateNum) { + fn export_macros_untracked(&self, cnum: CrateNum) { let data = self.get_crate_data(cnum); let dep_node = data.metadata_dep_node(GlobalMetaDataKind::CrateDeps); @@ -237,83 +395,11 @@ impl CrateStore for cstore::CStore { } } - fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> - { - self.get_crate_data(cnum).get_lang_items(&self.dep_graph) - } - - fn missing_lang_items(&self, cnum: CrateNum) - -> Vec - { - self.get_crate_data(cnum).get_missing_lang_items(&self.dep_graph) - } - - fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_compiler_builtins(&self.dep_graph) - } - - fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_sanitizer_runtime(&self.dep_graph) - } - - fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_profiler_runtime(&self.dep_graph) - } - - fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { - self.get_crate_data(cnum).panic_strategy(&self.dep_graph) - } - - fn crate_name(&self, cnum: CrateNum) -> Symbol + fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { self.get_crate_data(cnum).name } - fn original_crate_name(&self, cnum: CrateNum) -> Symbol - { - self.get_crate_data(cnum).name() - } - - fn crate_hash(&self, cnum: CrateNum) -> Svh - { - self.get_crate_hash(cnum) - } - - fn crate_disambiguator(&self, cnum: CrateNum) -> Symbol - { - self.get_crate_data(cnum).disambiguator() - } - - fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option - { - self.get_crate_data(cnum).root.plugin_registrar_fn.map(|index| DefId { - krate: cnum, - index, - }) - } - - fn derive_registrar_fn(&self, cnum: CrateNum) -> Option - { - self.get_crate_data(cnum).root.macro_derive_registrar.map(|index| DefId { - krate: cnum, - index, - }) - } - - fn native_libraries(&self, cnum: CrateNum) -> Vec - { - self.get_crate_data(cnum).get_native_libraries(&self.dep_graph) - } - - fn exported_symbols(&self, cnum: CrateNum) -> Vec - { - self.get_crate_data(cnum).get_exported_symbols(&self.dep_graph) - } - - fn is_no_builtins(&self, cnum: CrateNum) -> bool { - self.get_crate_data(cnum).is_no_builtins(&self.dep_graph) - } - /// Returns the `DefKey` for a given `DefId`. This indicates the /// parent `DefId` as well as some idea of what kind of data the /// `DefId` refers to. @@ -343,13 +429,13 @@ impl CrateStore for cstore::CStore { self.get_crate_data(cnum).def_path_table.clone() } - fn struct_field_names(&self, def: DefId) -> Vec + fn struct_field_names_untracked(&self, def: DefId) -> Vec { self.read_dep_node(def); self.get_crate_data(def.krate).get_struct_field_names(def.index) } - fn item_children(&self, def_id: DefId, sess: &Session) -> Vec + fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec { self.read_dep_node(def_id); let mut result = vec![]; @@ -358,7 +444,7 @@ impl CrateStore for cstore::CStore { result } - fn load_macro(&self, id: DefId, sess: &Session) -> LoadedMacro { + fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { let data = self.get_crate_data(id.krate); if let Some(ref proc_macros) = data.proc_macros { return LoadedMacro::ProcMacro(proc_macros[id.index.as_usize() - 1].1.clone()); @@ -387,7 +473,7 @@ impl CrateStore for cstore::CStore { .insert(local_span, (name.to_string(), data.get_span(id.index, sess))); LoadedMacro::MacroDef(ast::Item { - ident: ast::Ident::with_empty_ctxt(name), + ident: ast::Ident::from_str(&name), id: ast::DUMMY_NODE_ID, span: local_span, attrs: attrs.iter().cloned().collect(), @@ -400,50 +486,20 @@ impl CrateStore for cstore::CStore { }) } - fn item_body<'a, 'tcx>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> &'tcx hir::Body { - self.read_dep_node(def_id); - - if let Some(cached) = tcx.hir.get_inlined_body_untracked(def_id) { - return cached; - } - - debug!("item_body({:?}): inlining item", def_id); - - self.get_crate_data(def_id.krate).item_body(tcx, def_id.index) - } - - fn crates(&self) -> Vec + fn crates_untracked(&self) -> Vec { let mut result = vec![]; self.iter_crate_data(|cnum, _| result.push(cnum)); result } - fn used_libraries(&self) -> Vec - { - self.get_used_libraries().borrow().clone() - } - - fn used_link_args(&self) -> Vec - { - self.get_used_link_args().borrow().clone() - } - fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> - { - self.do_get_used_crates(prefer) - } - - fn used_crate_source(&self, cnum: CrateNum) -> CrateSource + fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option { - self.get_crate_data(cnum).source.clone() + self.do_extern_mod_stmt_cnum(emod_id) } - fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option - { - self.do_extern_mod_stmt_cnum(emod_id) + fn postorder_cnums_untracked(&self) -> Vec { + self.do_postorder_cnums_untracked() } fn encode_metadata<'a, 'tcx>(&self, @@ -459,67 +515,4 @@ impl CrateStore for cstore::CStore { { schema::METADATA_HEADER } - - /// Returns a map from a sufficiently visible external item (i.e. an external item that is - /// visible from at least one local module) to a sufficiently visible parent (considering - /// modules that re-export the external item to be parents). - fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefIdMap> { - { - let visible_parent_map = self.visible_parent_map.borrow(); - if !visible_parent_map.is_empty() { - return visible_parent_map; - } - } - - use std::collections::vec_deque::VecDeque; - use std::collections::hash_map::Entry; - - let mut visible_parent_map = self.visible_parent_map.borrow_mut(); - - for cnum in (1 .. self.next_crate_num().as_usize()).map(CrateNum::new) { - let cdata = self.get_crate_data(cnum); - - match cdata.extern_crate.get() { - // Ignore crates without a corresponding local `extern crate` item. - Some(extern_crate) if !extern_crate.direct => continue, - _ => {}, - } - - let bfs_queue = &mut VecDeque::new(); - let mut add_child = |bfs_queue: &mut VecDeque<_>, child: def::Export, parent: DefId| { - let child = child.def.def_id(); - - if self.visibility(child) != ty::Visibility::Public { - return; - } - - match visible_parent_map.entry(child) { - Entry::Occupied(mut entry) => { - // If `child` is defined in crate `cnum`, ensure - // that it is mapped to a parent in `cnum`. - if child.krate == cnum && entry.get().krate != cnum { - entry.insert(parent); - } - } - Entry::Vacant(entry) => { - entry.insert(parent); - bfs_queue.push_back(child); - } - } - }; - - bfs_queue.push_back(DefId { - krate: cnum, - index: CRATE_DEF_INDEX - }); - while let Some(def) = bfs_queue.pop_front() { - for child in self.item_children(def, sess) { - add_child(bfs_queue, child, def); - } - } - } - - drop(visible_parent_map); - self.visible_parent_map.borrow() - } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 1e2f167f19962..324bab369dc7d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -41,6 +41,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; use syntax::codemap; +use syntax::symbol::{InternedString, Symbol}; use syntax::ext::base::MacroKind; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; @@ -473,7 +474,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn item_name(&self, item_index: DefIndex) -> ast::Name { + pub fn item_name(&self, item_index: DefIndex) -> InternedString { self.def_key(item_index) .disambiguated_data .data @@ -520,12 +521,12 @@ impl<'a, 'tcx> CrateMetadata { ty::VariantDef { did: self.local_def_id(data.struct_ctor.unwrap_or(index)), - name: self.item_name(index), + name: Symbol::intern(&self.item_name(index)), fields: item.children.decode(self).map(|index| { let f = self.entry(index); ty::FieldDef { did: self.local_def_id(index), - name: self.item_name(index), + name: Symbol::intern(&self.item_name(index)), vis: f.visibility.decode(self) } }).collect(), @@ -705,7 +706,7 @@ impl<'a, 'tcx> CrateMetadata { if let Some(def) = self.get_def(child_index) { callback(def::Export { def, - ident: Ident::with_empty_ctxt(self.item_name(child_index)), + ident: Ident::from_str(&self.item_name(child_index)), span: self.entry(child_index).span.decode((self, sess)), }); } @@ -722,7 +723,7 @@ impl<'a, 'tcx> CrateMetadata { 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::with_empty_ctxt(name); + let ident = Ident::from_str(&name); callback(def::Export { def: def, ident: ident, span: span }); // For non-reexport structs and variants add their constructors to children. // Reexport lists automatically contain constructors when necessary. @@ -759,10 +760,10 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn item_body(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - id: DefIndex) - -> &'tcx hir::Body { + pub fn extern_const_body(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: DefIndex) + -> &'tcx hir::Body { assert!(!self.is_proc_macro(id)); let ast = self.entry(id).ast.unwrap(); let def_id = self.local_def_id(id); @@ -836,7 +837,7 @@ impl<'a, 'tcx> CrateMetadata { }; ty::AssociatedItem { - name, + name: Symbol::intern(&name), kind, vis: item.visibility.decode(self), defaultness: container.defaultness(), @@ -906,7 +907,7 @@ impl<'a, 'tcx> CrateMetadata { self.entry(id) .children .decode(self) - .map(|index| self.item_name(index)) + .map(|index| Symbol::intern(&self.item_name(index))) .collect() } @@ -1038,7 +1039,7 @@ impl<'a, 'tcx> CrateMetadata { .collect() } - pub fn get_macro(&self, id: DefIndex) -> (ast::Name, MacroDef) { + pub fn get_macro(&self, id: DefIndex) -> (InternedString, MacroDef) { let entry = self.entry(id); match entry.kind { EntryKind::MacroDef(macro_def) => (self.item_name(id), macro_def.decode(self)), diff --git a/src/librustc_metadata/diagnostics.rs b/src/librustc_metadata/diagnostics.rs index 1fa1a896dd6b6..0a1662dd42d90 100644 --- a/src/librustc_metadata/diagnostics.rs +++ b/src/librustc_metadata/diagnostics.rs @@ -14,7 +14,7 @@ register_long_diagnostics! { E0454: r##" A link name was given with an empty name. Erroneous code example: -```compile_fail,E0454 +```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-trans) #[link(name = "")] extern {} // error: #[link(name = "")] given with empty name ``` @@ -51,7 +51,7 @@ https://doc.rust-lang.org/book/first-edition/conditional-compilation.html E0458: r##" An unknown "kind" was specified for a link attribute. Erroneous code example: -```compile_fail,E0458 +```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-trans) #[link(kind = "wonderful_unicorn")] extern {} // error: unknown kind: `wonderful_unicorn` ``` @@ -67,7 +67,7 @@ Please specify a valid "kind" value, from one of the following: E0459: r##" A link was used without a name parameter. Erroneous code example: -```compile_fail,E0459 +```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-trans) #[link(kind = "dylib")] extern {} // error: #[link(...)] specified without `name = "foo"` ``` diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d36aebe38eb0b..a27a85a63e8a7 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -991,7 +991,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // "unsized info", else just store None let coerce_unsized_info = trait_ref.and_then(|t| { - if Some(t.def_id) == tcx.lang_items.coerce_unsized_trait() { + if Some(t.def_id) == tcx.lang_items().coerce_unsized_trait() { Some(tcx.at(item.span).coerce_unsized_info(def_id)) } else { None @@ -1283,21 +1283,20 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_native_libraries(&mut self, _: ()) -> LazySeq { - let used_libraries = self.tcx.sess.cstore.used_libraries(); - self.lazy_seq(used_libraries) + let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); + self.lazy_seq(used_libraries.iter().cloned()) } fn encode_crate_deps(&mut self, _: ()) -> LazySeq { - let cstore = &*self.tcx.sess.cstore; - let crates = cstore.crates(); + let crates = self.tcx.crates(); let mut deps = crates .iter() .map(|&cnum| { let dep = CrateDep { - name: cstore.original_crate_name(cnum), - hash: cstore.crate_hash(cnum), - kind: cstore.dep_kind(cnum), + name: self.tcx.original_crate_name(cnum), + hash: self.tcx.crate_hash(cnum), + kind: self.tcx.dep_kind(cnum), }; (cnum, dep) }) @@ -1323,7 +1322,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> { let tcx = self.tcx; - let lang_items = tcx.lang_items.items().iter(); + let lang_items = tcx.lang_items(); + let lang_items = lang_items.items().iter(); self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { if let Some(def_id) = opt_def_id { if def_id.is_local() { @@ -1336,7 +1336,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq { let tcx = self.tcx; - self.lazy_seq_ref(&tcx.lang_items.missing) + self.lazy_seq_ref(&tcx.lang_items().missing) } /// Encodes an index, mapping each trait to its (local) implementations. diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index f4e6f57c43777..54dbb68667b3a 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -50,6 +50,8 @@ mod decoder; mod cstore_impl; mod isolated_encoder; mod schema; +mod native_libs; +mod link_args; pub mod creader; pub mod cstore; diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs new file mode 100644 index 0000000000000..6fafde0d09c16 --- /dev/null +++ b/src/librustc_metadata/link_args.rs @@ -0,0 +1,65 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir; +use rustc::ty::TyCtxt; +use syntax::abi::Abi; + +pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { + let mut collector = Collector { + args: Vec::new(), + }; + tcx.hir.krate().visit_all_item_likes(&mut collector); + + for attr in tcx.hir.krate().attrs.iter() { + if attr.path == "link_args" { + if let Some(linkarg) = attr.value_str() { + collector.add_link_args(&linkarg.as_str()); + } + } + } + + return collector.args +} + +struct Collector { + args: Vec, +} + +impl<'tcx> ItemLikeVisitor<'tcx> for Collector { + fn visit_item(&mut self, it: &'tcx hir::Item) { + let fm = match it.node { + hir::ItemForeignMod(ref fm) => fm, + _ => return, + }; + if fm.abi == Abi::Rust || + fm.abi == Abi::RustIntrinsic || + fm.abi == Abi::PlatformIntrinsic { + return + } + + // First, add all of the custom #[link_args] attributes + for m in it.attrs.iter().filter(|a| a.check_name("link_args")) { + if let Some(linkarg) = m.value_str() { + self.add_link_args(&linkarg.as_str()); + } + } + } + + fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem) {} + fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem) {} +} + +impl Collector { + fn add_link_args(&mut self, args: &str) { + self.args.extend(args.split(' ').filter(|s| !s.is_empty()).map(|s| s.to_string())) + } +} diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs new file mode 100644 index 0000000000000..669681d2aadde --- /dev/null +++ b/src/librustc_metadata/native_libs.rs @@ -0,0 +1,217 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir; +use rustc::middle::cstore::{self, NativeLibrary}; +use rustc::session::Session; +use rustc::ty::TyCtxt; +use rustc::util::nodemap::FxHashSet; +use syntax::abi::Abi; +use syntax::attr; +use syntax::codemap::Span; +use syntax::feature_gate::{self, GateIssue}; +use syntax::symbol::Symbol; + +pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec { + let mut collector = Collector { + tcx, + libs: Vec::new(), + }; + tcx.hir.krate().visit_all_item_likes(&mut collector); + collector.process_command_line(); + return collector.libs +} + +pub fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { + match lib.cfg { + Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None), + None => true, + } +} + +struct Collector<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + libs: Vec, +} + +impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> { + fn visit_item(&mut self, it: &'tcx hir::Item) { + let fm = match it.node { + hir::ItemForeignMod(ref fm) => fm, + _ => return, + }; + + if fm.abi == Abi::Rust || + fm.abi == Abi::RustIntrinsic || + fm.abi == Abi::PlatformIntrinsic { + return + } + + // Process all of the #[link(..)]-style arguments + for m in it.attrs.iter().filter(|a| a.check_name("link")) { + let items = match m.meta_item_list() { + Some(item) => item, + None => continue, + }; + let kind = items.iter().find(|k| { + k.check_name("kind") + }).and_then(|a| a.value_str()).map(Symbol::as_str); + let kind = match kind.as_ref().map(|s| &s[..]) { + Some("static") => cstore::NativeStatic, + Some("static-nobundle") => cstore::NativeStaticNobundle, + Some("dylib") => cstore::NativeUnknown, + Some("framework") => cstore::NativeFramework, + Some(k) => { + struct_span_err!(self.tcx.sess, m.span, E0458, + "unknown kind: `{}`", k) + .span_label(m.span, "unknown kind").emit(); + cstore::NativeUnknown + } + None => cstore::NativeUnknown + }; + let n = items.iter().find(|n| { + n.check_name("name") + }).and_then(|a| a.value_str()); + let n = match n { + Some(n) => n, + None => { + struct_span_err!(self.tcx.sess, m.span, E0459, + "#[link(...)] specified without `name = \"foo\"`") + .span_label(m.span, "missing `name` argument").emit(); + Symbol::intern("foo") + } + }; + let cfg = items.iter().find(|k| { + k.check_name("cfg") + }).and_then(|a| a.meta_item_list()); + let cfg = cfg.map(|list| { + list[0].meta_item().unwrap().clone() + }); + let foreign_items = fm.items.iter() + .map(|it| self.tcx.hir.local_def_id(it.id).index) + .collect(); + let lib = NativeLibrary { + name: n, + kind, + cfg, + foreign_items, + }; + self.register_native_lib(Some(m.span), lib); + } + } + + fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem) {} + fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem) {} +} + +impl<'a, 'tcx> Collector<'a, 'tcx> { + fn register_native_lib(&mut self, span: Option, lib: NativeLibrary) { + if lib.name.as_str().is_empty() { + match span { + Some(span) => { + struct_span_err!(self.tcx.sess, span, E0454, + "#[link(name = \"\")] given with empty name") + .span_label(span, "empty name given") + .emit(); + } + None => { + self.tcx.sess.err("empty library name given via `-l`"); + } + } + return + } + let is_osx = self.tcx.sess.target.target.options.is_like_osx; + if lib.kind == cstore::NativeFramework && !is_osx { + let msg = "native frameworks are only available on macOS targets"; + match span { + Some(span) => span_err!(self.tcx.sess, span, E0455, "{}", msg), + None => self.tcx.sess.err(msg), + } + } + if lib.cfg.is_some() && !self.tcx.sess.features.borrow().link_cfg { + feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, + "link_cfg", + span.unwrap(), + GateIssue::Language, + "is feature gated"); + } + if lib.kind == cstore::NativeStaticNobundle && + !self.tcx.sess.features.borrow().static_nobundle { + feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, + "static_nobundle", + span.unwrap(), + GateIssue::Language, + "kind=\"static-nobundle\" is feature gated"); + } + self.libs.push(lib); + } + + // Process libs passed on the command line + fn process_command_line(&mut self) { + // First, check for errors + let mut renames = FxHashSet(); + for &(ref name, ref new_name, _) in &self.tcx.sess.opts.libs { + if let &Some(ref new_name) = new_name { + if new_name.is_empty() { + self.tcx.sess.err( + &format!("an empty renaming target was specified for library `{}`",name)); + } else if !self.libs.iter().any(|lib| lib.name == name as &str) { + self.tcx.sess.err(&format!("renaming of the library `{}` was specified, \ + however this crate contains no #[link(...)] \ + attributes referencing this library.", name)); + } else if renames.contains(name) { + self.tcx.sess.err(&format!("multiple renamings were \ + specified for library `{}` .", + name)); + } else { + renames.insert(name); + } + } + } + + // Update kind and, optionally, the name of all native libaries + // (there may be more than one) with the specified name. + for &(ref name, ref new_name, kind) in &self.tcx.sess.opts.libs { + let mut found = false; + for lib in self.libs.iter_mut() { + if lib.name == name as &str { + let mut changed = false; + if let Some(k) = kind { + lib.kind = k; + changed = true; + } + if let &Some(ref new_name) = new_name { + lib.name = Symbol::intern(new_name); + changed = true; + } + if !changed { + let msg = format!("redundant linker flag specified for \ + library `{}`", name); + self.tcx.sess.warn(&msg); + } + + found = true; + } + } + if !found { + // Add if not found + let new_name = new_name.as_ref().map(|s| &**s); // &Option -> Option<&str> + let lib = NativeLibrary { + name: Symbol::intern(new_name.unwrap_or(name)), + kind: if let Some(k) = kind { k } else { cstore::NativeUnknown }, + cfg: None, + foreign_items: Vec::new(), + }; + self.register_native_lib(None, lib); + } + } + } +} diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 80a126dc42569..ec06e474980a6 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -209,7 +209,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let f = ty.fn_sig(this.hir.tcx()); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { - Some(this.hir.tcx().item_name(def_id).as_str()) + Some(this.hir.tcx().item_name(def_id)) } else { None } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index dc15163ecc12e..0b91e08fc6d70 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -299,7 +299,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let fail = self.cfg.start_new_block(); if let ty::TyRef(_, mt) = ty.sty { assert!(ty.is_slice()); - let eq_def_id = self.hir.tcx().lang_items.eq_trait().unwrap(); + let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap(); let ty = mt.ty; let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty]); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index d3c886dab4e86..ec545443bcd90 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -47,7 +47,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, bug!("item {:?} passed to make_shim", instance), ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); - let adjustment = match tcx.lang_items.fn_trait_kind(trait_) { + let adjustment = match tcx.lang_items().fn_trait_kind(trait_) { Some(ty::ClosureKind::FnOnce) => Adjustment::Identity, Some(ty::ClosureKind::FnMut) | Some(ty::ClosureKind::Fn) => Adjustment::Deref, @@ -82,7 +82,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, ) } ty::InstanceDef::ClosureOnceShim { call_once } => { - let fn_mut = tcx.lang_items.fn_mut_trait().unwrap(); + let fn_mut = tcx.lang_items().fn_mut_trait().unwrap(); let call_mut = tcx.global_tcx() .associated_items(fn_mut) .find(|it| it.kind == ty::AssociatedKind::Method) @@ -100,7 +100,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, build_drop_shim(tcx, def_id, ty) } ty::InstanceDef::CloneShim(def_id, ty) => { - let name = tcx.item_name(def_id).as_str(); + let name = tcx.item_name(def_id); if name == "clone" { build_clone_shim(tcx, def_id, ty) } else if name == "clone_from" { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index d1e0465f5551c..0fb34c96b062d 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -715,7 +715,7 @@ impl MirPass for StateTransform { let gen_ty = mir.local_decls.raw[1].ty; // Compute GeneratorState - let state_did = tcx.lang_items.gen_state().unwrap(); + let state_did = tcx.lang_items().gen_state().unwrap(); let state_adt_ref = tcx.adt_def(state_did); let state_substs = tcx.mk_substs([Kind::from(yield_ty), Kind::from(mir.return_ty)].iter()); diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 3f8070fb3aa31..46aa391897a9c 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -338,7 +338,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { debug!("Inlined {:?} into {:?}", callsite.callee, self.source); - let is_box_free = Some(callsite.callee) == self.tcx.lang_items.box_free_fn(); + let is_box_free = Some(callsite.callee) == self.tcx.lang_items().box_free_fn(); let mut local_map = IndexVec::with_capacity(callee_mir.local_decls.len()); let mut scope_map = IndexVec::with_capacity(callee_mir.visibility_scopes.len()); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 415421757c5c5..ded97275468b9 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -252,7 +252,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } fn find_drop_implementation_method_span(&self) -> Option { - self.tcx.lang_items + self.tcx.lang_items() .drop_trait() .and_then(|drop_trait_id| { let mut span = None; @@ -795,7 +795,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { self.deny_drop(); } - if Some(def.did) == self.tcx.lang_items.unsafe_cell_type() { + if Some(def.did) == self.tcx.lang_items().unsafe_cell_type() { let ty = rvalue.ty(self.mir, self.tcx); self.add_type(ty); assert!(self.qualif.intersects(Qualif::MUTABLE_INTERIOR)); @@ -824,7 +824,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { Abi::RustIntrinsic | Abi::PlatformIntrinsic => { assert!(!self.tcx.is_const_fn(def_id)); - match &self.tcx.item_name(def_id).as_str()[..] { + match &self.tcx.item_name(def_id)[..] { "size_of" | "min_align_of" => is_const_fn = true, name if name.starts_with("simd_shuffle") => { diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index d4da14ea96e72..7fbeb9610f471 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -575,7 +575,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { value: ConstVal::Function(def_id, _), .. }, .. }) => { - Some(def_id) == self.tcx().lang_items.box_free_fn() + Some(def_id) == self.tcx().lang_items().box_free_fn() } _ => false, } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index f3b121f2eed57..8ea47c2991009 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -515,7 +515,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> { debug!("destructor_call_block({:?}, {:?})", self, succ); let tcx = self.tcx(); - let drop_trait = tcx.lang_items.drop_trait().unwrap(); + let drop_trait = tcx.lang_items().drop_trait().unwrap(); let drop_fn = tcx.associated_items(drop_trait).next().unwrap(); let ty = self.lvalue_ty(self.lvalue); let substs = tcx.mk_substs(iter::once(Kind::from(ty))); diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index b4f4f56519121..6f2c448ceb6f9 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -401,7 +401,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node hir::ExprStruct(..) => { if let ty::TyAdt(adt, ..) = v.tables.expr_ty(e).sty { // unsafe_cell_type doesn't necessarily exist with no_core - if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() { + if Some(adt.did) == v.tcx.lang_items().unsafe_cell_type() { v.promotable = false; } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 872a29e7bc0c5..139cb61bd9bd7 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -630,7 +630,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { }; ty::Visibility::from_hir(vis, node_id, self.tcx) } - None => self.tcx.sess.cstore.visibility(did), + None => self.tcx.visibility(did), } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 47fa5357abf0d..35e7522db0184 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -42,6 +42,7 @@ use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::parse::token; use syntax::symbol::keywords; +use syntax::symbol::Symbol; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; @@ -253,7 +254,7 @@ impl<'a> Resolver<'a> { self.crate_loader.process_item(item, &self.definitions); // n.b. we don't need to look at the path option here, because cstore already did - let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap(); + let crate_id = self.session.cstore.extern_mod_stmt_cnum_untracked(item.id).unwrap(); let module = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); self.populate_module_if_necessary(module); @@ -449,7 +450,7 @@ impl<'a> Resolver<'a> { let ident = child.ident; let def = child.def; let def_id = def.def_id(); - let vis = self.session.cstore.visibility(def_id); + let vis = self.session.cstore.visibility_untracked(def_id); let span = child.span; let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene match def { @@ -485,12 +486,12 @@ impl<'a> Resolver<'a> { span); self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); - for child in self.session.cstore.item_children(def_id, self.session) { + for child in self.session.cstore.item_children_untracked(def_id, self.session) { let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS }; self.define(module, child.ident, ns, (child.def, ty::Visibility::Public, DUMMY_SP, expansion)); - if self.session.cstore.associated_item_cloned(child.def.def_id()) + if self.session.cstore.associated_item_cloned_untracked(child.def.def_id()) .method_has_self_argument { self.has_self.insert(child.def.def_id()); } @@ -501,7 +502,7 @@ impl<'a> Resolver<'a> { self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); // Record field names for error reporting. - let field_names = self.session.cstore.struct_field_names(def_id); + let field_names = self.session.cstore.struct_field_names_untracked(def_id); self.insert_field_names(def_id, field_names); } Def::Macro(..) => { @@ -516,20 +517,20 @@ impl<'a> Resolver<'a> { return self.module_map[&def_id] } - let macros_only = self.session.cstore.dep_kind(def_id.krate).macros_only(); + let macros_only = self.session.cstore.dep_kind_untracked(def_id.krate).macros_only(); if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) { return module; } let (name, parent) = if def_id.index == CRATE_DEF_INDEX { - (self.session.cstore.crate_name(def_id.krate), None) + (self.session.cstore.crate_name_untracked(def_id.krate).as_str(), None) } else { let def_key = self.session.cstore.def_key(def_id); (def_key.disambiguated_data.data.get_opt_name().unwrap(), Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }))) }; - let kind = ModuleKind::Def(Def::Mod(def_id), name); + let kind = ModuleKind::Def(Def::Mod(def_id), Symbol::intern(&name)); let module = self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP)); self.extern_module_map.insert((def_id, macros_only), module); @@ -558,7 +559,7 @@ impl<'a> Resolver<'a> { return ext.clone(); } - let macro_def = match self.session.cstore.load_macro(def_id, &self.session) { + let macro_def = match self.session.cstore.load_macro_untracked(def_id, &self.session) { LoadedMacro::MacroDef(macro_def) => macro_def, LoadedMacro::ProcMacro(ext) => return ext, }; @@ -574,7 +575,8 @@ impl<'a> Resolver<'a> { /// is built, building it if it is not. pub fn populate_module_if_necessary(&mut self, module: Module<'a>) { if module.populated.get() { return } - for child in self.session.cstore.item_children(module.def_id().unwrap(), self.session) { + let def_id = module.def_id().unwrap(); + for child in self.session.cstore.item_children_untracked(def_id, self.session) { self.build_reduced_graph_for_external_crate_def(module, child); } module.populated.set(true) @@ -605,7 +607,8 @@ impl<'a> Resolver<'a> { span_err!(self.session, item.span, E0468, "an `extern crate` loading macros must be at the crate root"); } else if !self.use_extern_macros && !used && - self.session.cstore.dep_kind(module.def_id().unwrap().krate).macros_only() { + self.session.cstore.dep_kind_untracked(module.def_id().unwrap().krate) + .macros_only() { let msg = "proc macro crates and `#[no_link]` crates have no effect without \ `#[macro_use]`"; self.session.span_warn(item.span, msg); @@ -648,7 +651,7 @@ impl<'a> Resolver<'a> { } } for (name, span) in legacy_imports.reexports { - self.session.cstore.export_macros(module.def_id().unwrap().krate); + self.session.cstore.export_macros_untracked(module.def_id().unwrap().krate); let ident = Ident::with_empty_ctxt(name); let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span); if let Ok(binding) = result { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 9531c8baa0bc1..c083a0ff58855 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -778,7 +778,7 @@ impl<'a> Resolver<'a> { _ => return, }; - let crate_name = self.session.cstore.crate_name(krate); + let crate_name = self.session.cstore.crate_name_untracked(krate); self.session.struct_span_err(use_span, warn_msg) .help(&format!("instead, import the procedural macro like any other item: \ diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 71bcee56ecc51..7524b7e8c6c21 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -844,7 +844,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let def = binding.def(); if def != Def::Err { if !def.def_id().is_local() { - self.session.cstore.export_macros(def.def_id().krate); + self.session.cstore.export_macros_untracked(def.def_id().krate); } if let Def::Macro(..) = def { if let Some(&span) = exported_macro_names.get(&ident.modern()) { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 9ee38dd86c1b5..3de5fda0d45c1 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -109,7 +109,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_external_crates(&self) -> Vec { let mut result = Vec::new(); - for n in self.tcx.sess.cstore.crates() { + for &n in self.tcx.crates().iter() { let span = match *self.tcx.extern_crate(n.as_def_id()) { Some(ref c) => c.span, None => { @@ -119,7 +119,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }; let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo()); result.push(ExternalCrateData { - name: self.tcx.sess.cstore.crate_name(n).to_string(), + name: self.tcx.crate_name(n).to_string(), num: n.as_u32(), file_name: SpanUtils::make_path_string(&lo_loc.file.name), }); diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 4b56376ad9bea..9bc6b737a6d26 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -19,10 +19,9 @@ use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, Pri use rustc::session::filesearch; use rustc::session::search_paths::PathKind; use rustc::session::Session; -use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, LinkagePreference, - NativeLibraryKind}; +use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, NativeLibraryKind}; use rustc::middle::dependency_format::Linkage; -use CrateTranslation; +use {CrateTranslation, CrateInfo}; use rustc::util::common::time; use rustc::util::fs::fix_windows_verbatim_for_gcc; use rustc::dep_graph::{DepKind, DepNode}; @@ -216,8 +215,9 @@ fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilen } pub fn each_linked_rlib(sess: &Session, + info: &CrateInfo, f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> { - let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter(); + let crates = info.used_crates_static.iter(); let fmts = sess.dependency_formats.borrow(); let fmts = fmts.get(&config::CrateTypeExecutable) .or_else(|| fmts.get(&config::CrateTypeStaticlib)) @@ -227,16 +227,16 @@ pub fn each_linked_rlib(sess: &Session, Some(f) => f, None => return Err(format!("could not find formats for rlibs")) }; - for (cnum, path) in crates { + for &(cnum, ref path) in crates { match fmts.get(cnum.as_usize() - 1) { Some(&Linkage::NotLinked) | Some(&Linkage::IncludedFromDylib) => continue, Some(_) => {} None => return Err(format!("could not find formats for rlibs")) } - let name = sess.cstore.crate_name(cnum).clone(); - let path = match path { - LibSource::Some(p) => p, + let name = &info.crate_name[&cnum]; + let path = match *path { + LibSource::Some(ref p) => p, LibSource::MetadataOnly => { return Err(format!("could not find rlib for: `{}`, found rmeta (metadata) file", name)) @@ -260,12 +260,12 @@ pub fn each_linked_rlib(sess: &Session, /// It's unusual for a crate to not participate in LTO. Typically only /// compiler-specific and unstable crates have a reason to not participate in /// LTO. -pub fn ignored_for_lto(sess: &Session, cnum: CrateNum) -> bool { +pub fn ignored_for_lto(info: &CrateInfo, cnum: CrateNum) -> bool { // `#![no_builtins]` crates don't participate in LTO because the state // of builtins gets messed up (our crate isn't tagged with no builtins). // Similarly `#![compiler_builtins]` doesn't participate because we want // those builtins! - sess.cstore.is_no_builtins(cnum) || sess.cstore.is_compiler_builtins(cnum) + info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum) } fn out_filename(sess: &Session, @@ -431,7 +431,7 @@ fn link_rlib<'a>(sess: &'a Session, // feature then we'll need to figure out how to record what objects were // loaded from the libraries found here and then encode that into the // metadata of the rlib we're generating somehow. - for lib in sess.cstore.used_libraries() { + for lib in trans.crate_info.used_libraries.iter() { match lib.kind { NativeLibraryKind::NativeStatic => {} NativeLibraryKind::NativeStaticNobundle | @@ -611,9 +611,9 @@ fn link_staticlib(sess: &Session, tempdir); let mut all_native_libs = vec![]; - let res = each_linked_rlib(sess, &mut |cnum, path| { - let name = sess.cstore.crate_name(cnum); - let native_libs = sess.cstore.native_libraries(cnum); + let res = each_linked_rlib(sess, &trans.crate_info, &mut |cnum, path| { + let name = &trans.crate_info.crate_name[&cnum]; + let native_libs = &trans.crate_info.native_libraries[&cnum]; // Here when we include the rlib into our staticlib we need to make a // decision whether to include the extra object files along the way. @@ -634,10 +634,10 @@ fn link_staticlib(sess: &Session, }); ab.add_rlib(path, &name.as_str(), - sess.lto() && !ignored_for_lto(sess, cnum), + sess.lto() && !ignored_for_lto(&trans.crate_info, cnum), skip_object_files).unwrap(); - all_native_libs.extend(sess.cstore.native_libraries(cnum)); + all_native_libs.extend(trans.crate_info.native_libraries[&cnum].iter().cloned()); }); if let Err(e) = res { sess.fatal(&e); @@ -930,7 +930,7 @@ fn link_args(cmd: &mut Linker, cmd.gc_sections(keep_metadata); } - let used_link_args = sess.cstore.used_link_args(); + let used_link_args = &trans.crate_info.link_args; if crate_type == config::CrateTypeExecutable && t.options.position_independent_executables { @@ -1000,9 +1000,9 @@ fn link_args(cmd: &mut Linker, // link line. And finally upstream native libraries can't depend on anything // in this DAG so far because they're only dylibs and dylibs can only depend // on other dylibs (e.g. other native deps). - add_local_native_libraries(cmd, sess); - add_upstream_rust_crates(cmd, sess, crate_type, tmpdir); - add_upstream_native_libraries(cmd, sess, crate_type); + add_local_native_libraries(cmd, sess, trans); + add_upstream_rust_crates(cmd, sess, trans, crate_type, tmpdir); + add_upstream_native_libraries(cmd, sess, trans, crate_type); // Tell the linker what we're doing. if crate_type != config::CrateTypeExecutable { @@ -1027,7 +1027,7 @@ fn link_args(cmd: &mut Linker, path }; let mut rpath_config = RPathConfig { - used_crates: sess.cstore.used_crates(LinkagePreference::RequireDynamic), + used_crates: &trans.crate_info.used_crates_dynamic, out_filename: out_filename.to_path_buf(), has_rpath: sess.target.target.options.has_rpath, is_like_osx: sess.target.target.options.is_like_osx, @@ -1057,7 +1057,9 @@ fn link_args(cmd: &mut Linker, // Also note that the native libraries linked here are only the ones located // in the current crate. Upstream crates with native library dependencies // may have their native library pulled in above. -fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) { +fn add_local_native_libraries(cmd: &mut Linker, + sess: &Session, + trans: &CrateTranslation) { sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| { match k { PathKind::Framework => { cmd.framework_path(path); } @@ -1065,7 +1067,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) { } }); - let relevant_libs = sess.cstore.used_libraries().into_iter().filter(|l| { + let relevant_libs = trans.crate_info.used_libraries.iter().filter(|l| { relevant_lib(sess, l) }); @@ -1088,6 +1090,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) { // the intermediate rlib version) fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session, + trans: &CrateTranslation, crate_type: config::CrateType, tmpdir: &Path) { // All of the heavy lifting has previously been accomplished by the @@ -1103,35 +1106,35 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // Invoke get_used_crates to ensure that we get a topological sorting of // crates. - let deps = sess.cstore.used_crates(LinkagePreference::RequireDynamic); + let deps = &trans.crate_info.used_crates_dynamic; let mut compiler_builtins = None; - for &(cnum, _) in &deps { + for &(cnum, _) in deps.iter() { // We may not pass all crates through to the linker. Some crates may // appear statically in an existing dylib, meaning we'll pick up all the // symbols from the dylib. - let src = sess.cstore.used_crate_source(cnum); + let src = &trans.crate_info.used_crate_source[&cnum]; match data[cnum.as_usize() - 1] { - _ if sess.cstore.is_profiler_runtime(cnum) => { - add_static_crate(cmd, sess, tmpdir, crate_type, cnum); + _ if trans.crate_info.profiler_runtime == Some(cnum) => { + add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum); } - _ if sess.cstore.is_sanitizer_runtime(cnum) => { - link_sanitizer_runtime(cmd, sess, tmpdir, cnum); + _ if trans.crate_info.sanitizer_runtime == Some(cnum) => { + link_sanitizer_runtime(cmd, sess, trans, tmpdir, cnum); } // compiler-builtins are always placed last to ensure that they're // linked correctly. - _ if sess.cstore.is_compiler_builtins(cnum) => { + _ if trans.crate_info.compiler_builtins == Some(cnum) => { assert!(compiler_builtins.is_none()); compiler_builtins = Some(cnum); } Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { - add_static_crate(cmd, sess, tmpdir, crate_type, cnum); + add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum); } Linkage::Dynamic => { - add_dynamic_crate(cmd, sess, &src.dylib.unwrap().0) + add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0) } } } @@ -1142,7 +1145,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // was already "included" in a dylib (e.g. `libstd` when `-C prefer-dynamic` // is used) if let Some(cnum) = compiler_builtins { - add_static_crate(cmd, sess, tmpdir, crate_type, cnum); + add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum); } // Converts a library file-stem into a cc -l argument @@ -1160,10 +1163,11 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // linking it. fn link_sanitizer_runtime(cmd: &mut Linker, sess: &Session, + trans: &CrateTranslation, tmpdir: &Path, cnum: CrateNum) { - let src = sess.cstore.used_crate_source(cnum); - let cratepath = &src.rlib.unwrap().0; + let src = &trans.crate_info.used_crate_source[&cnum]; + let cratepath = &src.rlib.as_ref().unwrap().0; if sess.target.target.options.is_like_osx { // On Apple platforms, the sanitizer is always built as a dylib, and @@ -1228,21 +1232,22 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // we're at the end of the dependency chain. fn add_static_crate(cmd: &mut Linker, sess: &Session, + trans: &CrateTranslation, tmpdir: &Path, crate_type: config::CrateType, cnum: CrateNum) { - let src = sess.cstore.used_crate_source(cnum); - let cratepath = &src.rlib.unwrap().0; + let src = &trans.crate_info.used_crate_source[&cnum]; + let cratepath = &src.rlib.as_ref().unwrap().0; // See the comment above in `link_staticlib` and `link_rlib` for why if // there's a static library that's not relevant we skip all object // files. - let native_libs = sess.cstore.native_libraries(cnum); + let native_libs = &trans.crate_info.native_libraries[&cnum]; let skip_native = native_libs.iter().any(|lib| { lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib) }); - if (!sess.lto() || ignored_for_lto(sess, cnum)) && + if (!sess.lto() || ignored_for_lto(&trans.crate_info, cnum)) && crate_type != config::CrateTypeDylib && !skip_native { cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath)); @@ -1284,7 +1289,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // LTO module. Note that `#![no_builtins]` is excluded from LTO, // though, so we let that object file slide. let skip_because_lto = sess.lto() && is_rust_object && - !sess.cstore.is_no_builtins(cnum); + !trans.crate_info.is_no_builtins.contains(&cnum); if skip_because_cfg_say_so || skip_because_lto { archive.remove_file(&f); @@ -1306,7 +1311,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // compiler-builtins crate (e.g. compiler-rt) because it'll get // repeatedly linked anyway. if crate_type == config::CrateTypeDylib && - !sess.cstore.is_compiler_builtins(cnum) { + trans.crate_info.compiler_builtins != Some(cnum) { cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst)); } else { cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst)); @@ -1350,7 +1355,10 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // generic function calls a native function, then the generic function must // be instantiated in the target crate, meaning that the native symbol must // also be resolved in the target crate. -fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session, crate_type: config::CrateType) { +fn add_upstream_native_libraries(cmd: &mut Linker, + sess: &Session, + trans: &CrateTranslation, + crate_type: config::CrateType) { // Be sure to use a topological sorting of crates because there may be // interdependencies between native libraries. When passing -nodefaultlibs, // for example, almost all native libraries depend on libc, so we have to @@ -1363,9 +1371,9 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session, crate_type: c let formats = sess.dependency_formats.borrow(); let data = formats.get(&crate_type).unwrap(); - let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic); - for (cnum, _) in crates { - for lib in sess.cstore.native_libraries(cnum) { + let crates = &trans.crate_info.used_crates_static; + for &(cnum, _) in crates { + for lib in trans.crate_info.native_libraries[&cnum].iter() { if !relevant_lib(sess, &lib) { continue } diff --git a/src/librustc_trans/back/rpath.rs b/src/librustc_trans/back/rpath.rs index 104e7bc6a52bd..8e5e7d376488b 100644 --- a/src/librustc_trans/back/rpath.rs +++ b/src/librustc_trans/back/rpath.rs @@ -17,7 +17,7 @@ use rustc::hir::def_id::CrateNum; use rustc::middle::cstore::LibSource; pub struct RPathConfig<'a> { - pub used_crates: Vec<(CrateNum, LibSource)>, + pub used_crates: &'a [(CrateNum, LibSource)], pub out_filename: PathBuf, pub is_like_osx: bool, pub has_rpath: bool, @@ -36,7 +36,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec { debug!("preparing the RPATH!"); let libs = config.used_crates.clone(); - let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::>(); + let libs = libs.iter().filter_map(|&(_, ref l)| l.option()).collect::>(); let rpaths = get_rpaths(config, &libs); flags.extend_from_slice(&rpaths_to_flags(&rpaths)); diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 971483e91b6f3..b546059b4c51d 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -110,13 +110,13 @@ impl ExportedSymbols { let mut exports = FxHashMap(); exports.insert(LOCAL_CRATE, local_crate); - for cnum in tcx.sess.cstore.crates() { + for &cnum in tcx.crates().iter() { debug_assert!(cnum != LOCAL_CRATE); // If this crate is a plugin and/or a custom derive crate, then // we're not even going to link those in so we skip those crates. - if tcx.sess.cstore.plugin_registrar_fn(cnum).is_some() || - tcx.sess.cstore.derive_registrar_fn(cnum).is_some() { + if tcx.plugin_registrar_fn(cnum).is_some() || + tcx.derive_registrar_fn(cnum).is_some() { continue; } @@ -128,12 +128,9 @@ impl ExportedSymbols { // Down below we'll hardwire all of the symbols to the `Rust` export // level instead. let special_runtime_crate = - tcx.is_panic_runtime(cnum.as_def_id()) || - tcx.sess.cstore.is_compiler_builtins(cnum); + tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum); let crate_exports = tcx - .sess - .cstore .exported_symbols(cnum) .iter() .map(|&def_id| { diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 10b66fb199108..abeb2568cbe1e 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -242,7 +242,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance return name.to_string(); } // Don't mangle foreign items. - return tcx.item_name(def_id).as_str().to_string(); + return tcx.item_name(def_id).to_string(); } if let Some(name) = attr::find_export_name_attr(tcx.sess.diagnostic(), &attrs) { @@ -252,7 +252,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance if attr::contains_name(&attrs, "no_mangle") { // Don't mangle - return tcx.item_name(def_id).as_str().to_string(); + return tcx.item_name(def_id).to_string(); } // We want to compute the "type" of this item. Unfortunately, some diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 3f9b28d3d610c..72e1fc3478954 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -22,6 +22,7 @@ use llvm; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; use llvm::SMDiagnosticRef; use {CrateTranslation, ModuleSource, ModuleTranslation, CompiledModule, ModuleKind}; +use CrateInfo; use rustc::hir::def_id::CrateNum; use rustc::util::common::{time, time_depth, set_time_depth, path2cstr, print_time_passes_entry}; use rustc::util::fs::{link_or_copy, rename_or_copy_remove}; @@ -675,6 +676,7 @@ pub fn start_async_translation(sess: &Session, no_builtins: bool, windows_subsystem: Option, linker_info: LinkerInfo, + crate_info: CrateInfo, no_integrated_as: bool) -> OngoingCrateTranslation { let output_types_override = if no_integrated_as { @@ -774,6 +776,7 @@ pub fn start_async_translation(sess: &Session, let (coordinator_send, coordinator_receive) = channel(); let coordinator_thread = start_executing_work(sess, + &crate_info, shared_emitter, trans_worker_send, coordinator_send.clone(), @@ -788,6 +791,7 @@ pub fn start_async_translation(sess: &Session, windows_subsystem, linker_info, no_integrated_as, + crate_info, regular_module_config: modules_config, metadata_module_config: metadata_config, @@ -1101,6 +1105,7 @@ enum MainThreadWorkerState { } fn start_executing_work(sess: &Session, + crate_info: &CrateInfo, shared_emitter: SharedEmitter, trans_worker_send: Sender, coordinator_send: Sender, @@ -1125,8 +1130,8 @@ fn start_executing_work(sess: &Session, }).expect("failed to spawn helper thread"); let mut each_linked_rlib_for_lto = Vec::new(); - drop(link::each_linked_rlib(sess, &mut |cnum, path| { - if link::ignored_for_lto(sess, cnum) { + drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| { + if link::ignored_for_lto(crate_info, cnum) { return } each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); @@ -1802,6 +1807,7 @@ pub struct OngoingCrateTranslation { windows_subsystem: Option, linker_info: LinkerInfo, no_integrated_as: bool, + crate_info: CrateInfo, output_filenames: OutputFilenames, regular_module_config: ModuleConfig, @@ -1850,6 +1856,7 @@ impl OngoingCrateTranslation { metadata: self.metadata, windows_subsystem: self.windows_subsystem, linker_info: self.linker_info, + crate_info: self.crate_info, modules: compiled_modules.modules, allocator_module: compiled_modules.allocator_module, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index a6c6b0efcfa8c..6cfde9c7bbc73 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -41,7 +41,7 @@ use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::dep_graph::AssertDepGraphSafe; -use rustc::middle::cstore::LinkMeta; +use rustc::middle::cstore::{self, LinkMeta, LinkagePreference}; use rustc::hir::map as hir_map; use rustc::util::common::{time, print_time_passes_entry}; use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType}; @@ -75,6 +75,7 @@ use type_::Type; use type_of; use value::Value; use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet}; +use CrateInfo; use libc::c_uint; use std::ffi::{CStr, CString}; @@ -904,7 +905,7 @@ pub fn find_exported_symbols(tcx: TyCtxt, reachable: &NodeSet) -> NodeSet { match tcx.hir.get(id) { hir_map::NodeForeignItem(..) => { let def_id = tcx.hir.local_def_id(id); - tcx.sess.cstore.is_statically_included_foreign_item(def_id) + tcx.is_statically_included_foreign_item(def_id) } // Only consider nodes that actually have exported symbols. @@ -970,6 +971,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } else { None }; + let crate_info = CrateInfo::new(tcx); // Skip crate items and just output metadata in -Z no-trans mode. if tcx.sess.opts.debugging_opts.no_trans || @@ -987,6 +989,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, no_builtins, None, linker_info, + crate_info, false); ongoing_translation.submit_pre_translated_module_to_llvm(tcx.sess, metadata_module, true); @@ -1039,6 +1042,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, no_builtins, windows_subsystem, linker_info, + crate_info, no_integrated_as); // Translate an allocator shim, if any @@ -1502,3 +1506,46 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a (translation_items, codegen_units) } + +impl CrateInfo { + pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CrateInfo { + let mut info = CrateInfo { + panic_runtime: None, + compiler_builtins: None, + profiler_runtime: None, + sanitizer_runtime: None, + is_no_builtins: FxHashSet(), + native_libraries: FxHashMap(), + used_libraries: tcx.native_libraries(LOCAL_CRATE), + link_args: tcx.link_args(LOCAL_CRATE), + crate_name: FxHashMap(), + used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic), + used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic), + used_crate_source: FxHashMap(), + }; + + for &cnum in tcx.crates().iter() { + info.native_libraries.insert(cnum, tcx.native_libraries(cnum)); + info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string()); + info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum)); + if tcx.is_panic_runtime(cnum) { + info.panic_runtime = Some(cnum); + } + if tcx.is_compiler_builtins(cnum) { + info.compiler_builtins = Some(cnum); + } + if tcx.is_profiler_runtime(cnum) { + info.profiler_runtime = Some(cnum); + } + if tcx.is_sanitizer_runtime(cnum) { + info.sanitizer_runtime = Some(cnum); + } + if tcx.is_no_builtins(cnum) { + info.is_no_builtins.insert(cnum); + } + } + + + return info + } +} diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 76f94565bae51..246eb49ffa674 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -124,13 +124,17 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } - if ccx.use_dll_storage_attrs() && - ccx.sess().cstore.is_dllimport_foreign_item(instance_def_id) - { - unsafe { - llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); + // FIXME(#42293) we should actually track this, but fails too many tests + // today. + tcx.dep_graph.with_ignore(|| { + if ccx.use_dll_storage_attrs() && + tcx.is_dllimport_foreign_item(instance_def_id) + { + unsafe { + llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); + } } - } + }); llfn }; diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 8b864a7fdcfbb..b56fa34e348e5 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -432,7 +432,7 @@ fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0); debug!(" => recursion depth={}", recursion_depth); - let recursion_depth = if Some(def_id) == tcx.lang_items.drop_in_place_fn() { + let recursion_depth = if Some(def_id) == tcx.lang_items().drop_in_place_fn() { // HACK: drop_in_place creates tight monomorphization loops. Give // it more margin. recursion_depth / 4 @@ -550,7 +550,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => { let tcx = self.scx.tcx(); let exchange_malloc_fn_def_id = tcx - .lang_items + .lang_items() .require(ExchangeMallocFnLangItem) .unwrap_or_else(|e| self.scx.sess().fatal(&e)); let instance = Instance::mono(tcx, exchange_malloc_fn_def_id); diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 261792735dcab..d947cd8e71974 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -423,7 +423,7 @@ pub fn langcall(tcx: TyCtxt, msg: &str, li: LangItem) -> DefId { - match tcx.lang_items.require(li) { + match tcx.lang_items().require(li) { Ok(id) => id, Err(s) => { let msg = format!("{} {}", msg, s); @@ -530,7 +530,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); sig.map_bound(|sig| { - let state_did = tcx.lang_items.gen_state().unwrap(); + let state_did = tcx.lang_items().gen_state().unwrap(); let state_adt_ref = tcx.adt_def(state_did); let state_substs = tcx.mk_substs([Kind::from(sig.yield_ty), Kind::from(sig.return_ty)].iter()); diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 310cd6fe9559d..a30a15f75b3af 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -211,12 +211,17 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { g }; - if ccx.use_dll_storage_attrs() && ccx.sess().cstore.is_dllimport_foreign_item(def_id) { - // For foreign (native) libs we know the exact storage type to use. - unsafe { - llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport); + + // FIXME(#42293) we should actually track this, but fails too many tests + // today. + ccx.tcx().dep_graph.with_ignore(|| { + if ccx.use_dll_storage_attrs() && ccx.tcx().is_dllimport_foreign_item(def_id) { + // For foreign (native) libs we know the exact storage type to use. + unsafe { + llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport); + } } - } + }); ccx.instances().borrow_mut().insert(instance, g); ccx.statics().borrow_mut().insert(g, def_id); g diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index f2b07cf6a5831..a5830eb17edb1 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -616,7 +616,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { return llpersonality } let tcx = self.tcx(); - let llfn = match tcx.lang_items.eh_personality() { + let llfn = match tcx.lang_items().eh_personality() { Some(def_id) if !base::wants_msvc_seh(self.sess()) => { callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[])) } @@ -645,7 +645,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { let tcx = self.tcx(); assert!(self.sess().target.target.options.custom_unwind_resume); - if let Some(def_id) = tcx.lang_items.eh_unwind_resume() { + if let Some(def_id) = tcx.lang_items().eh_unwind_resume() { let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[])); unwresume.set(Some(llfn)); return llfn; diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index bcc6aca6149bd..8bd835ac5d114 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1612,7 +1612,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn get_enum_discriminant_name(cx: &CrateContext, def_id: DefId) -> InternedString { - cx.tcx().item_name(def_id).as_str() + cx.tcx().item_name(def_id) } } diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 5dd1c15fd2d6e..6eda865751933 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -189,7 +189,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push_str(&path_element.data.as_interned_str()); } } else { - output.push_str(&cx.tcx().item_name(def_id).as_str()); + output.push_str(&cx.tcx().item_name(def_id)); } } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 9a3c8a5079a2f..8f968a8a6c609 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -104,7 +104,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let sig = tcx.erase_late_bound_regions_and_normalize(&sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); - let name = &*tcx.item_name(def_id).as_str(); + let name = &*tcx.item_name(def_id); let llret_ty = type_of::type_of(ccx, ret_ty); @@ -822,7 +822,7 @@ fn trans_msvc_try<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, catchswitch.add_handler(cs, catchpad.llbb()); let tcx = ccx.tcx(); - let tydesc = match tcx.lang_items.msvc_try_filter() { + let tydesc = match tcx.lang_items().msvc_try_filter() { Some(did) => ::consts::get_static(ccx, did), None => bug!("msvc_try_filter not defined"), }; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 1758e331129d5..ab0c646ccd040 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -66,6 +66,12 @@ pub use back::symbol_names::provide; pub use metadata::LlvmMetadataLoader; pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug}; +use std::rc::Rc; + +use rustc::hir::def_id::CrateNum; +use rustc::util::nodemap::{FxHashSet, FxHashMap}; +use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource}; + pub mod back { mod archive; pub(crate) mod linker; @@ -216,7 +222,24 @@ pub struct CrateTranslation { pub link: rustc::middle::cstore::LinkMeta, pub metadata: rustc::middle::cstore::EncodedMetadata, windows_subsystem: Option, - linker_info: back::linker::LinkerInfo + linker_info: back::linker::LinkerInfo, + crate_info: CrateInfo, +} + +// Misc info we load from metadata to persist beyond the tcx +pub struct CrateInfo { + panic_runtime: Option, + compiler_builtins: Option, + profiler_runtime: Option, + sanitizer_runtime: Option, + is_no_builtins: FxHashSet, + native_libraries: FxHashMap>>, + crate_name: FxHashMap, + used_libraries: Rc>, + link_args: Rc>, + used_crate_source: FxHashMap>, + used_crates_static: Vec<(CrateNum, LibSource)>, + used_crates_dynamic: Vec<(CrateNum, LibSource)>, } __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index 95b76d32bf848..949b9fe71ca64 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -114,7 +114,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> { }, .. }), ref args, .. - } if Some(def_id) == self.cx.ccx.tcx().lang_items.box_free_fn() => { + } if Some(def_id) == self.cx.ccx.tcx().lang_items().box_free_fn() => { // box_free(x) shares with `drop x` the property that it // is not guaranteed to be statically dominated by the // definition of x, so x must always be in an alloca. diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index bba3b1fa5baee..0f42a244a1ff9 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -445,7 +445,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // Handle intrinsics old trans wants Expr's for, ourselves. let intrinsic = match def { Some(ty::InstanceDef::Intrinsic(def_id)) - => Some(bcx.tcx().item_name(def_id).as_str()), + => Some(bcx.tcx().item_name(def_id)), _ => None }; let intrinsic = intrinsic.as_ref().map(|s| &s[..]); diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 9987c9c33102d..1109f34a1482e 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -365,7 +365,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } if let Some((ref dest, target)) = *destination { let result = if fn_ty.fn_sig(tcx).abi() == Abi::RustIntrinsic { - match &tcx.item_name(def_id).as_str()[..] { + match &tcx.item_name(def_id)[..] { "size_of" => { let llval = C_uint(self.ccx, self.ccx.size_of(substs.type_at(0))); @@ -610,7 +610,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { match operand.ty.sty { ty::TyClosure(def_id, substs) => { // Get the def_id for FnOnce::call_once - let fn_once = tcx.lang_items.fn_once_trait().unwrap(); + let fn_once = tcx.lang_items().fn_once_trait().unwrap(); let call_once = tcx .global_tcx().associated_items(fn_once) .find(|it| it.kind == ty::AssociatedKind::Method) diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 096f43e44ab0f..34dec57543a2b 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -482,7 +482,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let box_ty = bcx.tcx().mk_box(content_ty); // Allocate space: - let def_id = match bcx.tcx().lang_items.require(ExchangeMallocFnLangItem) { + let def_id = match bcx.tcx().lang_items().require(ExchangeMallocFnLangItem) { Ok(id) => id, Err(s) => { bcx.sess().fatal(&format!("allocation of `{}` {}", box_ty, s)); diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 4989ca8cc938c..9a7f1524d209f 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -31,7 +31,7 @@ fn fn_once_adapter_instance<'a, 'tcx>( debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs); - let fn_once = tcx.lang_items.fn_once_trait().unwrap(); + let fn_once = tcx.lang_items().fn_once_trait().unwrap(); let call_once = tcx.associated_items(fn_once) .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap().def_id; @@ -132,7 +132,7 @@ fn resolve_associated_item<'a, 'tcx>( } } traits::VtableClosure(closure_data) => { - let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap(); + let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap(); resolve_closure(scx, closure_data.closure_def_id, closure_data.substs, trait_closure_kind) } @@ -149,7 +149,7 @@ fn resolve_associated_item<'a, 'tcx>( substs: rcvr_substs } } - traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items.clone_trait() => { + traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items().clone_trait() => { Instance { def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()), substs: rcvr_substs @@ -187,7 +187,7 @@ pub fn resolve<'a, 'tcx>( ty::InstanceDef::Intrinsic(def_id) } _ => { - if Some(def_id) == scx.tcx().lang_items.drop_in_place_fn() { + if Some(def_id) == scx.tcx().lang_items().drop_in_place_fn() { let ty = substs.type_at(0); if glue::needs_drop_glue(scx, ty) { debug!(" => nontrivial drop glue"); @@ -224,7 +224,7 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx target_ty: Ty<'tcx>) -> CustomCoerceUnsized { let trait_ref = ty::Binder(ty::TraitRef { - def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(), + def_id: scx.tcx().lang_items().coerce_unsized_trait().unwrap(), substs: scx.tcx().mk_substs_trait(source_ty, &[target_ty]) }); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ee1e6bd950fa1..2583d18652dc5 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -96,22 +96,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { -> ty::Region<'tcx> { let tcx = self.tcx(); - let r = match tcx.named_region_map.defs.get(&lifetime.id) { - Some(&rl::Region::Static) => { + let hir_id = tcx.hir.node_to_hir_id(lifetime.id); + let r = match tcx.named_region(hir_id) { + Some(rl::Region::Static) => { tcx.types.re_static } - Some(&rl::Region::LateBound(debruijn, id)) => { + Some(rl::Region::LateBound(debruijn, id)) => { let name = tcx.hir.name(id); tcx.mk_region(ty::ReLateBound(debruijn, ty::BrNamed(tcx.hir.local_def_id(id), name))) } - Some(&rl::Region::LateBoundAnon(debruijn, index)) => { + Some(rl::Region::LateBoundAnon(debruijn, index)) => { tcx.mk_region(ty::ReLateBound(debruijn, ty::BrAnon(index))) } - Some(&rl::Region::EarlyBound(index, id)) => { + Some(rl::Region::EarlyBound(index, id)) => { let name = tcx.hir.name(id); tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: tcx.hir.local_def_id(id), @@ -120,7 +121,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { })) } - Some(&rl::Region::Free(scope, id)) => { + Some(rl::Region::Free(scope, id)) => { let name = tcx.hir.name(id); tcx.mk_region(ty::ReFree(ty::FreeRegion { scope, @@ -627,7 +628,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.ast_region_to_region(lifetime, None) } else { self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { - if tcx.named_region_map.defs.contains_key(&lifetime.id) { + let hir_id = tcx.hir.node_to_hir_id(lifetime.id); + if tcx.named_region(hir_id).is_some() { self.ast_region_to_region(lifetime, None) } else { self.re_infer(span, None).unwrap_or_else(|| { @@ -1286,8 +1288,8 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, Def::Trait(trait_did) => { // Checks whether `trait_did` refers to one of the builtin // traits, like `Send`, and adds it to `auto_traits` if so. - if Some(trait_did) == tcx.lang_items.send_trait() || - Some(trait_did) == tcx.lang_items.sync_trait() { + if Some(trait_did) == tcx.lang_items().send_trait() || + Some(trait_did) == tcx.lang_items().sync_trait() { let segments = &bound.trait_ref.path.segments; let parameters = &segments[segments.len() - 1].parameters; if !parameters.types.is_empty() { @@ -1400,7 +1402,7 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { // If it could be sized, and is, add the sized predicate if self.implicitly_sized { - if let Some(sized) = tcx.lang_items.sized_trait() { + if let Some(sized) = tcx.lang_items().sized_trait() { let trait_ref = ty::TraitRef { def_id: sized, substs: tcx.mk_substs_trait(param_ty, &[]) diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index e0e946a9c63fa..a25deb7685af5 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { // let trait_ref = TraitRef { - def_id: match tcx.lang_items.deref_trait() { + def_id: match tcx.lang_items().deref_trait() { Some(f) => f, None => return None, }, diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 5b9d4af08e069..866949220b5df 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -28,7 +28,7 @@ use rustc::hir; /// to `trait_id` (this only cares about the trait, not the specific /// method that is called) pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefId) { - if tcx.lang_items.drop_trait() == Some(trait_id) { + if tcx.lang_items().drop_trait() == Some(trait_id) { struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method") .span_label(span, "explicit destructor calls not allowed") .emit(); @@ -157,9 +157,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { MethodCallee<'tcx>)> { // Try the options that are least restrictive on the caller first. for &(opt_trait_def_id, method_name, borrow) in - &[(self.tcx.lang_items.fn_trait(), Symbol::intern("call"), true), - (self.tcx.lang_items.fn_mut_trait(), Symbol::intern("call_mut"), true), - (self.tcx.lang_items.fn_once_trait(), Symbol::intern("call_once"), false)] { + &[(self.tcx.lang_items().fn_trait(), Symbol::intern("call"), true), + (self.tcx.lang_items().fn_mut_trait(), Symbol::intern("call_mut"), true), + (self.tcx.lang_items().fn_once_trait(), Symbol::intern("call_once"), false)] { let trait_def_id = match opt_trait_def_id { Some(def_id) => def_id, None => continue, diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index a768271f3b825..aa2b9c1e03815 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -139,7 +139,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }) .next(); let kind = object_type.principal() - .and_then(|p| self.tcx.lang_items.fn_trait_kind(p.def_id())); + .and_then(|p| self.tcx.lang_items().fn_trait_kind(p.def_id())); (sig, kind) } ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), @@ -204,7 +204,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Predicate::ClosureKind(..) => None, }; opt_trait_ref.and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid)) - .and_then(|tr| self.tcx.lang_items.fn_trait_kind(tr.def_id())) + .and_then(|tr| self.tcx.lang_items().fn_trait_kind(tr.def_id())) }) .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur)))); @@ -223,7 +223,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let trait_ref = projection.to_poly_trait_ref(tcx); - if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() { + if tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_none() { return None; } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index e406ce845a6d1..cfcdbcc11959b 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -438,8 +438,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tcx> { debug!("coerce_unsized(source={:?}, target={:?})", source, target); - let traits = (self.tcx.lang_items.unsize_trait(), - self.tcx.lang_items.coerce_unsized_trait()); + let traits = (self.tcx.lang_items().unsize_trait(), + self.tcx.lang_items().coerce_unsized_trait()); let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits { (u, cu) } else { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 08ec3bf74a71d..852134bbee315 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -540,7 +540,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn predicates_require_illegal_sized_bound(&self, predicates: &ty::InstantiatedPredicates<'tcx>) -> bool { - let sized_def_id = match self.tcx.lang_items.sized_trait() { + let sized_def_id = match self.tcx.lang_items().sized_trait() { Some(def_id) => def_id, None => return false, }; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index ba74c902f55e0..3771d330f6dd3 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -393,6 +393,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_probe(&mut self, self_ty: Ty<'tcx>) { debug!("assemble_probe: self_ty={:?}", self_ty); + let lang_items = self.tcx.lang_items(); match self_ty.sty { ty::TyDynamic(ref data, ..) => { @@ -408,79 +409,79 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.assemble_inherent_candidates_from_param(self_ty, p); } ty::TyChar => { - let lang_def_id = self.tcx.lang_items.char_impl(); + let lang_def_id = lang_items.char_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyStr => { - let lang_def_id = self.tcx.lang_items.str_impl(); + let lang_def_id = lang_items.str_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TySlice(_) => { - let lang_def_id = self.tcx.lang_items.slice_impl(); + let lang_def_id = lang_items.slice_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { - let lang_def_id = self.tcx.lang_items.const_ptr_impl(); + let lang_def_id = lang_items.const_ptr_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { - let lang_def_id = self.tcx.lang_items.mut_ptr_impl(); + let lang_def_id = lang_items.mut_ptr_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyInt(ast::IntTy::I8) => { - let lang_def_id = self.tcx.lang_items.i8_impl(); + let lang_def_id = lang_items.i8_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyInt(ast::IntTy::I16) => { - let lang_def_id = self.tcx.lang_items.i16_impl(); + let lang_def_id = lang_items.i16_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyInt(ast::IntTy::I32) => { - let lang_def_id = self.tcx.lang_items.i32_impl(); + let lang_def_id = lang_items.i32_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyInt(ast::IntTy::I64) => { - let lang_def_id = self.tcx.lang_items.i64_impl(); + let lang_def_id = lang_items.i64_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyInt(ast::IntTy::I128) => { - let lang_def_id = self.tcx.lang_items.i128_impl(); + let lang_def_id = lang_items.i128_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyInt(ast::IntTy::Is) => { - let lang_def_id = self.tcx.lang_items.isize_impl(); + let lang_def_id = lang_items.isize_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyUint(ast::UintTy::U8) => { - let lang_def_id = self.tcx.lang_items.u8_impl(); + let lang_def_id = lang_items.u8_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyUint(ast::UintTy::U16) => { - let lang_def_id = self.tcx.lang_items.u16_impl(); + let lang_def_id = lang_items.u16_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyUint(ast::UintTy::U32) => { - let lang_def_id = self.tcx.lang_items.u32_impl(); + let lang_def_id = lang_items.u32_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyUint(ast::UintTy::U64) => { - let lang_def_id = self.tcx.lang_items.u64_impl(); + let lang_def_id = lang_items.u64_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyUint(ast::UintTy::U128) => { - let lang_def_id = self.tcx.lang_items.u128_impl(); + let lang_def_id = lang_items.u128_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyUint(ast::UintTy::Us) => { - let lang_def_id = self.tcx.lang_items.usize_impl(); + let lang_def_id = lang_items.usize_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyFloat(ast::FloatTy::F32) => { - let lang_def_id = self.tcx.lang_items.f32_impl(); + let lang_def_id = lang_items.f32_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::TyFloat(ast::FloatTy::F64) => { - let lang_def_id = self.tcx.lang_items.f64_impl(); + let lang_def_id = lang_items.f64_impl(); self.assemble_inherent_impl_for_primitive(lang_def_id); } _ => {} diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f2d7842e473f6..7fa3dd7472db8 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -45,7 +45,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::TyFnPtr(_) => true, // If it's not a simple function, look for things which implement FnOnce _ => { - let fn_once = match tcx.lang_items.require(FnOnceTraitLangItem) { + let fn_once = match tcx.lang_items().require(FnOnceTraitLangItem) { Ok(fn_once) => fn_once, Err(..) => return false, }; @@ -552,14 +552,14 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> if !external_mods.insert(def_id) { return; } - for child in tcx.sess.cstore.item_children(def_id, tcx.sess) { + for child in tcx.item_children(def_id).iter() { handle_external_def(tcx, traits, external_mods, child.def) } } _ => {} } } - for cnum in tcx.sess.cstore.crates() { + for &cnum in tcx.crates().iter() { let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3f210ea1737b7..0a8d2129a890d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2296,13 +2296,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn resolve_lvalue_op(&self, op: LvalueOp, is_mut: bool) -> (Option, Symbol) { let (tr, name) = match (op, is_mut) { (LvalueOp::Deref, false) => - (self.tcx.lang_items.deref_trait(), "deref"), + (self.tcx.lang_items().deref_trait(), "deref"), (LvalueOp::Deref, true) => - (self.tcx.lang_items.deref_mut_trait(), "deref_mut"), + (self.tcx.lang_items().deref_mut_trait(), "deref_mut"), (LvalueOp::Index, false) => - (self.tcx.lang_items.index_trait(), "index"), + (self.tcx.lang_items().index_trait(), "index"), (LvalueOp::Index, true) => - (self.tcx.lang_items.index_mut_trait(), "index_mut"), + (self.tcx.lang_items().index_mut_trait(), "index_mut"), }; (tr, Symbol::intern(name)) } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index a4e1fdaf39e29..a3dd81fdddee3 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -362,7 +362,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn lookup_op_method(&self, lhs_ty: Ty<'tcx>, other_tys: &[Ty<'tcx>], op: Op) -> Result, ()> { - let lang = &self.tcx.lang_items; + let lang = self.tcx.lang_items(); let span = match op { Op::Binary(op, _) => op.span, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 69f045ab4e96a..9c19aef5992e6 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -539,7 +539,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { { let mut err = error_392(self.tcx, span, param_name); - let suggested_marker_id = self.tcx.lang_items.phantom_data(); + let suggested_marker_id = self.tcx.lang_items().phantom_data(); match suggested_marker_id { Some(def_id) => { err.help( diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 3da154e0689ad..93f15775b1560 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -14,8 +14,9 @@ use rustc::ty::TyCtxt; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; -use rustc::hir; +use rustc::hir::def_id::LOCAL_CRATE; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir; use rustc::util::nodemap::DefIdSet; struct CheckVisitor<'a, 'tcx: 'a> { @@ -25,7 +26,8 @@ struct CheckVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> CheckVisitor<'a, 'tcx> { fn check_import(&self, id: ast::NodeId, span: Span) { - if !self.tcx.maybe_unused_trait_imports.contains(&id) { + let hir_id = self.tcx.hir.node_to_hir_id(id); + if !self.tcx.maybe_unused_trait_import(hir_id) { return; } @@ -73,14 +75,20 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = CheckVisitor { tcx, used_trait_imports }; tcx.hir.krate().visit_all_item_likes(&mut visitor); - for &(id, span) in &tcx.maybe_unused_extern_crates { - let cnum = tcx.sess.cstore.extern_mod_stmt_cnum(id).unwrap().as_def_id(); - if !tcx.is_compiler_builtins(cnum) - && !tcx.is_panic_runtime(cnum) - && !tcx.has_global_allocator(cnum) { - let lint = lint::builtin::UNUSED_EXTERN_CRATES; - let msg = "unused extern crate"; - tcx.lint_node(lint, id, span, msg); - } + for &(hir_id, span) in tcx.maybe_unused_extern_crates(LOCAL_CRATE).iter() { + let cnum = tcx.extern_mod_stmt_cnum(hir_id).unwrap(); + if tcx.is_compiler_builtins(cnum) { + continue + } + if tcx.is_panic_runtime(cnum) { + continue + } + if tcx.has_global_allocator(cnum) { + continue + } + let id = tcx.hir.definitions().find_node_for_hir_id(hir_id); + let lint = lint::builtin::UNUSED_EXTERN_CRATES; + let msg = "unused extern crate"; + tcx.lint_node(lint, id, span, msg); } } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index b421fdfe8d813..fedfa51d61d11 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -28,9 +28,9 @@ use rustc::hir::{self, ItemImpl}; pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) { Checker { tcx, trait_def_id } - .check(tcx.lang_items.drop_trait(), visit_implementation_of_drop) - .check(tcx.lang_items.copy_trait(), visit_implementation_of_copy) - .check(tcx.lang_items.coerce_unsized_trait(), + .check(tcx.lang_items().drop_trait(), visit_implementation_of_drop) + .check(tcx.lang_items().copy_trait(), visit_implementation_of_copy) + .check(tcx.lang_items().coerce_unsized_trait(), visit_implementation_of_coerce_unsized); } @@ -176,9 +176,9 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); - let coerce_unsized_trait = tcx.lang_items.coerce_unsized_trait().unwrap(); + let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap(); - let unsize_trait = match tcx.lang_items.require(UnsizeTraitLangItem) { + let unsize_trait = match tcx.lang_items().require(UnsizeTraitLangItem) { Ok(id) => id, Err(err) => { tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index e24d766002187..15e15abfb3606 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -112,6 +112,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { let def_id = self.tcx.hir.local_def_id(item.id); let self_ty = self.tcx.type_of(def_id); + let lang_items = self.tcx.lang_items(); match self_ty.sty { ty::TyAdt(def, _) => { self.check_def_id(item, def.did); @@ -121,133 +122,133 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { } ty::TyChar => { self.check_primitive_impl(def_id, - self.tcx.lang_items.char_impl(), + lang_items.char_impl(), "char", "char", item.span); } ty::TyStr => { self.check_primitive_impl(def_id, - self.tcx.lang_items.str_impl(), + lang_items.str_impl(), "str", "str", item.span); } ty::TySlice(_) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.slice_impl(), + lang_items.slice_impl(), "slice", "[T]", item.span); } ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.const_ptr_impl(), + lang_items.const_ptr_impl(), "const_ptr", "*const T", item.span); } ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.mut_ptr_impl(), + lang_items.mut_ptr_impl(), "mut_ptr", "*mut T", item.span); } ty::TyInt(ast::IntTy::I8) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.i8_impl(), + lang_items.i8_impl(), "i8", "i8", item.span); } ty::TyInt(ast::IntTy::I16) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.i16_impl(), + lang_items.i16_impl(), "i16", "i16", item.span); } ty::TyInt(ast::IntTy::I32) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.i32_impl(), + lang_items.i32_impl(), "i32", "i32", item.span); } ty::TyInt(ast::IntTy::I64) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.i64_impl(), + lang_items.i64_impl(), "i64", "i64", item.span); } ty::TyInt(ast::IntTy::I128) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.i128_impl(), + lang_items.i128_impl(), "i128", "i128", item.span); } ty::TyInt(ast::IntTy::Is) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.isize_impl(), + lang_items.isize_impl(), "isize", "isize", item.span); } ty::TyUint(ast::UintTy::U8) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.u8_impl(), + lang_items.u8_impl(), "u8", "u8", item.span); } ty::TyUint(ast::UintTy::U16) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.u16_impl(), + lang_items.u16_impl(), "u16", "u16", item.span); } ty::TyUint(ast::UintTy::U32) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.u32_impl(), + lang_items.u32_impl(), "u32", "u32", item.span); } ty::TyUint(ast::UintTy::U64) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.u64_impl(), + lang_items.u64_impl(), "u64", "u64", item.span); } ty::TyUint(ast::UintTy::U128) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.u128_impl(), + lang_items.u128_impl(), "u128", "u128", item.span); } ty::TyUint(ast::UintTy::Us) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.usize_impl(), + lang_items.usize_impl(), "usize", "usize", item.span); } ty::TyFloat(ast::FloatTy::F32) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.f32_impl(), + lang_items.f32_impl(), "f32", "f32", item.span); } ty::TyFloat(ast::FloatTy::F64) => { self.check_primitive_impl(def_id, - self.tcx.lang_items.f64_impl(), + lang_items.f64_impl(), "f64", "f64", item.span); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 165be49f7603d..6109fc57b0dfc 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -51,7 +51,7 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_def_id: DefId) { let did = Some(trait_def_id); - let li = &tcx.lang_items; + let li = tcx.lang_items(); // Disallow *all* explicit impls of `Sized` and `Unsize` for now. if did == li.sized_trait() { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c177623af48fb..e4ca0f82ea1a0 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -812,7 +812,8 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) { if self.has_late_bound_regions.is_some() { return } - match self.tcx.named_region_map.defs.get(<.id).cloned() { + let hir_id = self.tcx.hir.node_to_hir_id(lt.id); + match self.tcx.named_region(hir_id) { Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {} Some(rl::Region::LateBound(debruijn, _)) | Some(rl::Region::LateBoundAnon(debruijn, _)) @@ -830,7 +831,8 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx, binder_depth: 1, has_late_bound_regions: None }; for lifetime in &generics.lifetimes { - if tcx.named_region_map.late_bound.contains(&lifetime.lifetime.id) { + let hir_id = tcx.hir.node_to_hir_id(lifetime.lifetime.id); + if tcx.is_late_bound(hir_id) { return Some(lifetime.lifetime.span); } } @@ -987,8 +989,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }).collect::>(); - let object_lifetime_defaults = - tcx.named_region_map.object_lifetime_defaults.get(&node_id); + let hir_id = tcx.hir.node_to_hir_id(node_id); + let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id); // Now create the real type parameters. let type_start = own_start + regions.len() as u32; @@ -1014,7 +1016,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: tcx.hir.local_def_id(p.id), has_default: p.default.is_some(), object_lifetime_default: - object_lifetime_defaults.map_or(rl::Set1::Empty, |o| o[i]), + object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]), pure_wrt_drop: p.pure_wrt_drop, } }); @@ -1307,7 +1309,7 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, } } - let kind_id = tcx.lang_items.require(SizedTraitLangItem); + let kind_id = tcx.lang_items().require(SizedTraitLangItem); match unbound { Some(ref tpb) => { // FIXME(#8559) currently requires the unbound to be built-in. @@ -1343,7 +1345,10 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( ast_generics .lifetimes .iter() - .filter(move |l| !tcx.named_region_map.late_bound.contains(&l.lifetime.id)) + .filter(move |l| { + let hir_id = tcx.hir.node_to_hir_id(l.lifetime.id); + !tcx.is_late_bound(hir_id) + }) } fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index c624b11c5eca2..6062ac96ada78 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -94,17 +94,18 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx> } fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec)> { + let lang_items = tcx.lang_items(); let all = vec![ - (tcx.lang_items.phantom_data(), vec![ty::Covariant]), - (tcx.lang_items.unsafe_cell_type(), vec![ty::Invariant]), + (lang_items.phantom_data(), vec![ty::Covariant]), + (lang_items.unsafe_cell_type(), vec![ty::Invariant]), // Deprecated: - (tcx.lang_items.covariant_type(), vec![ty::Covariant]), - (tcx.lang_items.contravariant_type(), vec![ty::Contravariant]), - (tcx.lang_items.invariant_type(), vec![ty::Invariant]), - (tcx.lang_items.covariant_lifetime(), vec![ty::Covariant]), - (tcx.lang_items.contravariant_lifetime(), vec![ty::Contravariant]), - (tcx.lang_items.invariant_lifetime(), vec![ty::Invariant]), + (lang_items.covariant_type(), vec![ty::Covariant]), + (lang_items.contravariant_type(), vec![ty::Contravariant]), + (lang_items.invariant_type(), vec![ty::Invariant]), + (lang_items.covariant_lifetime(), vec![ty::Covariant]), + (lang_items.contravariant_lifetime(), vec![ty::Contravariant]), + (lang_items.invariant_lifetime(), vec![ty::Invariant]), ]; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 5d39d1d27f4c3..70563b3d26713 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -120,7 +120,7 @@ pub fn load_attrs(cx: &DocContext, did: DefId) -> clean::Attributes { /// These names are used later on by HTML rendering to generate things like /// source links back to the original item. pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) { - let crate_name = cx.tcx.sess.cstore.crate_name(did.krate).to_string(); + let crate_name = cx.tcx.crate_name(did.krate).to_string(); let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| { // extern blocks have an empty name let s = elem.data.to_string(); @@ -236,31 +236,34 @@ pub fn build_impls(cx: &DocContext, did: DefId) -> Vec { cx.populated_all_crate_impls.set(true); - for did in tcx.sess.cstore.implementations_of_trait(None) { - build_impl(cx, did, &mut impls); + for &cnum in tcx.crates().iter() { + for did in tcx.all_trait_implementations(cnum).iter() { + build_impl(cx, *did, &mut impls); + } } // Also try to inline primitive impls from other crates. + let lang_items = tcx.lang_items(); let primitive_impls = [ - tcx.lang_items.isize_impl(), - tcx.lang_items.i8_impl(), - tcx.lang_items.i16_impl(), - tcx.lang_items.i32_impl(), - tcx.lang_items.i64_impl(), - tcx.lang_items.i128_impl(), - tcx.lang_items.usize_impl(), - tcx.lang_items.u8_impl(), - tcx.lang_items.u16_impl(), - tcx.lang_items.u32_impl(), - tcx.lang_items.u64_impl(), - tcx.lang_items.u128_impl(), - tcx.lang_items.f32_impl(), - tcx.lang_items.f64_impl(), - tcx.lang_items.char_impl(), - tcx.lang_items.str_impl(), - tcx.lang_items.slice_impl(), - tcx.lang_items.const_ptr_impl(), - tcx.lang_items.mut_ptr_impl(), + lang_items.isize_impl(), + lang_items.i8_impl(), + lang_items.i16_impl(), + lang_items.i32_impl(), + lang_items.i64_impl(), + lang_items.i128_impl(), + lang_items.usize_impl(), + lang_items.u8_impl(), + lang_items.u16_impl(), + lang_items.u32_impl(), + lang_items.u64_impl(), + lang_items.u128_impl(), + lang_items.f32_impl(), + lang_items.f64_impl(), + lang_items.char_impl(), + lang_items.str_impl(), + lang_items.slice_impl(), + lang_items.const_ptr_impl(), + lang_items.mut_ptr_impl(), ]; for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) { @@ -399,7 +402,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { clean::RegionBound(..) => unreachable!(), } }); - if trait_.def_id() == tcx.lang_items.deref_trait() { + if trait_.def_id() == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } @@ -443,9 +446,9 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module { // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. let mut visited = FxHashSet(); - for item in cx.tcx.sess.cstore.item_children(did, cx.tcx.sess) { + for &item in cx.tcx.item_children(did).iter() { let def_id = item.def.def_id(); - if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public { + if cx.tcx.visibility(def_id) == ty::Visibility::Public { if !visited.insert(def_id) { continue } if let Some(i) = try_inline(cx, item.def, item.ident.name) { items.extend(i) @@ -471,7 +474,7 @@ impl hir::print::PpAnn for InlinedConst { } fn print_inlined_const(cx: &DocContext, did: DefId) -> String { - let body = cx.tcx.sess.cstore.item_body(cx.tcx, did); + let body = cx.tcx.extern_const_body(did); let inlined = InlinedConst { nested_bodies: cx.tcx.item_body_nested_bodies(did) }; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index aab44ddce0e6a..3a5786f668919 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -125,13 +125,13 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { { let mut r = cx.renderinfo.borrow_mut(); - r.deref_trait_did = cx.tcx.lang_items.deref_trait(); - r.deref_mut_trait_did = cx.tcx.lang_items.deref_mut_trait(); - r.owned_box_did = cx.tcx.lang_items.owned_box(); + r.deref_trait_did = cx.tcx.lang_items().deref_trait(); + r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); + r.owned_box_did = cx.tcx.lang_items().owned_box(); } let mut externs = Vec::new(); - for cnum in cx.sess().cstore.crates() { + for &cnum in cx.tcx.crates().iter() { externs.push((cnum, cnum.clean(cx))); // Analyze doc-reachability for extern items LibEmbargoVisitor::new(cx).visit_lib(cnum); @@ -244,7 +244,7 @@ impl Clean for CrateNum { } }).collect() } else { - cx.tcx.sess.cstore.item_children(root, cx.tcx.sess).iter().map(|item| item.def) + cx.tcx.item_children(root).iter().map(|item| item.def) .filter_map(as_primitive).collect() }; @@ -672,7 +672,7 @@ impl TyParamBound { fn maybe_sized(cx: &DocContext) -> TyParamBound { let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), + let path = external_path(cx, &cx.tcx.item_name(did), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); TraitBound(PolyTrait { @@ -689,7 +689,7 @@ impl TyParamBound { fn is_sized_bound(&self, cx: &DocContext) -> bool { use rustc::hir::TraitBoundModifier as TBM; if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { - if trait_.def_id() == cx.tcx.lang_items.sized_trait() { + if trait_.def_id() == cx.tcx.lang_items().sized_trait() { return true; } } @@ -713,7 +713,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, has_self: boo match trait_did { // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C - Some(did) if cx.tcx.lang_items.fn_trait_kind(did).is_some() => { + Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => { assert_eq!(types.len(), 1); let inputs = match types[0].sty { ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(), @@ -763,7 +763,7 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option, has_self impl<'tcx> Clean for ty::TraitRef<'tcx> { fn clean(&self, cx: &DocContext) -> TyParamBound { inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait); - let path = external_path(cx, &cx.tcx.item_name(self.def_id).as_str(), + let path = external_path(cx, &cx.tcx.item_name(self.def_id), Some(self.def_id), true, vec![], self.substs); debug!("ty::TraitRef\n subst: {:?}\n", self.substs); @@ -830,7 +830,8 @@ impl Lifetime { impl Clean for hir::Lifetime { fn clean(&self, cx: &DocContext) -> Lifetime { - let def = cx.tcx.named_region_map.defs.get(&self.id).cloned(); + let hir_id = cx.tcx.hir.node_to_hir_id(self.id); + let def = cx.tcx.named_region(hir_id); match def { Some(rl::Region::EarlyBound(_, node_id)) | Some(rl::Region::LateBound(_, node_id)) | @@ -1914,7 +1915,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { AdtKind::Enum => TypeKind::Enum, }; inline::record_extern_fqn(cx, did, kind); - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), + let path = external_path(cx, &cx.tcx.item_name(did), None, false, vec![], substs); ResolvedPath { path, @@ -1932,7 +1933,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { reg.clean(cx).map(|b| typarams.push(RegionBound(b))); for did in obj.auto_traits() { let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), + let path = external_path(cx, &cx.tcx.item_name(did), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); let bound = TraitBound(PolyTrait { @@ -1955,7 +1956,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { }); } - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), + let path = external_path(cx, &cx.tcx.item_name(did), Some(did), false, bindings, principal.0.substs); ResolvedPath { path, @@ -2525,7 +2526,7 @@ impl Clean> for doctree::Impl { // If this impl block is an implementation of the Deref trait, then we // need to try inlining the target's inherent impl blocks as well. - if trait_.def_id() == cx.tcx.lang_items.deref_trait() { + if trait_.def_id() == cx.tcx.lang_items().deref_trait() { build_deref_target_impls(cx, &items, &mut ret); } @@ -2581,27 +2582,27 @@ fn build_deref_target_impls(cx: &DocContext, } }; let did = match primitive { - Isize => tcx.lang_items.isize_impl(), - I8 => tcx.lang_items.i8_impl(), - I16 => tcx.lang_items.i16_impl(), - I32 => tcx.lang_items.i32_impl(), - I64 => tcx.lang_items.i64_impl(), - I128 => tcx.lang_items.i128_impl(), - Usize => tcx.lang_items.usize_impl(), - U8 => tcx.lang_items.u8_impl(), - U16 => tcx.lang_items.u16_impl(), - U32 => tcx.lang_items.u32_impl(), - U64 => tcx.lang_items.u64_impl(), - U128 => tcx.lang_items.u128_impl(), - F32 => tcx.lang_items.f32_impl(), - F64 => tcx.lang_items.f64_impl(), - Char => tcx.lang_items.char_impl(), + Isize => tcx.lang_items().isize_impl(), + I8 => tcx.lang_items().i8_impl(), + I16 => tcx.lang_items().i16_impl(), + I32 => tcx.lang_items().i32_impl(), + I64 => tcx.lang_items().i64_impl(), + I128 => tcx.lang_items().i128_impl(), + Usize => tcx.lang_items().usize_impl(), + U8 => tcx.lang_items().u8_impl(), + U16 => tcx.lang_items().u16_impl(), + U32 => tcx.lang_items().u32_impl(), + U64 => tcx.lang_items().u64_impl(), + U128 => tcx.lang_items().u128_impl(), + F32 => tcx.lang_items().f32_impl(), + F64 => tcx.lang_items().f64_impl(), + Char => tcx.lang_items().char_impl(), Bool => None, - Str => tcx.lang_items.str_impl(), - Slice => tcx.lang_items.slice_impl(), - Array => tcx.lang_items.slice_impl(), + Str => tcx.lang_items().str_impl(), + Slice => tcx.lang_items().slice_impl(), + Array => tcx.lang_items().slice_impl(), Tuple => None, - RawPointer => tcx.lang_items.const_ptr_impl(), + RawPointer => tcx.lang_items().const_ptr_impl(), Reference => None, Fn => None, }; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 1f33cd7765164..d354d726ff703 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -207,8 +207,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { continue // These are `krate.exported_macros`, handled in `self.visit()`. } - let imported_from = self.cx.sess().cstore.original_crate_name(def_id.krate); - let def = match self.cx.sess().cstore.load_macro(def_id, self.cx.sess()) { + let imported_from = self.cx.tcx.original_crate_name(def_id.krate); + let cstore = &self.cx.sess().cstore; + let def = match cstore.load_macro_untracked(def_id, self.cx.sess()) { LoadedMacro::MacroDef(macro_def) => macro_def, // FIXME(jseyfried): document proc macro reexports LoadedMacro::ProcMacro(..) => continue, @@ -371,9 +372,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { _ if self.inlining && item.vis != hir::Public => {} hir::ItemGlobalAsm(..) => {} hir::ItemExternCrate(ref p) => { - let cstore = &self.cx.sess().cstore; + let hir_id = self.cx.tcx.hir.node_to_hir_id(item.id); om.extern_crates.push(ExternCrate { - cnum: cstore.extern_mod_stmt_cnum(item.id) + cnum: self.cx.tcx.extern_mod_stmt_cnum(hir_id) .unwrap_or(LOCAL_CRATE), name, path: p.map(|x|x.to_string()), diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 7b5b27c5565cb..9f75388238f0c 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::{AccessLevels, AccessLevel}; use rustc::hir::def::Def; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; @@ -25,7 +24,6 @@ use clean::{AttributesExt, NestedAttributesExt}; /// specific rustdoc annotations into account (i.e. `doc(hidden)`) pub struct LibEmbargoVisitor<'a, 'b: 'a, 'tcx: 'b> { cx: &'a ::core::DocContext<'b, 'tcx>, - cstore: &'a CrateStore, // Accessibility levels for reachable nodes access_levels: RefMut<'a, AccessLevels>, // Previous accessibility level, None means unreachable @@ -38,7 +36,6 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { pub fn new(cx: &'a ::core::DocContext<'b, 'tcx>) -> LibEmbargoVisitor<'a, 'b, 'tcx> { LibEmbargoVisitor { cx, - cstore: &*cx.sess().cstore, access_levels: cx.access_levels.borrow_mut(), prev_level: Some(AccessLevel::Public), visited_mods: FxHashSet() @@ -70,14 +67,14 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { return; } - for item in self.cstore.item_children(def_id, self.cx.tcx.sess) { + for item in self.cx.tcx.item_children(def_id).iter() { self.visit_item(item.def); } } fn visit_item(&mut self, def: Def) { let def_id = def.def_id(); - let vis = self.cstore.visibility(def_id); + let vis = self.cx.tcx.visibility(def_id); let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { diff --git a/src/test/compile-fail/empty-linkname.rs b/src/test/compile-fail/empty-linkname.rs index cd5ee1cafecfb..20e0f9cd0b251 100644 --- a/src/test/compile-fail/empty-linkname.rs +++ b/src/test/compile-fail/empty-linkname.rs @@ -11,3 +11,5 @@ #[link(name = "")] //~ ERROR: given with empty name extern { } + +fn main() {} diff --git a/src/test/compile-fail/feature-gate-static-nobundle.rs b/src/test/compile-fail/feature-gate-static-nobundle.rs index bc0025c7c9581..0d13a4937c468 100644 --- a/src/test/compile-fail/feature-gate-static-nobundle.rs +++ b/src/test/compile-fail/feature-gate-static-nobundle.rs @@ -11,3 +11,5 @@ #[link(name="foo", kind="static-nobundle")] //~^ ERROR: kind="static-nobundle" is feature gated extern {} + +fn main() {} diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs index 6eec1779a2d87..06b8720666953 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs @@ -99,7 +99,8 @@ // For #![crate_id], see issue #43142. (I cannot bear to enshrine current behavior in a test) -#![feature ( x0600)] //~ WARN unused or unknown feature +// FIXME(#44232) we should warn that this isn't used. +#![feature ( x0600)] // For #![no_start], see issue #43144. (I cannot bear to enshrine current behavior in a test) diff --git a/src/test/compile-fail/lint-output-format-2.rs b/src/test/compile-fail/lint-output-format-2.rs index 0e68ff752e5a9..ef072d4bbb391 100644 --- a/src/test/compile-fail/lint-output-format-2.rs +++ b/src/test/compile-fail/lint-output-format-2.rs @@ -8,21 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -F unused_features // aux-build:lint_output_format.rs +// FIXME(#44232) we should warn that this isn't used. #![feature(foo)] -//~^ ERROR unused or unknown feature -//~| NOTE requested on the command line with `-F unused-features` #![feature(test_feature)] +#![feature(rustc_attrs)] extern crate lint_output_format; use lint_output_format::{foo, bar}; //~^ WARNING use of deprecated item: text //~| NOTE #[warn(deprecated)] on by default -fn main() { +#[rustc_error] +fn main() { //~ ERROR: compilation successful let _x = foo(); //~^ WARNING use of deprecated item: text //~| NOTE #[warn(deprecated)] on by default diff --git a/src/test/compile-fail/lint-unknown-feature-default.rs b/src/test/compile-fail/lint-unknown-feature-default.rs index afd1a3933bf85..79ba3ea45e187 100644 --- a/src/test/compile-fail/lint-unknown-feature-default.rs +++ b/src/test/compile-fail/lint-unknown-feature-default.rs @@ -10,8 +10,10 @@ // Tests the default for the unused_features lint -#![deny(warnings)] +// FIXME(#44232) we should warn that this isn't used. +#![feature(this_is_not_a_feature)] -#![feature(this_is_not_a_feature)] //~ ERROR: unused or unknown feature +#![feature(rustc_attrs)] -fn main() { } +#[rustc_error] +fn main() { } //~ ERROR: compilation successful diff --git a/src/test/compile-fail/lint-unknown-feature.rs b/src/test/compile-fail/lint-unknown-feature.rs index ac1720b339e84..d230297aaba01 100644 --- a/src/test/compile-fail/lint-unknown-feature.rs +++ b/src/test/compile-fail/lint-unknown-feature.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(unused_features)] +#![warn(unused_features)] -#![feature(this_is_not_a_feature)] //~ ERROR: unused or unknown feature +// FIXME(#44232) we should warn that this isn't used. +#![feature(this_is_not_a_feature)] -fn main() {} +#![feature(rustc_attrs)] + +#[rustc_error] +fn main() {} //~ ERROR: compilation successful diff --git a/src/test/compile-fail/stable-features.rs b/src/test/compile-fail/stable-features.rs index 6f8c95c384032..5993f4b5a0941 100644 --- a/src/test/compile-fail/stable-features.rs +++ b/src/test/compile-fail/stable-features.rs @@ -12,8 +12,11 @@ // language and lib features. #![deny(stable_features)] + #![feature(test_accepted_feature)] //~ ERROR this feature has been stable since 1.0.0 -#![feature(rust1)] //~ ERROR this feature has been stable since 1.0.0 + +// FIXME(#44232) we should error that this isn't used. +#![feature(rust1)] fn main() { let _foo: Vec<()> = Vec::new(); diff --git a/src/test/compile-fail/weak-lang-item.rs b/src/test/compile-fail/weak-lang-item.rs index fdf50c27bf4cf..8eac959fc1e90 100644 --- a/src/test/compile-fail/weak-lang-item.rs +++ b/src/test/compile-fail/weak-lang-item.rs @@ -16,3 +16,5 @@ extern crate core; extern crate weak_lang_items; + +fn main() {} diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs index 40067efd57595..875aa32936508 100644 --- a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs +++ b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs @@ -15,6 +15,7 @@ // revisions:rpass1 rpass2 // compile-flags: -Z query-dep-graph // aux-build:point.rs +// ignore-test FIXME(#42293) this regressed in #44142 but should get fixed with red/green #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs index 701c5fec49b55..58fb8bc3c889f 100644 --- a/src/test/incremental/remapped_paths_cc/main.rs +++ b/src/test/incremental/remapped_paths_cc/main.rs @@ -11,6 +11,7 @@ // revisions:rpass1 rpass2 rpass3 // compile-flags: -Z query-dep-graph -g -Zincremental-cc // aux-build:extern_crate.rs +// ignore-test FIXME(#42293) this regressed in #44142 but should get fixed with red/green // This test case makes sure that we detect if paths emitted into debuginfo diff --git a/src/test/incremental/remove-private-item-cross-crate/main.rs b/src/test/incremental/remove-private-item-cross-crate/main.rs index 582ee905d7ca4..24fa1502b9224 100644 --- a/src/test/incremental/remove-private-item-cross-crate/main.rs +++ b/src/test/incremental/remove-private-item-cross-crate/main.rs @@ -16,7 +16,9 @@ #![feature(rustc_attrs)] #![crate_type = "bin"] -#![rustc_partition_reused(module="main", cfg="rpass2")] + +// FIXME(#42293) this regressed in #44142 but should get fixed with red/green +// #![rustc_partition_reused(module="main", cfg="rpass2")] extern crate a;