rust/src/librustc_metadata/cstore_impl.rs

561 lines
21 KiB
Rust
Raw Normal View History

// Copyright 2015 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use cstore::{self, LoadedMacro};
use encoder;
use link_args;
use native_libs;
rustc: Add a `#[wasm_import_module]` attribute This commit adds a new attribute to the Rust compiler specific to the wasm target (and no other targets). The `#[wasm_import_module]` attribute is used to specify the module that a name is imported from, and is used like so: #[wasm_import_module = "./foo.js"] extern { fn some_js_function(); } Here the import of the symbol `some_js_function` is tagged with the `./foo.js` module in the wasm output file. Wasm-the-format includes two fields on all imports, a module and a field. The field is the symbol name (`some_js_function` above) and the module has historically unconditionally been `"env"`. I'm not sure if this `"env"` convention has asm.js or LLVM roots, but regardless we'd like the ability to configure it! The proposed ES module integration with wasm (aka a wasm module is "just another ES module") requires that the import module of wasm imports is interpreted as an ES module import, meaning that you'll need to encode paths, NPM packages, etc. As a result, we'll need this to be something other than `"env"`! Unfortunately neither our version of LLVM nor LLD supports custom import modules (aka anything not `"env"`). My hope is that by the time LLVM 7 is released both will have support, but in the meantime this commit adds some primitive encoding/decoding of wasm files to the compiler. This way rustc postprocesses the wasm module that LLVM emits to ensure it's got all the imports we'd like to have in it. Eventually I'd ideally like to unconditionally require this attribute to be placed on all `extern { ... }` blocks. For now though it seemed prudent to add it as an unstable attribute, so for now it's not required (as that'd force usage of a feature gate). Hopefully it doesn't take too long to "stabilize" this! cc rust-lang-nursery/rust-wasm#29
2018-02-10 16:28:17 -06:00
use foreign_modules;
use schema;
2018-06-13 08:44:43 -05:00
use rustc::ty::query::QueryConfig;
use rustc::middle::cstore::{CrateStore, DepKind,
EncodedMetadata, NativeLibraryKind};
use rustc::middle::exported_symbols::ExportedSymbol;
use rustc::middle::stability::DeprecationEntry;
2017-04-27 13:27:16 -05:00
use rustc::hir::def;
use rustc::session::{CrateDisambiguator, Session};
use rustc::ty::{self, TyCtxt};
2018-06-13 08:44:43 -05:00
use rustc::ty::query::Providers;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
use rustc::hir::map::{DefKey, DefPath, DefPathHash};
use rustc::hir::map::definitions::DefPathTable;
use rustc::util::nodemap::DefIdMap;
2018-08-03 13:22:22 -05:00
use rustc_data_structures::svh::Svh;
use std::any::Any;
2018-02-27 10:11:14 -06:00
use rustc_data_structures::sync::Lrc;
use std::sync::Arc;
use syntax::ast;
use syntax::attr;
2018-08-18 05:14:03 -05:00
use syntax::source_map;
2018-05-12 19:50:39 -05:00
use syntax::edition::Edition;
2018-08-18 05:13:56 -05:00
use syntax::parse::source_file_to_stream;
use syntax::symbol::Symbol;
use syntax_pos::{Span, NO_EXPANSION, FileName};
Merge indexed_set.rs into bitvec.rs, and rename it bit_set.rs. Currently we have two files implementing bitsets (and 2D bit matrices). This commit combines them into one, taking the best features from each. This involves renaming a lot of things. The high level changes are as follows. - bitvec.rs --> bit_set.rs - indexed_set.rs --> (removed) - BitArray + IdxSet --> BitSet (merged, see below) - BitVector --> GrowableBitSet - {,Sparse,Hybrid}IdxSet --> {,Sparse,Hybrid}BitSet - BitMatrix --> BitMatrix - SparseBitMatrix --> SparseBitMatrix The changes within the bitset types themselves are as follows. ``` OLD OLD NEW BitArray<C> IdxSet<T> BitSet<T> -------- ------ ------ grow - grow new - (remove) new_empty new_empty new_empty new_filled new_filled new_filled - to_hybrid to_hybrid clear clear clear set_up_to set_up_to set_up_to clear_above - clear_above count - count contains(T) contains(&T) contains(T) contains_all - superset is_empty - is_empty insert(T) add(&T) insert(T) insert_all - insert_all() remove(T) remove(&T) remove(T) words words words words_mut words_mut words_mut - overwrite overwrite merge union union - subtract subtract - intersect intersect iter iter iter ``` In general, when choosing names I went with: - names that are more obvious (e.g. `BitSet` over `IdxSet`). - names that are more like the Rust libraries (e.g. `T` over `C`, `insert` over `add`); - names that are more set-like (e.g. `union` over `merge`, `superset` over `contains_all`, `domain_size` over `num_bits`). Also, using `T` for index arguments seems more sensible than `&T` -- even though the latter is standard in Rust collection types -- because indices are always copyable. It also results in fewer `&` and `*` sigils in practice.
2018-09-14 00:07:25 -05:00
use rustc_data_structures::bit_set::BitSet;
macro_rules! provide {
(<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident,
$($name:ident => $compute:block)*) => {
pub fn provide_extern<$lt>(providers: &mut Providers<$lt>) {
$(fn $name<'a, $lt:$lt, T>($tcx: TyCtxt<'a, $lt, $lt>, def_id_arg: T)
-> <ty::queries::$name<$lt> as
QueryConfig<$lt>>::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(DefId {
krate: $def_id.krate,
index: CRATE_DEF_INDEX
});
let dep_node = def_path_hash
.to_dep_node(::rustc::dep_graph::DepKind::CrateMetadata);
// The DepNodeIndex of the DepNode::CrateMetadata should be
// cached somewhere, so that we can use read_index().
$tcx.dep_graph.read(dep_node);
let $cdata = $tcx.crate_data_as_rc_any($def_id.krate);
let $cdata = $cdata.downcast_ref::<cstore::CrateMetadata>()
2018-10-22 11:21:55 -05:00
.expect("CrateStore created data is not a CrateMetadata");
$compute
})*
*providers = Providers {
$($name,)*
..*providers
};
}
}
}
// 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, tcx.sess))
}
predicates_of => { cdata.get_predicates(def_id.index, tcx) }
predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) }
super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
trait_def => {
tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
}
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
adt_destructor => {
let _ = cdata;
tcx.calculate_dtor(def_id, &mut |_,_| Ok(()))
}
2018-02-27 10:11:14 -06:00
variances_of => { Lrc::new(cdata.get_item_variances(def_id.index)) }
associated_item_def_ids => {
let mut result = vec![];
2017-06-15 00:49:07 -05:00
cdata.each_child_of_item(def_id.index,
|child| result.push(child.def.def_id()), tcx.sess);
2018-02-27 10:11:14 -06:00
Lrc::new(result)
}
associated_item => { cdata.get_associated_item(def_id.index) }
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
impl_polarity => { cdata.get_impl_polarity(def_id.index) }
coerce_unsized_info => {
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
})
}
optimized_mir => {
let mir = cdata.maybe_get_optimized_mir(tcx, def_id.index).unwrap_or_else(|| {
bug!("get_optimized_mir: missing MIR for `{:?}`", def_id)
});
let mir = tcx.alloc_mir(mir);
mir
}
mir_const_qualif => {
Merge indexed_set.rs into bitvec.rs, and rename it bit_set.rs. Currently we have two files implementing bitsets (and 2D bit matrices). This commit combines them into one, taking the best features from each. This involves renaming a lot of things. The high level changes are as follows. - bitvec.rs --> bit_set.rs - indexed_set.rs --> (removed) - BitArray + IdxSet --> BitSet (merged, see below) - BitVector --> GrowableBitSet - {,Sparse,Hybrid}IdxSet --> {,Sparse,Hybrid}BitSet - BitMatrix --> BitMatrix - SparseBitMatrix --> SparseBitMatrix The changes within the bitset types themselves are as follows. ``` OLD OLD NEW BitArray<C> IdxSet<T> BitSet<T> -------- ------ ------ grow - grow new - (remove) new_empty new_empty new_empty new_filled new_filled new_filled - to_hybrid to_hybrid clear clear clear set_up_to set_up_to set_up_to clear_above - clear_above count - count contains(T) contains(&T) contains(T) contains_all - superset is_empty - is_empty insert(T) add(&T) insert(T) insert_all - insert_all() remove(T) remove(&T) remove(T) words words words words_mut words_mut words_mut - overwrite overwrite merge union union - subtract subtract - intersect intersect iter iter iter ``` In general, when choosing names I went with: - names that are more obvious (e.g. `BitSet` over `IdxSet`). - names that are more like the Rust libraries (e.g. `T` over `C`, `insert` over `add`); - names that are more set-like (e.g. `union` over `merge`, `superset` over `contains_all`, `domain_size` over `num_bits`). Also, using `T` for index arguments seems more sensible than `&T` -- even though the latter is standard in Rust collection types -- because indices are always copyable. It also results in fewer `&` and `*` sigils in practice.
2018-09-14 00:07:25 -05:00
(cdata.mir_const_qualif(def_id.index), Lrc::new(BitSet::new_empty(0)))
}
2017-05-13 05:12:29 -05:00
fn_sig => { cdata.fn_sig(def_id.index, tcx) }
2018-02-27 10:11:14 -06:00
inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) }
is_foreign_item => { cdata.is_foreign_item(def_id.index) }
2017-04-27 13:27:16 -05:00
describe_def => { cdata.get_def(def_id.index) }
2017-04-28 10:59:57 -05:00
def_span => { cdata.get_span(def_id.index, &tcx.sess) }
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.sess) }
2017-05-03 09:01:49 -05:00
// FIXME(#38501) We've skipped a `read` on the `HirBody` of
// a `fn` when encoding, so the dep-tracking wouldn't work.
// This is only used by rustdoc anyway, which shouldn't have
// incremental recompilation ever enabled.
fn_arg_names => { cdata.get_fn_arg_names(def_id.index) }
2018-04-15 18:41:33 -05:00
rendered_const => { cdata.get_rendered_const(def_id.index) }
2017-05-04 09:37:34 -05:00
impl_parent => { cdata.get_parent_impl(def_id.index) }
2017-05-04 08:27:48 -05:00
trait_of_item => { cdata.get_trait_of_item(def_id.index) }
const_is_rvalue_promotable_to_static => {
cdata.const_is_rvalue_promotable_to_static(def_id.index)
2017-04-28 03:28:22 -05:00
}
is_mir_available => { cdata.is_item_mir_available(def_id.index) }
2017-06-15 00:49:07 -05:00
2018-02-27 10:11:14 -06:00
dylib_dependency_formats => { Lrc::new(cdata.get_dylib_dependency_formats()) }
is_panic_runtime => { cdata.root.panic_runtime }
is_compiler_builtins => { cdata.root.compiler_builtins }
has_global_allocator => { cdata.root.has_global_allocator }
has_panic_handler => { cdata.root.has_panic_handler }
is_sanitizer_runtime => { cdata.root.sanitizer_runtime }
is_profiler_runtime => { cdata.root.profiler_runtime }
panic_strategy => { cdata.root.panic_strategy }
2018-02-15 03:52:26 -06:00
extern_crate => {
let r = Lrc::new(*cdata.extern_crate.lock());
r
}
is_no_builtins => { cdata.root.no_builtins }
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
reachable_non_generics => {
let reachable_non_generics = tcx
.exported_symbols(cdata.cnum)
.iter()
.filter_map(|&(exported_symbol, export_level)| {
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
return Some((def_id, export_level))
} else {
None
}
})
.collect();
Lrc::new(reachable_non_generics)
}
2018-02-27 10:11:14 -06:00
native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
rustc: Add a `#[wasm_import_module]` attribute This commit adds a new attribute to the Rust compiler specific to the wasm target (and no other targets). The `#[wasm_import_module]` attribute is used to specify the module that a name is imported from, and is used like so: #[wasm_import_module = "./foo.js"] extern { fn some_js_function(); } Here the import of the symbol `some_js_function` is tagged with the `./foo.js` module in the wasm output file. Wasm-the-format includes two fields on all imports, a module and a field. The field is the symbol name (`some_js_function` above) and the module has historically unconditionally been `"env"`. I'm not sure if this `"env"` convention has asm.js or LLVM roots, but regardless we'd like the ability to configure it! The proposed ES module integration with wasm (aka a wasm module is "just another ES module") requires that the import module of wasm imports is interpreted as an ES module import, meaning that you'll need to encode paths, NPM packages, etc. As a result, we'll need this to be something other than `"env"`! Unfortunately neither our version of LLVM nor LLD supports custom import modules (aka anything not `"env"`). My hope is that by the time LLVM 7 is released both will have support, but in the meantime this commit adds some primitive encoding/decoding of wasm files to the compiler. This way rustc postprocesses the wasm module that LLVM emits to ensure it's got all the imports we'd like to have in it. Eventually I'd ideally like to unconditionally require this attribute to be placed on all `extern { ... }` blocks. For now though it seemed prudent to add it as an unstable attribute, so for now it's not required (as that'd force usage of a feature gate). Hopefully it doesn't take too long to "stabilize" this! cc rust-lang-nursery/rust-wasm#29
2018-02-10 16:28:17 -06:00
foreign_modules => { Lrc::new(cdata.get_foreign_modules(tcx.sess)) }
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.root.disambiguator }
crate_hash => { cdata.root.hash }
original_crate_name => { cdata.root.name }
extra_filename => { cdata.root.extra_filename.clone() }
implementations_of_trait => {
let mut result = vec![];
let filter = Some(other);
cdata.get_implementations_for_trait(filter, &mut result);
2018-02-27 10:11:14 -06:00
Lrc::new(result)
}
all_trait_implementations => {
let mut result = vec![];
cdata.get_implementations_for_trait(None, &mut result);
2018-02-27 10:11:14 -06:00
Lrc::new(result)
}
visibility => { cdata.get_visibility(def_id.index) }
2018-02-15 03:52:26 -06:00
dep_kind => {
let r = *cdata.dep_kind.lock();
r
}
crate_name => { cdata.name }
item_children => {
let mut result = vec![];
cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess);
2018-02-27 10:11:14 -06:00
Lrc::new(result)
}
defined_lib_features => { Lrc::new(cdata.get_lib_features()) }
2018-02-27 10:11:14 -06:00
defined_lang_items => { Lrc::new(cdata.get_lang_items()) }
missing_lang_items => { Lrc::new(cdata.get_missing_lang_items()) }
missing_extern_crate_item => {
2018-02-15 03:52:26 -06:00
let r = match *cdata.extern_crate.borrow() {
Some(extern_crate) if !extern_crate.direct => true,
_ => false,
2018-02-15 03:52:26 -06:00
};
r
}
2018-02-27 10:11:14 -06:00
used_crate_source => { Lrc::new(cdata.source.clone()) }
2017-09-20 13:42:49 -05:00
exported_symbols => {
let cnum = cdata.cnum;
assert!(cnum != LOCAL_CRATE);
Arc::new(cdata.exported_symbols(tcx))
}
}
pub fn provide<'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
2017-06-11 23:16:26 -05:00
*providers = Providers {
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))
rustc: Add a `#[wasm_import_module]` attribute This commit adds a new attribute to the Rust compiler specific to the wasm target (and no other targets). The `#[wasm_import_module]` attribute is used to specify the module that a name is imported from, and is used like so: #[wasm_import_module = "./foo.js"] extern { fn some_js_function(); } Here the import of the symbol `some_js_function` is tagged with the `./foo.js` module in the wasm output file. Wasm-the-format includes two fields on all imports, a module and a field. The field is the symbol name (`some_js_function` above) and the module has historically unconditionally been `"env"`. I'm not sure if this `"env"` convention has asm.js or LLVM roots, but regardless we'd like the ability to configure it! The proposed ES module integration with wasm (aka a wasm module is "just another ES module") requires that the import module of wasm imports is interpreted as an ES module import, meaning that you'll need to encode paths, NPM packages, etc. As a result, we'll need this to be something other than `"env"`! Unfortunately neither our version of LLVM nor LLD supports custom import modules (aka anything not `"env"`). My hope is that by the time LLVM 7 is released both will have support, but in the meantime this commit adds some primitive encoding/decoding of wasm files to the compiler. This way rustc postprocesses the wasm module that LLVM emits to ensure it's got all the imports we'd like to have in it. Eventually I'd ideally like to unconditionally require this attribute to be placed on all `extern { ... }` blocks. For now though it seemed prudent to add it as an unstable attribute, so for now it's not required (as that'd force usage of a feature gate). Hopefully it doesn't take too long to "stabilize" this! cc rust-lang-nursery/rust-wasm#29
2018-02-10 16:28:17 -06:00
.find(|lib| {
let fm_id = match lib.foreign_module {
Some(id) => id,
None => return false,
};
tcx.foreign_modules(id.krate)
.iter()
.find(|m| m.def_id == fm_id)
.expect("failed to find foreign module")
.foreign_items
.contains(&id)
})
.map(|l| l.kind)
},
native_libraries: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
2018-02-27 10:11:14 -06:00
Lrc::new(native_libs::collect(tcx))
},
rustc: Add a `#[wasm_import_module]` attribute This commit adds a new attribute to the Rust compiler specific to the wasm target (and no other targets). The `#[wasm_import_module]` attribute is used to specify the module that a name is imported from, and is used like so: #[wasm_import_module = "./foo.js"] extern { fn some_js_function(); } Here the import of the symbol `some_js_function` is tagged with the `./foo.js` module in the wasm output file. Wasm-the-format includes two fields on all imports, a module and a field. The field is the symbol name (`some_js_function` above) and the module has historically unconditionally been `"env"`. I'm not sure if this `"env"` convention has asm.js or LLVM roots, but regardless we'd like the ability to configure it! The proposed ES module integration with wasm (aka a wasm module is "just another ES module") requires that the import module of wasm imports is interpreted as an ES module import, meaning that you'll need to encode paths, NPM packages, etc. As a result, we'll need this to be something other than `"env"`! Unfortunately neither our version of LLVM nor LLD supports custom import modules (aka anything not `"env"`). My hope is that by the time LLVM 7 is released both will have support, but in the meantime this commit adds some primitive encoding/decoding of wasm files to the compiler. This way rustc postprocesses the wasm module that LLVM emits to ensure it's got all the imports we'd like to have in it. Eventually I'd ideally like to unconditionally require this attribute to be placed on all `extern { ... }` blocks. For now though it seemed prudent to add it as an unstable attribute, so for now it's not required (as that'd force usage of a feature gate). Hopefully it doesn't take too long to "stabilize" this! cc rust-lang-nursery/rust-wasm#29
2018-02-10 16:28:17 -06:00
foreign_modules: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
Lrc::new(foreign_modules::collect(tcx))
},
link_args: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
2018-02-27 10:11:14 -06:00
Lrc::new(link_args::collect(tcx))
},
// 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<DefId> = DefIdMap();
// Issue 46112: We want the map to prefer the shortest
// paths when reporting the path to an item. Therefore we
// build up the map via a breadth-first search (BFS),
// which naturally yields minimal-length paths.
//
// Note that it needs to be a BFS over the whole forest of
// crates, not just each individual crate; otherwise you
// only get paths that are locally minimal with respect to
// whatever crate we happened to encounter first in this
// traversal, but not globally minimal across all crates.
let bfs_queue = &mut VecDeque::new();
// Preferring shortest paths alone does not guarantee a
// deterministic result; so sort by crate num to avoid
// hashtable iteration non-determinism. This only makes
// things as deterministic as crate-nums assignment is,
// which is to say, its not deterministic in general. But
// we believe that libstd is consistently assigned crate
// num 1, so it should be enough to resolve #46112.
let mut crates: Vec<CrateNum> = (*tcx.crates()).clone();
crates.sort();
for &cnum in crates.iter() {
// Ignore crates without a corresponding local `extern crate` item.
if tcx.missing_extern_crate_item(cnum) {
continue
}
bfs_queue.push_back(DefId {
krate: cnum,
index: CRATE_DEF_INDEX
});
}
// (restrict scope of mutable-borrow of `visible_parent_map`)
{
let visible_parent_map = &mut visible_parent_map;
let mut add_child = |bfs_queue: &mut VecDeque<_>,
child: &def::Export,
parent: DefId| {
if child.vis != ty::Visibility::Public {
return;
}
let child = child.def.def_id();
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);
}
}
};
while let Some(def) = bfs_queue.pop_front() {
for child in tcx.item_children(def).iter() {
add_child(bfs_queue, child, def);
}
}
}
2018-02-27 10:11:14 -06:00
Lrc::new(visible_parent_map)
},
2017-06-11 23:16:26 -05:00
..*providers
};
}
impl cstore::CStore {
pub fn export_macros_untracked(&self, cnum: CrateNum) {
let data = self.get_crate_data(cnum);
2018-02-15 03:52:26 -06:00
let mut dep_kind = data.dep_kind.lock();
if *dep_kind == DepKind::UnexportedMacrosOnly {
*dep_kind = DepKind::MacrosOnly;
}
}
pub fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind {
let data = self.get_crate_data(cnum);
let r = *data.dep_kind.lock();
r
}
pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition {
self.get_crate_data(cnum).root.edition
2018-05-12 19:50:39 -05:00
}
pub fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name> {
self.get_crate_data(def.krate).get_struct_field_names(def.index)
2015-11-20 09:46:39 -06:00
}
pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<def::Export> {
2015-11-20 09:46:39 -06:00
let mut result = vec![];
self.get_crate_data(def_id.krate)
2017-06-07 09:17:11 -05:00
.each_child_of_item(def_id.index, |child| result.push(child), sess);
2015-11-20 09:46:39 -06:00
result
}
pub 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.to_proc_macro_index()].1.clone());
} else if data.name == "proc_macro" && data.item_name(id.index) == "quote" {
use syntax::ext::base::SyntaxExtension;
use syntax_ext::proc_macro_impl::BangProcMacro;
let ext = SyntaxExtension::ProcMacro {
expander: Box::new(BangProcMacro { inner: ::proc_macro::quote }),
allow_internal_unstable: true,
edition: data.root.edition,
};
2018-02-27 10:11:14 -06:00
return LoadedMacro::ProcMacro(Lrc::new(ext));
}
let def = data.get_macro(id.index);
let macro_full_name = data.def_path(id.index).to_string_friendly(|_| data.imported_name);
let source_name = FileName::Macros(macro_full_name);
2016-10-28 01:52:45 -05:00
2018-08-18 05:14:09 -05:00
let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body);
2018-08-18 05:13:56 -05:00
let local_span = Span::new(source_file.start_pos, source_file.end_pos, NO_EXPANSION);
let body = source_file_to_stream(&sess.parse_sess, source_file, None);
2016-10-28 01:52:45 -05:00
// Mark the attrs as used
let attrs = data.get_item_attrs(id.index, sess);
for attr in attrs.iter() {
2016-10-28 01:52:45 -05:00
attr::mark_used(attr);
}
let name = data.def_key(id.index).disambiguated_data.data
.get_opt_name().expect("no name in load_macro");
2016-10-28 01:52:45 -05:00
sess.imported_macro_spans.borrow_mut()
.insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
2016-10-28 01:52:45 -05:00
LoadedMacro::MacroDef(ast::Item {
ident: ast::Ident::from_str(&name.as_str()),
2016-10-28 01:52:45 -05:00
id: ast::DUMMY_NODE_ID,
span: local_span,
attrs: attrs.iter().cloned().collect(),
2017-03-17 16:58:48 -05:00
node: ast::ItemKind::MacroDef(ast::MacroDef {
tokens: body.into(),
2017-03-22 03:39:51 -05:00
legacy: def.legacy,
2017-03-17 16:58:48 -05:00
}),
2018-08-18 05:14:03 -05:00
vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
tokens: None,
})
2016-10-28 01:52:45 -05:00
}
pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem {
self.get_crate_data(def.krate).get_associated_item(def.index)
}
}
impl CrateStore for cstore::CStore {
fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any> {
self.get_crate_data(krate)
}
fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
self.get_crate_data(def.krate).get_generics(def.index, sess)
}
fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol
{
self.get_crate_data(cnum).name
}
fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator
{
self.get_crate_data(cnum).root.disambiguator
}
2018-08-03 13:22:22 -05:00
fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh
{
self.get_crate_data(cnum).root.hash
}
/// 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.
fn def_key(&self, def: DefId) -> DefKey {
// Note: loading the def-key (or def-path) for a def-id is not
// a *read* of its metadata. This is because the def-id is
// really just an interned shorthand for a def-path, which is the
// canonical name for an item.
//
// self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).def_key(def.index)
}
fn def_path(&self, def: DefId) -> DefPath {
// See `Note` above in `def_key()` for why this read is
// commented out:
//
// self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).def_path(def.index)
}
fn def_path_hash(&self, def: DefId) -> DefPathHash {
self.get_crate_data(def.krate).def_path_hash(def.index)
}
fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable> {
self.get_crate_data(cnum).def_path_table.clone()
}
fn crates_untracked(&self) -> Vec<CrateNum>
{
let mut result = vec![];
self.iter_crate_data(|cnum, _| result.push(cnum));
result
}
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>
{
2015-11-25 09:02:59 -06:00
self.do_extern_mod_stmt_cnum(emod_id)
}
fn postorder_cnums_untracked(&self) -> Vec<CrateNum> {
self.do_postorder_cnums_untracked()
}
2017-03-23 13:18:25 -05:00
fn encode_metadata<'a, 'tcx>(&self,
2018-08-18 05:08:06 -05:00
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> EncodedMetadata
{
2018-08-18 05:08:06 -05:00
encoder::encode_metadata(tcx)
2015-11-20 17:08:09 -06:00
}
fn metadata_encoding_version(&self) -> &[u8]
{
schema::METADATA_HEADER
2015-11-20 17:08:09 -06:00
}
}