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,

View file

@ -20,6 +20,7 @@ pub use self::MovedValueUseKind::*;
use self::InteriorKind::*;
use rustc::dep_graph::DepNode;
use rustc::front::map as hir_map;
use rustc::front::map::blocks::FnParts;
use rustc::middle::cfg;
@ -109,7 +110,7 @@ pub fn check_crate(tcx: &ty::ctxt) {
}
};
tcx.map.krate().visit_all_items(&mut bccx);
tcx.visit_all_items_in_krate(DepNode::BorrowCheck, &mut bccx);
if tcx.sess.borrowck_stats() {
println!("--- borrowck stats ---");

View file

@ -801,7 +801,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
time(time_passes,
"rvalue checking",
|| middle::check_rvalues::check_crate(tcx, krate));
|| middle::check_rvalues::check_crate(tcx));
// Avoid overwhelming user with errors if type checking failed.
// I'm not sure how helpful this is, to be honest, but it avoids

View file

@ -204,6 +204,7 @@ impl PpSourceMode {
let annotation = TypedAnnotation {
tcx: tcx,
};
let _ignore = tcx.dep_graph.in_ignore();
f(&annotation,
payload,
&ast_map.forest.krate)

View file

@ -23,6 +23,7 @@ extern crate rustc_front;
use build;
use graphviz;
use transform::*;
use rustc::dep_graph::DepNode;
use rustc::mir::repr::Mir;
use hair::cx::Cx;
use std::fs::File;
@ -47,7 +48,7 @@ pub fn build_mir_for_crate<'tcx>(tcx: &ty::ctxt<'tcx>) -> MirMap<'tcx> {
tcx: tcx,
map: &mut map,
};
tcx.map.krate().visit_all_items(&mut dump);
tcx.visit_all_items_in_krate(DepNode::MirMapConstruction, &mut dump);
}
map
}

View file

