Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track more crate metadata #42598

Merged
merged 7 commits into from
Jun 17, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ define_dep_nodes!(
// Represents the metadata for a given HIR node, typically found
// in an extern crate.
MetaData(DefId),
MetaDataByCrateNum(CrateNum),

// Represents some artifact that we save to disk. Note that these
// do not have a def-id as part of their identifier.
Expand Down Expand Up @@ -339,6 +340,7 @@ define_dep_nodes!(
ItemSignature(DefId),
ItemVarianceConstraints(DefId),
ItemVariances(DefId),
IsConstFn(DefId),
IsForeignItem(DefId),
TypeParamPredicates { item_id: DefId, param_id: DefId },
SizedConstraint(DefId),
Expand Down
13 changes: 0 additions & 13 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,23 +243,17 @@ pub trait CrateStore {
fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem;

// flags
fn is_const_fn(&self, did: DefId) -> bool;
fn is_dllimport_foreign_item(&self, def: DefId) -> bool;
fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool;

// crate metadata
fn dylib_dependency_formats(&self, cnum: CrateNum)
-> Vec<(CrateNum, LinkagePreference)>;
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<lang_items::LangItem>;
fn is_allocator(&self, cnum: CrateNum) -> bool;
fn is_panic_runtime(&self, cnum: CrateNum) -> bool;
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool;
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy;
fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate>;
/// The name of the crate as it is referred to in source code of the current
/// crate.
fn crate_name(&self, cnum: CrateNum) -> Symbol;
Expand Down Expand Up @@ -364,28 +358,21 @@ impl CrateStore for DummyCrateStore {
{ bug!("associated_item_cloned") }

// flags
fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
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 dylib_dependency_formats(&self, cnum: CrateNum)
-> Vec<(CrateNum, LinkagePreference)>
{ bug!("dylib_dependency_formats") }
fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>
{ bug!("lang_items") }
fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>
{ 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_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") }
fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") }
fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }
fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") }
fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
bug!("panic_strategy")
}
fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate> { bug!("extern_crate") }
fn crate_name(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") }
fn original_crate_name(&self, cnum: CrateNum) -> Symbol {
bug!("original_crate_name")
Expand Down
43 changes: 25 additions & 18 deletions src/librustc/middle/dependency_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ use hir::def_id::CrateNum;

use session;
use session::config;
use ty::TyCtxt;
use middle::cstore::DepKind;
use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic};
use util::nodemap::FxHashMap;
Expand All @@ -91,18 +92,22 @@ pub enum Linkage {
Dynamic,
}

pub fn calculate(sess: &session::Session) {
pub fn calculate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let sess = &tcx.sess;
let mut fmts = sess.dependency_formats.borrow_mut();
for &ty in sess.crate_types.borrow().iter() {
let linkage = calculate_type(sess, ty);
verify_ok(sess, &linkage);
let linkage = calculate_type(tcx, ty);
verify_ok(tcx, &linkage);
fmts.insert(ty, linkage);
}
sess.abort_if_errors();
}

fn calculate_type(sess: &session::Session,
ty: config::CrateType) -> DependencyList {
fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Random aside: I feel like a GlobalTyCtxt<'a, 'tcx> alias might be nice.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At that point, the Ty part is maybe a bit unnecessary and we should move towards a generalized idea of a "global context" (aka god object).

ty: config::CrateType) -> DependencyList {

let sess = &tcx.sess;

if !sess.opts.output_types.should_trans() {
return Vec::new();
}
Expand All @@ -111,7 +116,7 @@ fn calculate_type(sess: &session::Session,
// If the global prefer_dynamic switch is turned off, first attempt
// static linkage (this can fail).
config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
if let Some(v) = attempt_static(sess) {
if let Some(v) = attempt_static(tcx) {
return v;
}
}
Expand All @@ -124,7 +129,7 @@ fn calculate_type(sess: &session::Session,
// to be found, we generate some nice pretty errors.
config::CrateTypeStaticlib |
config::CrateTypeCdylib => {
if let Some(v) = attempt_static(sess) {
if let Some(v) = attempt_static(tcx) {
return v;
}
for cnum in sess.cstore.crates() {
Expand All @@ -141,7 +146,7 @@ fn calculate_type(sess: &session::Session,
// to try to eagerly statically link all dependencies. This is normally
// done for end-product dylibs, not intermediate products.
config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => {
if let Some(v) = attempt_static(sess) {
if let Some(v) = attempt_static(tcx) {
return v;
}
}
Expand All @@ -167,8 +172,8 @@ fn calculate_type(sess: &session::Session,
if src.dylib.is_some() {
info!("adding dylib: {}", name);
add_library(sess, cnum, RequireDynamic, &mut formats);
let deps = sess.cstore.dylib_dependency_formats(cnum);
for &(depnum, style) in &deps {
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);
Expand Down Expand Up @@ -210,9 +215,9 @@ fn calculate_type(sess: &session::Session,
// Things like allocators and panic runtimes may not have been activated
// quite yet, so do so here.
activate_injected_dep(sess.injected_allocator.get(), &mut ret,
&|cnum| sess.cstore.is_allocator(cnum));
&|cnum| tcx.is_allocator(cnum));
activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret,
&|cnum| sess.cstore.is_panic_runtime(cnum));
&|cnum| tcx.is_panic_runtime(cnum));

// When dylib B links to dylib A, then when using B we must also link to A.
// It could be the case, however, that the rlib for A is present (hence we
Expand Down Expand Up @@ -269,7 +274,8 @@ fn add_library(sess: &session::Session,
}
}

fn attempt_static(sess: &session::Session) -> Option<DependencyList> {
fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<DependencyList> {
let sess = &tcx.sess;
let crates = sess.cstore.used_crates(RequireStatic);
if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) {
return None
Expand All @@ -290,9 +296,9 @@ fn attempt_static(sess: &session::Session) -> Option<DependencyList> {
// explicitly linked, which is the case for any injected dependency. Handle
// that here and activate them.
activate_injected_dep(sess.injected_allocator.get(), &mut ret,
&|cnum| sess.cstore.is_allocator(cnum));
&|cnum| tcx.is_allocator(cnum));
activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret,
&|cnum| sess.cstore.is_panic_runtime(cnum));
&|cnum| tcx.is_panic_runtime(cnum));

Some(ret)
}
Expand Down Expand Up @@ -327,7 +333,8 @@ fn activate_injected_dep(injected: Option<CrateNum>,

// After the linkage for a crate has been determined we need to verify that
// there's only going to be one allocator in the output.
fn verify_ok(sess: &session::Session, list: &[Linkage]) {
fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) {
let sess = &tcx.sess;
if list.len() == 0 {
return
}
Expand All @@ -338,7 +345,7 @@ fn verify_ok(sess: &session::Session, list: &[Linkage]) {
continue
}
let cnum = CrateNum::new(i + 1);
if sess.cstore.is_allocator(cnum) {
if tcx.is_allocator(cnum) {
if let Some(prev) = allocator {
let prev_name = sess.cstore.crate_name(prev);
let cur_name = sess.cstore.crate_name(cnum);
Expand All @@ -349,7 +356,7 @@ fn verify_ok(sess: &session::Session, list: &[Linkage]) {
allocator = Some(cnum);
}

if sess.cstore.is_panic_runtime(cnum) {
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);
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/ty/item_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
//
// Returns `None` for the local crate.
if cnum != LOCAL_CRATE {
let opt_extern_crate = self.sess.cstore.extern_crate(cnum);
let opt_extern_crate = self.extern_crate(cnum);
let opt_extern_crate = opt_extern_crate.and_then(|extern_crate| {
if extern_crate.direct {
Some(extern_crate.def_id)
Expand Down Expand Up @@ -136,8 +136,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// 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.
if cur_def.index == CRATE_DEF_INDEX {
match self.sess.cstore.extern_crate(cur_def.krate) {
Some(extern_crate) if extern_crate.direct => {
match *self.extern_crate(cur_def.krate) {
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();
return true;
Expand Down
42 changes: 42 additions & 0 deletions src/librustc/ty/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use hir::def::Def;
use hir;
use middle::const_val;
use middle::cstore::{ExternCrate, LinkagePreference};
use middle::privacy::AccessLevels;
use middle::region::RegionMaps;
use mir;
Expand Down Expand Up @@ -476,6 +477,36 @@ impl<'tcx> QueryDescription for queries::is_object_safe<'tcx> {
}
}

impl<'tcx> QueryDescription for queries::is_const_fn<'tcx> {
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id))
}
}

impl<'tcx> QueryDescription for queries::dylib_dependency_formats<'tcx> {
fn describe(_: TyCtxt, _: CrateNum) -> String {
"dylib dependency formats of crate".to_string()
}
}

impl<'tcx> QueryDescription for queries::is_allocator<'tcx> {
fn describe(_: TyCtxt, _: CrateNum) -> String {
"checking if the crate is_allocator".to_string()
}
}

impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> {
fn describe(_: TyCtxt, _: CrateNum) -> String {
"checking if the crate is_panic_runtime".to_string()
}
}

impl<'tcx> QueryDescription for queries::extern_crate<'tcx> {
fn describe(_: TyCtxt, _: CrateNum) -> String {
"getting crate's ExternCrateData".to_string()
}
}

macro_rules! define_maps {
(<$tcx:tt>
$($(#[$attr:meta])*
Expand Down Expand Up @@ -791,6 +822,9 @@ define_maps! { <'tcx>
[] adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>],
[] adt_dtorck_constraint: DtorckConstraint(DefId) -> ty::DtorckConstraint<'tcx>,

/// True if this is a const fn
[] is_const_fn: IsConstFn(DefId) -> bool,

/// True if this is a foreign item (i.e., linked via `extern { ... }`).
[] is_foreign_item: IsForeignItem(DefId) -> bool,

Expand Down Expand Up @@ -929,6 +963,14 @@ define_maps! { <'tcx>
[] needs_drop_raw: needs_drop_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
[] layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-> Result<&'tcx Layout, LayoutError<'tcx>>,

[] dylib_dependency_formats: MetaDataByCrateNum(CrateNum)
-> Rc<Vec<(CrateNum, LinkagePreference)>>,

[] is_allocator: MetaDataByCrateNum(CrateNum) -> bool,
[] is_panic_runtime: MetaDataByCrateNum(CrateNum) -> bool,

[] extern_crate: MetaDataByCrateNum(CrateNum) -> Rc<Option<ExternCrate>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd rather all of these use DefId with DEF_INDEX_CRATE. What do you think, @nikomatsakis?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think that CrateNum would be preferred -- it seems clearer -- why do you think DefId, @eddyb?

One note: under the new dep-node system, a DepNode(CrateNum) is perfectly fine, and we should be able to handle it well (in the past, the "retracing" only worked for DefId, so we avoided using CrateNum in a DepNode.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these are literally the same as querying the attributes of the crate root of some extern crate (they should also probably be replaced with an actual attribute query but that's another question), so to me they make more sense as a property of that DefId instead of that of the CrateNum (the latter would make sense for e.g. all impl items in a crate).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I don't see it that way -- that is, I see putting the attributes on the crate root as a way of specifying properties that apply to the crate as a whole, but I have no strong opinion here. I'd be happy either way.

}

fn type_param_predicates((item_id, param_id): (DefId, DefId)) -> DepConstructor {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_const_eval/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
signal!(e, TypeckError)
}
} else {
if tcx.sess.cstore.is_const_fn(def_id) {
if tcx.is_const_fn(def_id) {
tcx.sess.cstore.item_body(tcx, def_id)
} else {
signal!(e, TypeckError)
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
reachable::provide(&mut local_providers);
rustc_const_eval::provide(&mut local_providers);
middle::region::provide(&mut local_providers);
cstore::provide_local(&mut local_providers);

let mut extern_providers = ty::maps::Providers::default();
cstore::provide(&mut extern_providers);
Expand Down Expand Up @@ -1048,7 +1049,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

time(time_passes,
"resolving dependency formats",
|| dependency_format::calculate(&tcx.sess));
|| dependency_format::calculate(tcx));

let translation =
time(time_passes,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_metadata/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePrefere
pub use rustc::middle::cstore::NativeLibraryKind::*;
pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};

pub use cstore_impl::provide;
pub use cstore_impl::{provide, provide_local};

// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
Expand Down
Loading