rust/src/librustc_metadata/cstore_impl.rs

586 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;
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;
use rustc::ty::maps::QueryConfig;
use rustc::middle::cstore::{CrateStore, DepKind,
MetadataLoader, LinkMeta,
LoadedMacro, 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};
use rustc::ty::maps::Providers;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
use rustc::hir::map::{DefKey, DefPath, DefPathHash};
2017-06-11 23:16:26 -05:00
use rustc::hir::map::blocks::FnLikeNode;
use rustc::hir::map::definitions::DefPathTable;
use rustc::util::nodemap::DefIdMap;
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-01-28 23:12:09 -06:00
use syntax::codemap;
use syntax::ext::base::SyntaxExtension;
2017-02-20 23:05:59 -06:00
use syntax::parse::filemap_to_stream;
use syntax::symbol::Symbol;
use syntax_pos::{Span, NO_EXPANSION, FileName};
use rustc_data_structures::indexed_set::IdxSetBuf;
2016-03-29 00:50:44 -05:00
use rustc::hir;
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>::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>()
.expect("CrateStore crated ata 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) }
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 => {
2018-02-27 10:11:14 -06:00
(cdata.mir_const_qualif(def_id.index), Lrc::new(IdxSetBuf::new_empty(0)))
}
typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) }
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)) }
2017-06-15 00:49:07 -05:00
is_const_fn => { cdata.is_const_fn(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) }
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) }
item_body_nested_bodies => { cdata.item_body_nested_bodies(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.is_panic_runtime(tcx.sess) }
is_compiler_builtins => { cdata.is_compiler_builtins(tcx.sess) }
has_global_allocator => { cdata.has_global_allocator() }
is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) }
is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) }
panic_strategy => { cdata.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.is_no_builtins(tcx.sess) }
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.disambiguator() }
crate_hash => { cdata.hash() }
original_crate_name => { cdata.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)
}
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()) }
extern_const_body => {
debug!("item_body({:?}): inlining item", def_id);
cdata.extern_const_body(tcx, def_id.index)
}
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);
// If this crate is a custom derive crate, then we're not even going to
// link those in so we skip those crates.
if cdata.root.macro_derive_registrar.is_some() {
return Arc::new(Vec::new())
}
Arc::new(cdata.exported_symbols(tcx))
}
wasm_custom_sections => { Lrc::new(cdata.wasm_custom_sections()) }
}
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
2017-06-11 23:16:26 -05:00
fn is_const_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
let node_id = tcx.hir.as_local_node_id(def_id)
.expect("Non-local call to local provider is_const_fn");
if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) {
fn_like.constness() == hir::Constness::Const
} else {
false
}
}
// 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_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))
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 CrateStore for cstore::CStore {
2018-02-27 10:11:14 -06:00
fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<Any> {
self.get_crate_data(krate)
}
fn metadata_loader(&self) -> &MetadataLoader {
&*self.metadata_loader
}
fn visibility_untracked(&self, def: DefId) -> ty::Visibility {
self.get_crate_data(def.krate).get_visibility(def.index)
}
fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
self.get_crate_data(def.krate).get_generics(def.index, sess)
}
fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
{
self.get_crate_data(def.krate).get_associated_item(def.index)
}
fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind
{
2018-02-15 03:52:26 -06:00
let data = self.get_crate_data(cnum);
let r = *data.dep_kind.lock();
r
}
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;
}
}
fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol
2015-11-20 17:08:09 -06:00
{
self.get_crate_data(cnum).name
2015-11-20 17:08:09 -06:00
}
fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator
{
self.get_crate_data(cnum).disambiguator()
}
fn crate_hash_untracked(&self, cnum: CrateNum) -> hir::svh::Svh
{
self.get_crate_data(cnum).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)
}
2018-02-27 10:11:14 -06:00
fn def_path_table(&self, cnum: CrateNum) -> Lrc<DefPathTable> {
self.get_crate_data(cnum).def_path_table.clone()
}
fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>
2015-11-20 09:46:39 -06:00
{
self.get_crate_data(def.krate).get_struct_field_names(def.index)
2015-11-20 09:46:39 -06:00
}
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
}
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" &&
self.get_crate_data(id.krate).item_name(id.index) == "quote" {
let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter));
2018-02-27 10:11:14 -06:00
return LoadedMacro::ProcMacro(Lrc::new(ext));
}
let (name, def) = data.get_macro(id.index);
let source_name = FileName::Macros(name.to_string());
2016-10-28 01:52:45 -05:00
let filemap = sess.parse_sess.codemap().new_filemap(source_name, def.body);
2017-07-31 15:04:34 -05:00
let local_span = Span::new(filemap.start_pos, filemap.end_pos, NO_EXPANSION);
let body = filemap_to_stream(&sess.parse_sess, filemap, 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),
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
}),
vis: codemap::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
tokens: None,
})
2016-10-28 01:52:45 -05:00
}
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,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta)
-> EncodedMetadata
{
encoder::encode_metadata(tcx, link_meta)
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
}
}