@ -35,6 +35,7 @@ use std::mem::replace;
use rustc_front::hir;
use rustc_front::intravisit::{self, Visitor};
use rustc::dep_graph::DepNode;
use rustc::lint;
use rustc::middle::def;
use rustc::middle::def_id::DefId;
@ -1674,6 +1675,8 @@ pub fn check_crate(tcx: &ty::ctxt,
export_map: &def::ExportMap,
external_exports: ExternalExports)
-> AccessLevels {
let _task = tcx.dep_graph.in_task(DepNode::Privacy);
let krate = tcx.map.krate();
// Sanity check to make sure that all privacy usage and controls are

View file

@ -182,8 +182,10 @@ pub fn find_crate_name(sess: Option<&Session>,
"rust_out".to_string()
}
pub fn build_link_meta(sess: &Session, krate: &hir::Crate,
name: &str) -> LinkMeta {
pub fn build_link_meta(sess: &Session,
krate: &hir::Crate,
name: &str)
-> LinkMeta {
let r = LinkMeta {
crate_name: name.to_owned(),
crate_hash: Svh::calculate(&sess.opts.cg.metadata, krate),

View file

@ -716,6 +716,8 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l ty::ctxt<'tcx>,
analysis: &ty::CrateAnalysis,
cratename: &str,
odir: Option<&Path>) {
let _ignore = tcx.dep_graph.in_ignore();
if generated_code(krate.span) {
return;
}

View file

@ -43,6 +43,7 @@ use middle::weak_lang_items;
use middle::pat_util::simple_name;
use middle::subst::Substs;
use middle::ty::{self, Ty, HasTypeFlags};
use rustc::dep_graph::DepNode;
use rustc::front::map as hir_map;
use rustc::util::common::time;
use rustc_mir::mir_map::MirMap;
@ -2978,9 +2979,16 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
mir_map: &MirMap<'tcx>,
analysis: ty::CrateAnalysis)
-> CrateTranslation {
let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
let _task = tcx.dep_graph.in_task(DepNode::TransCrate);
// Be careful with this krate: obviously it gives access to the
// entire contents of the krate. So if you push any subtasks of
// `TransCrate`, you need to be careful to register "reads" of the
// particular items that will be processed.
let krate = tcx.map.krate();
let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
v
} else {
@ -3186,7 +3194,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TransItemsWithinModVisitor<'a, 'tcx> {
// skip modules, they will be uncovered by the TransModVisitor
}
_ => {
trans_item(self.ccx, i);
let def_id = self.ccx.tcx().map.local_def_id(i.id);
let tcx = self.ccx.tcx();
// Create a subtask for trans'ing a particular item. We are
// giving `trans_item` access to this item, so also record a read.
tcx.dep_graph.with_task(DepNode::TransCrateItem(def_id), || {
tcx.dep_graph.read(DepNode::Hir(def_id));
trans_item(self.ccx, i);
});
intravisit::walk_item(self, i);
}
}

View file

@ -15,12 +15,13 @@ use middle::subst::Substs;
use trans::base::{push_ctxt, trans_item, get_item_val, trans_fn};
use trans::common::*;
use rustc::dep_graph::DepNode;
use rustc_front::hir;
fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
-> Option<DefId> {
fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
debug!("instantiate_inline({:?})", fn_id);
let _icx = push_ctxt("instantiate_inline");
let _task = ccx.tcx().dep_graph.in_task(DepNode::TransInlinedItem(fn_id));
match ccx.external().borrow().get(&fn_id) {
Some(&Some(node_id)) => {

View file

@ -37,6 +37,7 @@ use trans::machine;
use trans::type_::Type;
use middle::ty::{self, Ty, HasTypeFlags};
use middle::subst::Substs;
use rustc::dep_graph::DepNode;
use rustc_front::hir;
use syntax::abi::{self, RustIntrinsic};
use syntax::ast;
@ -101,6 +102,7 @@ pub fn span_transmute_size_error(a: &Session, b: Span, msg: &str) {
/// Performs late verification that intrinsics are used correctly. At present,
/// the only intrinsic that needs such verification is `transmute`.
pub fn check_intrinsics(ccx: &CrateContext) {
let _task = ccx.tcx().dep_graph.in_task(DepNode::IntrinsicUseCheck);
let mut last_failing_id = None;
for transmute_restriction in ccx.tcx().transmute_restrictions.borrow().iter() {
// Sometimes, a single call to transmute will push multiple

View file

@ -82,6 +82,7 @@ use self::TupleArgumentsFlag::*;
use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
use check::_match::pat_ctxt;
use dep_graph::DepNode;
use fmt_macros::{Parser, Piece, Position};
use middle::astconv_util::prohibit_type_params;
use middle::cstore::LOCAL_CRATE;
@ -384,34 +385,33 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
pub fn check_wf_new(ccx: &CrateCtxt) {
ccx.tcx.sess.abort_if_new_errors(|| {
let krate = ccx.tcx.map.krate();
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(ccx);
krate.visit_all_items(&mut visit);
ccx.tcx.visit_all_items_in_krate(DepNode::WfCheck, &mut visit);
});
}
pub fn check_item_types(ccx: &CrateCtxt) {
ccx.tcx.sess.abort_if_new_errors(|| {
let krate = ccx.tcx.map.krate();
let mut visit = CheckItemTypesVisitor { ccx: ccx };
krate.visit_all_items(&mut visit);
ccx.tcx.visit_all_items_in_krate(DepNode::TypeckItemType, &mut visit);
});
}
pub fn check_item_bodies(ccx: &CrateCtxt) {
ccx.tcx.sess.abort_if_new_errors(|| {
let krate = ccx.tcx.map.krate();
let mut visit = CheckItemBodiesVisitor { ccx: ccx };
krate.visit_all_items(&mut visit);
ccx.tcx.visit_all_items_in_krate(DepNode::TypeckItemBody, &mut visit);
});
}
pub fn check_drop_impls(ccx: &CrateCtxt) {
ccx.tcx.sess.abort_if_new_errors(|| {
let _task = ccx.tcx.dep_graph.in_task(DepNode::Dropck);
let drop_trait = match ccx.tcx.lang_items.drop_trait() {
Some(id) => ccx.tcx.lookup_trait_def(id), None => { return }
};
drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| {
let _task = ccx.tcx.dep_graph.in_task(DepNode::DropckImpl(drop_impl_did));
if drop_impl_did.is_local() {
match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
Ok(()) => {}

View file

@ -39,9 +39,10 @@ use std::rc::Rc;
use syntax::codemap::Span;
use syntax::parse::token;
use util::nodemap::{DefIdMap, FnvHashMap};
use rustc::dep_graph::DepNode;
use rustc::front::map as hir_map;
use rustc_front::intravisit;
use rustc_front::hir::{Item, ItemImpl,Crate};
use rustc_front::hir::{Item, ItemImpl};
use rustc_front::hir;
mod orphan;
@ -104,11 +105,13 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
}
impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
fn check(&self, krate: &Crate) {
fn check(&self) {
// Check implementations and traits. This populates the tables
// containing the inherent methods and extension methods. It also
// builds up the trait inheritance table.
krate.visit_all_items(&mut CoherenceCheckVisitor { cc: self });
self.crate_context.tcx.visit_all_items_in_krate(
DepNode::CoherenceCheckImpl,
&mut CoherenceCheckVisitor { cc: self });
// Copy over the inherent impls we gathered up during the walk into
// the tcx.
@ -513,11 +516,13 @@ fn enforce_trait_manually_implementable(tcx: &ty::ctxt, sp: Span, trait_def_id:
}
pub fn check_coherence(crate_context: &CrateCtxt) {
let _task = crate_context.tcx.dep_graph.in_task(DepNode::Coherence);
let infcx = new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None, true);
CoherenceChecker {
crate_context: crate_context,
inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None, true),
inference_context: infcx,
inherent_impls: RefCell::new(FnvHashMap()),
}.check(crate_context.tcx.map.krate());
}.check();
unsafety::check(crate_context.tcx);
orphan::check(crate_context.tcx);
overlap::check(crate_context.tcx);

View file

@ -17,12 +17,13 @@ use middle::traits;
use middle::ty;
use syntax::ast;
use syntax::codemap::Span;
use rustc::dep_graph::DepNode;
use rustc_front::intravisit;
use rustc_front::hir;
pub fn check(tcx: &ty::ctxt) {
let mut orphan = OrphanChecker { tcx: tcx };
tcx.map.krate().visit_all_items(&mut orphan);
tcx.visit_all_items_in_krate(DepNode::CoherenceOrphanCheck, &mut orphan);
}
struct OrphanChecker<'cx, 'tcx:'cx> {
@ -234,10 +235,10 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
}
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
span_err!(self.tcx.sess, item.span, E0210,
"type parameter `{}` must be used as the type parameter for \
some local type (e.g. `MyStruct<T>`); only traits defined in \
the current crate can be implemented for a type parameter",
param_ty);
"type parameter `{}` must be used as the type parameter for \
some local type (e.g. `MyStruct<T>`); only traits defined in \
the current crate can be implemented for a type parameter",
param_ty);
return;
}
}

View file

@ -79,6 +79,7 @@ use middle::ty::{VariantKind};
use middle::ty::fold::{TypeFolder};
use middle::ty::util::IntTypeExt;
use rscope::*;
use rustc::dep_graph::DepNode;
use rustc::front::map as hir_map;
use util::common::{ErrorReported, memoized};
use util::nodemap::{FnvHashMap, FnvHashSet};
@ -174,13 +175,11 @@ struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
}
impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
fn visit_item(&mut self, i: &hir::Item) {
convert_item(self.ccx, i);
intravisit::walk_item(self, i);
}
fn visit_foreign_item(&mut self, i: &hir::ForeignItem) {
convert_foreign_item(self.ccx, i);
intravisit::walk_foreign_item(self, i);
fn visit_item(&mut self, item: &hir::Item) {
let tcx = self.ccx.tcx;
let item_def_id = tcx.map.local_def_id(item.id);
let _task = tcx.dep_graph.in_task(DepNode::CollectItem(item_def_id));
convert_item(self.ccx, item);
}
}
@ -703,8 +702,12 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
debug!("convert: item {} with id {}", it.name, it.id);
match it.node {
// These don't define types.
hir::ItemExternCrate(_) | hir::ItemUse(_) |
hir::ItemForeignMod(_) | hir::ItemMod(_) => {
hir::ItemExternCrate(_) | hir::ItemUse(_) | hir::ItemMod(_) => {
}
hir::ItemForeignMod(ref foreign_mod) => {
for item in &foreign_mod.items {
convert_foreign_item(ccx, item);
}
}
hir::ItemEnum(ref enum_definition, _) => {
let (scheme, predicates) = convert_typed_item(ccx, it);
@ -1455,6 +1458,11 @@ fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
it: &hir::Item)
-> ty::TypeScheme<'tcx>
{
// Computing the type scheme of an item is a discrete task:
let item_def_id = ccx.tcx.map.local_def_id(it.id);
let _task = ccx.tcx.dep_graph.in_task(DepNode::TypeScheme(item_def_id));
ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); // we have access to `it`
memoized(&ccx.tcx.tcache,
ccx.tcx.map.local_def_id(it.id),
|_| compute_type_scheme_of_item(ccx, it))
@ -1571,13 +1579,18 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
fn type_scheme_of_foreign_item<'a, 'tcx>(
ccx: &CrateCtxt<'a, 'tcx>,
it: &hir::ForeignItem,
item: &hir::ForeignItem,
abi: abi::Abi)
-> ty::TypeScheme<'tcx>
{
// Computing the type scheme of a foreign item is a discrete task:
let item_def_id = ccx.tcx.map.local_def_id(item.id);
let _task = ccx.tcx.dep_graph.in_task(DepNode::TypeScheme(item_def_id));
ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); // we have access to `item`
memoized(&ccx.tcx.tcache,
ccx.tcx.map.local_def_id(it.id),
|_| compute_type_scheme_of_foreign_item(ccx, it, abi))
ccx.tcx.map.local_def_id(item.id),
|_| compute_type_scheme_of_foreign_item(ccx, item, abi))
}
fn compute_type_scheme_of_foreign_item<'a, 'tcx>(

View file

@ -92,6 +92,7 @@ extern crate rustc_platform_intrinsics as intrinsics;
extern crate rustc_front;
extern crate rustc_back;
pub use rustc::dep_graph;
pub use rustc::front;
pub use rustc::lint;
pub use rustc::middle;

View file

@ -266,6 +266,7 @@ use self::ParamKind::*;
use arena;
use arena::TypedArena;
use dep_graph::DepNode;
use middle::def_id::DefId;
use middle::resolve_lifetime as rl;
use middle::subst;
@ -280,6 +281,7 @@ use rustc_front::intravisit::Visitor;
use util::nodemap::NodeMap;
pub fn infer_variance(tcx: &ty::ctxt) {
let _task = tcx.dep_graph.in_task(DepNode::Variance);
let krate = tcx.map.krate();
let mut arena = arena::TypedArena::new();
let terms_cx = determine_parameters_to_be_inferred(tcx, &mut arena, krate);

View file

@ -154,6 +154,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
&name,
resolve::MakeGlobMap::No,
|tcx, _, analysis| {
let _ignore = tcx.dep_graph.in_ignore();
let ty::CrateAnalysis { access_levels, .. } = analysis;
// Convert from a NodeId set to a DefId set since we don't always have easy access