Annotate the compiler with information about what it is doing when.

This commit is contained in:
Niko Matsakis 2015-12-22 16:35:02 -05:00
parent aa265869ba
commit 005fa14358
29 changed files with 171 additions and 50 deletions

View file

@ -25,6 +25,7 @@
//! for all lint attributes.
use self::TargetLint::*;
use dep_graph::DepNode;
use middle::privacy::AccessLevels;
use middle::ty;
use session::{early_error, Session};
@ -1071,6 +1072,8 @@ impl LateLintPass for GatherNodeLevels {
///
/// Consumes the `lint_store` field of the `Session`.
pub fn check_crate(tcx: &ty::ctxt, access_levels: &AccessLevels) {
let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck);
let krate = tcx.map.krate();
let mut cx = LateContext::new(tcx, krate, access_levels);

View file

@ -24,6 +24,7 @@
// - It's not possible to take the address of a static item with unsafe interior. This is enforced
// by borrowck::gather_loans
use dep_graph::DepNode;
use middle::ty::cast::{CastKind};
use middle::const_eval::{self, ConstEvalErr};
use middle::const_eval::ErrKind::IndexOpFeatureGated;
@ -842,13 +843,12 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
}
pub fn check_crate(tcx: &ty::ctxt) {
tcx.map.krate().visit_all_items(&mut CheckCrateVisitor {
tcx.visit_all_items_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor {
tcx: tcx,
mode: Mode::Var,
qualif: ConstQualif::NOT_CONST,
rvalue_borrows: NodeMap()
});
tcx.sess.abort_if_errors();
}

View file

@ -12,6 +12,7 @@ pub use self::Constructor::*;
use self::Usefulness::*;
use self::WitnessPreference::*;
use dep_graph::DepNode;
use middle::const_eval::{compare_const_vals, ConstVal};
use middle::const_eval::{eval_const_expr, eval_const_expr_partial};
use middle::const_eval::{const_expr_to_pat, lookup_const_by_id};
@ -155,7 +156,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> {
}
pub fn check_crate(tcx: &ty::ctxt) {
tcx.map.krate().visit_all_items(&mut MatchCheckCtxt {
tcx.visit_all_items_in_krate(DepNode::MatchCheck, &mut MatchCheckCtxt {
tcx: tcx,
param_env: tcx.empty_parameter_environment(),
});

View file

@ -11,21 +11,21 @@
// Checks that all rvalues in a crate have statically known size. check_crate
// is the public starting point.
use dep_graph::DepNode;
use middle::expr_use_visitor as euv;
use middle::infer;
use middle::mem_categorization as mc;
use middle::ty::ParameterEnvironment;
use middle::ty;
use syntax::ast;
use rustc_front::hir;
use syntax::codemap::Span;
use rustc_front::intravisit;
use syntax::ast;
use syntax::codemap::Span;
pub fn check_crate(tcx: &ty::ctxt,
krate: &hir::Crate) {
pub fn check_crate(tcx: &ty::ctxt) {
let mut rvcx = RvalueContext { tcx: tcx };
krate.visit_all_items(&mut rvcx);
tcx.visit_all_items_in_krate(DepNode::RvalueCheck, &mut rvcx);
}
struct RvalueContext<'a, 'tcx: 'a> {

View file

@ -12,6 +12,7 @@
// closely. The idea is that all reachable symbols are live, codes called
// from live codes are live, and everything else is dead.
use dep_graph::DepNode;
use front::map as ast_map;
use rustc_front::hir;
use rustc_front::intravisit::{self, Visitor};
@ -590,6 +591,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
}
pub fn check_crate(tcx: &ty::ctxt, access_levels: &privacy::AccessLevels) {
let _task = tcx.dep_graph.in_task(DepNode::DeadCheck);
let krate = tcx.map.krate();
let live_symbols = find_live(tcx, access_levels, krate);
let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };

View file

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use dep_graph::DepNode;
use middle::def::DefFn;
use middle::def_id::DefId;
use middle::subst::{Subst, Substs, EnumeratedItems};
@ -29,7 +30,7 @@ pub fn check_crate(tcx: &ctxt) {
dummy_sized_ty: tcx.types.isize,
dummy_unsized_ty: tcx.mk_slice(tcx.types.isize),
};
tcx.map.krate().visit_all_items(&mut visitor);
tcx.visit_all_items_in_krate(DepNode::IntrinsicCheck, &mut visitor);
}
struct IntrinsicCheckingVisitor<'a, 'tcx: 'a> {

View file

@ -15,6 +15,7 @@
// makes all other generics or inline functions that it references
// reachable as well.
use dep_graph::DepNode;
use front::map as ast_map;
use middle::def;
use middle::def_id::DefId;
@ -349,6 +350,7 @@ impl<'a, 'v> Visitor<'v> for CollectPrivateImplItemsVisitor<'a> {
pub fn find_reachable(tcx: &ty::ctxt,
access_levels: &privacy::AccessLevels)
-> NodeSet {
let _task = tcx.dep_graph.in_task(DepNode::Reachability);
let mut reachable_context = ReachableContext::new(tcx);

View file

@ -13,6 +13,7 @@
pub use self::StabilityLevel::*;
use dep_graph::DepNode;
use session::Session;
use lint;
use middle::cstore::{CrateStore, LOCAL_CRATE};
@ -328,6 +329,7 @@ impl<'tcx> Index<'tcx> {
/// features used.
pub fn check_unstable_api_usage(tcx: &ty::ctxt)
-> FnvHashMap<InternedString, StabilityLevel> {
let _task = tcx.dep_graph.in_task(DepNode::StabilityCheck);
let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features;
// Put the active features into a map for quick lookup
@ -341,8 +343,7 @@ pub fn check_unstable_api_usage(tcx: &ty::ctxt)
};
intravisit::walk_crate(&mut checker, tcx.map.krate());
let used_features = checker.used_features;
return used_features;
checker.used_features
}
struct Checker<'a, 'tcx: 'a> {

View file

@ -15,10 +15,12 @@ pub use self::FulfillmentErrorCode::*;
pub use self::Vtable::*;
pub use self::ObligationCauseCode::*;
use dep_graph::DepNode;
use middle::def_id::DefId;
use middle::free_region::FreeRegionMap;
use middle::subst;
use middle::ty::{self, HasTypeFlags, Ty};
use middle::ty::fast_reject;
use middle::ty::fold::TypeFoldable;
use middle::infer::{self, fixup_err_to_string, InferCtxt};
@ -599,6 +601,18 @@ impl<'tcx> FulfillmentError<'tcx> {
}
impl<'tcx> TraitObligation<'tcx> {
/// Creates the dep-node for selecting/evaluating this trait reference.
fn dep_node(&self, tcx: &ty::ctxt<'tcx>) -> DepNode {
let simplified_ty =
fast_reject::simplify_type(tcx,
self.predicate.skip_binder().self_ty(), // (*)
true);
// (*) skip_binder is ok because `simplify_type` doesn't care about regions
DepNode::TraitSelect(self.predicate.def_id(), simplified_ty)
}
fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
ty::Binder(self.predicate.skip_binder().self_ty())
}

View file

@ -310,6 +310,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!("select({:?})", obligation);
assert!(!obligation.predicate.has_escaping_regions());
let dep_node = obligation.dep_node(self.tcx());
let _task = self.tcx().dep_graph.in_task(dep_node);
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
match try!(self.candidate_from_obligation(&stack)) {
None => {
@ -411,7 +414,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// accurate if inference variables are involved.
pub fn evaluate_obligation_conservatively(&mut self,
obligation: &PredicateObligation<'tcx>)
-> bool
-> bool
{
debug!("evaluate_obligation_conservatively({:?})",
obligation);

View file

@ -51,6 +51,7 @@ use syntax::parse::token::{InternedString, special_idents};
use rustc_front::hir;
use rustc_front::hir::{ItemImpl, ItemTrait};
use rustc_front::intravisit::Visitor;
pub use self::sty::{Binder, DebruijnIndex};
pub use self::sty::{BuiltinBound, BuiltinBounds, ExistentialBounds};
@ -1946,7 +1947,14 @@ fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
panic!("No def'n found for {:?} in tcx.{}", def_id, descr);
}
let v = load_external();
map.borrow_mut().insert(def_id, v.clone());
// Don't consider this a write from the current task, since we are
// loading from another crate. (Note that the current task will
// already have registered a read in the call to `get` above.)
dep_graph.with_ignore(|| {
map.borrow_mut().insert(def_id, v.clone());
});
v
}
@ -2458,6 +2466,10 @@ impl<'tcx> ctxt<'tcx> {
return
}
// The primitive is not local, hence we are reading this out
// of metadata.
let _ignore = self.dep_graph.in_ignore();
if self.populated_external_primitive_impls.borrow().contains(&primitive_def_id) {
return
}
@ -2480,6 +2492,10 @@ impl<'tcx> ctxt<'tcx> {
return
}
// The type is not local, hence we are reading this out of
// metadata and don't need to track edges.
let _ignore = self.dep_graph.in_ignore();
if self.populated_external_types.borrow().contains(&type_id) {
return
}
@ -2505,6 +2521,10 @@ impl<'tcx> ctxt<'tcx> {
return
}
// The type is not local, hence we are reading this out of
// metadata and don't need to track edges.
let _ignore = self.dep_graph.in_ignore();
let def = self.lookup_trait_def(trait_id);
if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
return;
@ -2727,6 +2747,15 @@ impl<'tcx> ctxt<'tcx> {
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone())
}
pub fn visit_all_items_in_krate<V,F>(&self,
dep_node_fn: F,
visitor: &mut V)
where F: FnMut(DefId) -> DepNode, V: Visitor<'tcx>
{
dep_graph::visit_all_items_in_krate(self, dep_node_fn, visitor);
}
}
/// The category of explicit self.

View file

@ -125,6 +125,8 @@ pub struct Options {
pub parse_only: bool,
pub no_trans: bool,
pub treat_err_as_bug: bool,
pub incremental_compilation: bool,
pub dump_dep_graph: bool,
pub no_analysis: bool,
pub debugging_opts: DebuggingOptions,
pub prints: Vec<PrintRequest>,
@ -234,6 +236,8 @@ pub fn basic_options() -> Options {
parse_only: false,
no_trans: false,
treat_err_as_bug: false,
incremental_compilation: false,
dump_dep_graph: false,
no_analysis: false,
debugging_opts: basic_debugging_options(),
prints: Vec::new(),
@ -606,6 +610,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"run all passes except translation; no output"),
treat_err_as_bug: bool = (false, parse_bool,
"treat all errors that occur as bugs"),
incr_comp: bool = (false, parse_bool,
"enable incremental compilation (experimental)"),
dump_dep_graph: bool = (false, parse_bool,
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
no_analysis: bool = (false, parse_bool,
"parse and expand the source, but run no analysis"),
extra_plugins: Vec<String> = (Vec::new(), parse_list,
@ -932,6 +940,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let parse_only = debugging_opts.parse_only;
let no_trans = debugging_opts.no_trans;
let treat_err_as_bug = debugging_opts.treat_err_as_bug;
let incremental_compilation = debugging_opts.incr_comp;
let dump_dep_graph = debugging_opts.dump_dep_graph;
let no_analysis = debugging_opts.no_analysis;
if debugging_opts.debug_llvm {
@ -1106,6 +1116,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
parse_only: parse_only,
no_trans: no_trans,
treat_err_as_bug: treat_err_as_bug,
incremental_compilation: incremental_compilation || dump_dep_graph,
dump_dep_graph: dump_dep_graph,
no_analysis: no_analysis,
debugging_opts: debugging_opts,
prints: prints,