1
Fork 0

rustc_typeck: save the type cache for rustdoc and save-analysis.

This commit is contained in:
Eduard Burtescu 2016-10-29 13:19:59 +03:00 committed by Eduard-Mihai Burtescu
parent 962633cdbb
commit da47c2e2ac
10 changed files with 111 additions and 81 deletions

View file

@ -29,8 +29,7 @@ use ty;
use ty::subst::{Subst, Substs};
use ty::walk::TypeWalker;
use util::common::MemoizationMap;
use util::nodemap::NodeSet;
use util::nodemap::{FxHashMap, FxHashSet};
use util::nodemap::{NodeSet, NodeMap, FxHashMap, FxHashSet};
use serialize::{self, Encodable, Encoder};
use std::borrow::Cow;
@ -111,12 +110,13 @@ pub type Disr = ConstInt;
/// The complete set of all analyses described in this module. This is
/// produced by the driver and fed to trans and later passes.
#[derive(Clone)]
pub struct CrateAnalysis<'a> {
pub struct CrateAnalysis<'tcx> {
pub export_map: ExportMap,
pub access_levels: middle::privacy::AccessLevels,
pub reachable: NodeSet,
pub name: &'a str,
pub name: String,
pub glob_map: Option<hir::GlobMap>,
pub hir_ty_to_ty: NodeMap<Ty<'tcx>>,
}
#[derive(Copy, Clone)]

View file

@ -25,7 +25,7 @@ use rustc::middle::{self, dependency_format, stability, reachable};
use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt};
use rustc::util::common::time;
use rustc::util::nodemap::NodeSet;
use rustc::util::nodemap::{NodeSet, NodeMap};
use rustc_borrowck as borrowck;
use rustc_incremental::{self, IncrementalHashesMap};
use rustc_resolve::{MakeGlobMap, Resolver};
@ -332,9 +332,9 @@ impl<'a> PhaseController<'a> {
/// State that is passed to a callback. What state is available depends on when
/// during compilation the callback is made. See the various constructor methods
/// (`state_*`) in the impl to see which data is provided for any given entry point.
pub struct CompileState<'a, 'b, 'ast: 'a, 'tcx: 'b> where 'ast: 'tcx {
pub struct CompileState<'a, 'tcx: 'a> {
pub input: &'a Input,
pub session: &'ast Session,
pub session: &'tcx Session,
pub krate: Option<ast::Crate>,
pub registry: Option<Registry<'a>>,
pub cstore: Option<&'a CStore>,
@ -342,21 +342,21 @@ pub struct CompileState<'a, 'b, 'ast: 'a, 'tcx: 'b> where 'ast: 'tcx {
pub output_filenames: Option<&'a OutputFilenames>,
pub out_dir: Option<&'a Path>,
pub out_file: Option<&'a Path>,
pub arenas: Option<&'ast ty::CtxtArenas<'ast>>,
pub arenas: Option<&'tcx ty::CtxtArenas<'tcx>>,
pub expanded_crate: Option<&'a ast::Crate>,
pub hir_crate: Option<&'a hir::Crate>,
pub ast_map: Option<&'a hir_map::Map<'ast>>,
pub ast_map: Option<&'a hir_map::Map<'tcx>>,
pub resolutions: Option<&'a Resolutions>,
pub analysis: Option<&'a ty::CrateAnalysis<'a>>,
pub tcx: Option<TyCtxt<'b, 'tcx, 'tcx>>,
pub analysis: Option<&'a ty::CrateAnalysis<'tcx>>,
pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
pub trans: Option<&'a trans::CrateTranslation>,
}
impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
impl<'a, 'tcx> CompileState<'a, 'tcx> {
fn empty(input: &'a Input,
session: &'ast Session,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>)
-> CompileState<'a, 'b, 'ast, 'tcx> {
-> Self {
CompileState {
input: input,
session: session,
@ -379,12 +379,12 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
}
fn state_after_parse(input: &'a Input,
session: &'ast Session,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>,
out_file: &'a Option<PathBuf>,
krate: ast::Crate,
cstore: &'a CStore)
-> CompileState<'a, 'b, 'ast, 'tcx> {
-> Self {
CompileState {
// Initialize the registry before moving `krate`
registry: Some(Registry::new(&session, krate.span)),
@ -396,13 +396,13 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
}
fn state_after_expand(input: &'a Input,
session: &'ast Session,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>,
out_file: &'a Option<PathBuf>,
cstore: &'a CStore,
expanded_crate: &'a ast::Crate,
crate_name: &'a str)
-> CompileState<'a, 'b, 'ast, 'tcx> {
-> Self {
CompileState {
crate_name: Some(crate_name),
cstore: Some(cstore),
@ -413,18 +413,18 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
}
fn state_after_hir_lowering(input: &'a Input,
session: &'ast Session,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>,
out_file: &'a Option<PathBuf>,
arenas: &'ast ty::CtxtArenas<'ast>,
arenas: &'tcx ty::CtxtArenas<'tcx>,
cstore: &'a CStore,
hir_map: &'a hir_map::Map<'ast>,
analysis: &'a ty::CrateAnalysis,
hir_map: &'a hir_map::Map<'tcx>,
analysis: &'a ty::CrateAnalysis<'static>,
resolutions: &'a Resolutions,
krate: &'a ast::Crate,
hir_crate: &'a hir::Crate,
crate_name: &'a str)
-> CompileState<'a, 'b, 'ast, 'tcx> {
-> Self {
CompileState {
crate_name: Some(crate_name),
arenas: Some(arenas),
@ -440,15 +440,15 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
}
fn state_after_analysis(input: &'a Input,
session: &'ast Session,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>,
out_file: &'a Option<PathBuf>,
krate: Option<&'a ast::Crate>,
hir_crate: &'a hir::Crate,
analysis: &'a ty::CrateAnalysis<'a>,
tcx: TyCtxt<'b, 'tcx, 'tcx>,
analysis: &'a ty::CrateAnalysis<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
crate_name: &'a str)
-> CompileState<'a, 'b, 'ast, 'tcx> {
-> Self {
CompileState {
analysis: Some(analysis),
tcx: Some(tcx),
@ -462,11 +462,11 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
fn state_after_llvm(input: &'a Input,
session: &'ast Session,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>,
out_file: &'a Option<PathBuf>,
trans: &'a trans::CrateTranslation)
-> CompileState<'a, 'b, 'ast, 'tcx> {
-> Self {
CompileState {
trans: Some(trans),
out_file: out_file.as_ref().map(|s| &**s),
@ -475,10 +475,10 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
}
fn state_when_compilation_done(input: &'a Input,
session: &'ast Session,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>,
out_file: &'a Option<PathBuf>)
-> CompileState<'a, 'b, 'ast, 'tcx> {
-> Self {
CompileState {
out_file: out_file.as_ref().map(|s| &**s),
..CompileState::empty(input, session, out_dir)
@ -532,10 +532,10 @@ fn count_nodes(krate: &ast::Crate) -> usize {
// For continuing compilation after a parsed crate has been
// modified
pub struct ExpansionResult<'a> {
pub struct ExpansionResult {
pub expanded_crate: ast::Crate,
pub defs: hir_map::Definitions,
pub analysis: ty::CrateAnalysis<'a>,
pub analysis: ty::CrateAnalysis<'static>,
pub resolutions: Resolutions,
pub hir_forest: hir_map::Forest,
}
@ -547,15 +547,15 @@ pub struct ExpansionResult<'a> {
/// standard library and prelude, and name resolution.
///
/// Returns `None` if we're aborting after handling -W help.
pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
cstore: &CStore,
krate: ast::Crate,
registry: Option<Registry>,
crate_name: &'a str,
addl_plugins: Option<Vec<String>>,
make_glob_map: MakeGlobMap,
after_expand: F)
-> Result<ExpansionResult<'a>, usize>
pub fn phase_2_configure_and_expand<F>(sess: &Session,
cstore: &CStore,
krate: ast::Crate,
registry: Option<Registry>,
crate_name: &str,
addl_plugins: Option<Vec<String>>,
make_glob_map: MakeGlobMap,
after_expand: F)
-> Result<ExpansionResult, usize>
where F: FnOnce(&ast::Crate) -> CompileResult,
{
let time_passes = sess.time_passes();
@ -789,8 +789,9 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
export_map: resolver.export_map,
access_levels: AccessLevels::default(),
reachable: NodeSet(),
name: crate_name,
name: crate_name.to_string(),
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
hir_ty_to_ty: NodeMap(),
},
resolutions: Resolutions {
def_map: resolver.def_map,
@ -807,14 +808,14 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
/// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
hir_map: hir_map::Map<'tcx>,
mut analysis: ty::CrateAnalysis,
mut analysis: ty::CrateAnalysis<'tcx>,
resolutions: Resolutions,
arenas: &'tcx ty::CtxtArenas<'tcx>,
name: &str,
f: F)
-> Result<R, usize>
where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>,
ty::CrateAnalysis,
ty::CrateAnalysis<'tcx>,
IncrementalHashesMap,
CompileResult) -> R
{
@ -886,7 +887,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|| rustc_incremental::load_dep_graph(tcx, &incremental_hashes_map));
// passes are timed inside typeck
try_with_f!(typeck::check_crate(tcx), (tcx, analysis, incremental_hashes_map));
analysis.hir_ty_to_ty =
try_with_f!(typeck::check_crate(tcx), (tcx, analysis, incremental_hashes_map));
time(time_passes,
"const checking",

View file

@ -200,7 +200,7 @@ impl PpSourceMode {
fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
sess: &'tcx Session,
ast_map: &hir_map::Map<'tcx>,
analysis: &ty::CrateAnalysis,
analysis: &ty::CrateAnalysis<'tcx>,
resolutions: &Resolutions,
arenas: &'tcx ty::CtxtArenas<'tcx>,
id: &str,
@ -817,7 +817,7 @@ pub fn print_after_parsing(sess: &Session,
pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
ast_map: &hir_map::Map<'tcx>,
analysis: &ty::CrateAnalysis,
analysis: &ty::CrateAnalysis<'tcx>,
resolutions: &Resolutions,
input: &Input,
krate: &ast::Crate,
@ -934,7 +934,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
// Instead, we call that function ourselves.
fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
ast_map: &hir_map::Map<'tcx>,
analysis: &ty::CrateAnalysis,
analysis: &ty::CrateAnalysis<'tcx>,
resolutions: &Resolutions,
crate_name: &str,
arenas: &'tcx ty::CtxtArenas<'tcx>,

View file

@ -68,7 +68,6 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, D: 'll> {
save_ctxt: SaveContext<'l, 'tcx>,
sess: &'l Session,
tcx: TyCtxt<'l, 'tcx, 'tcx>,
analysis: &'l ty::CrateAnalysis<'l>,
dumper: &'ll mut D,
span: SpanUtils<'l>,
@ -84,17 +83,14 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, D: 'll> {
}
impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
pub fn new(tcx: TyCtxt<'l, 'tcx, 'tcx>,
save_ctxt: SaveContext<'l, 'tcx>,
analysis: &'l ty::CrateAnalysis<'l>,
pub fn new(save_ctxt: SaveContext<'l, 'tcx>,
dumper: &'ll mut D)
-> DumpVisitor<'l, 'tcx, 'll, D> {
let span_utils = SpanUtils::new(&tcx.sess);
let span_utils = SpanUtils::new(&save_ctxt.tcx.sess);
DumpVisitor {
sess: &tcx.sess,
tcx: tcx,
sess: &save_ctxt.tcx.sess,
tcx: save_ctxt.tcx,
save_ctxt: save_ctxt,
analysis: analysis,
dumper: dumper,
span: span_utils.clone(),
cur_scope: CRATE_NODE_ID,
@ -1207,7 +1203,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
ast::ViewPathGlob(ref path) => {
// Make a comma-separated list of names of imported modules.
let mut names = vec![];
let glob_map = &self.analysis.glob_map;
let glob_map = &self.save_ctxt.analysis.glob_map;
let glob_map = glob_map.as_ref().unwrap();
if glob_map.contains_key(&item.id) {
for n in glob_map.get(&item.id).unwrap() {

View file

@ -85,6 +85,7 @@ pub mod recorder {
pub struct SaveContext<'l, 'tcx: 'l> {
tcx: TyCtxt<'l, 'tcx, 'tcx>,
analysis: &'l ty::CrateAnalysis<'tcx>,
span_utils: SpanUtils<'tcx>,
}
@ -93,16 +94,20 @@ macro_rules! option_try(
);
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
pub fn new(tcx: TyCtxt<'l, 'tcx, 'tcx>) -> SaveContext<'l, 'tcx> {
pub fn new(tcx: TyCtxt<'l, 'tcx, 'tcx>,
analysis: &'l ty::CrateAnalysis<'tcx>)
-> SaveContext<'l, 'tcx> {
let span_utils = SpanUtils::new(&tcx.sess);
SaveContext::from_span_utils(tcx, span_utils)
SaveContext::from_span_utils(tcx, analysis, span_utils)
}
pub fn from_span_utils(tcx: TyCtxt<'l, 'tcx, 'tcx>,
analysis: &'l ty::CrateAnalysis<'tcx>,
span_utils: SpanUtils<'tcx>)
-> SaveContext<'l, 'tcx> {
SaveContext {
tcx: tcx,
analysis: analysis,
span_utils: span_utils,
}
}
@ -520,8 +525,18 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
match *qpath {
hir::QPath::Resolved(_, ref path) => path.def,
hir::QPath::TypeRelative(..) => {
// FIXME(eddyb) Avoid keeping associated type resolutions.
self.tcx.tables().type_relative_path_defs[&id]
if let Some(ty) = self.analysis.hir_ty_to_ty.get(&id) {
if let ty::TyProjection(proj) = ty.sty {
for item in self.tcx.associated_items(proj.trait_ref.def_id) {
if item.kind == ty::AssociatedKind::Type {
if item.name == proj.item_name {
return Def::AssociatedTy(item.def_id);
}
}
}
}
}
Def::Err
}
}
}
@ -799,7 +814,7 @@ impl Format {
pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
krate: &ast::Crate,
analysis: &'l ty::CrateAnalysis<'l>,
analysis: &'l ty::CrateAnalysis<'tcx>,
cratename: &str,
odir: Option<&Path>,
format: Format) {
@ -847,12 +862,12 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
root_path.pop();
let output = &mut output_file;
let save_ctxt = SaveContext::new(tcx);
let save_ctxt = SaveContext::new(tcx, analysis);
macro_rules! dump {
($new_dumper: expr) => {{
let mut dumper = $new_dumper;
let mut visitor = DumpVisitor::new(tcx, save_ctxt, analysis, &mut dumper);
let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
visitor.dump_crate_info(cratename, krate);
visit::walk_crate(&mut visitor, krate);

View file

@ -1545,7 +1545,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
tcx.sess.opts.debug_assertions
};
let link_meta = link::build_link_meta(incremental_hashes_map, name);
let link_meta = link::build_link_meta(incremental_hashes_map, &name);
let shared_ccx = SharedCrateContext::new(tcx,
export_map,

View file

@ -43,6 +43,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
wbcx.visit_liberated_fn_sigs();
wbcx.visit_fru_field_types();
wbcx.visit_deferred_obligations(item_id);
wbcx.visit_type_nodes();
}
pub fn resolve_type_vars_in_fn(&self,
@ -67,6 +68,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
wbcx.visit_fru_field_types();
wbcx.visit_anon_types();
wbcx.visit_deferred_obligations(item_id);
wbcx.visit_type_nodes();
}
}
@ -478,6 +480,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
}
}
fn visit_type_nodes(&self) {
for (&id, ty) in self.fcx.ast_ty_to_ty_cache.borrow().iter() {
let ty = self.resolve(ty, ResolvingTyNode(id));
self.fcx.ccx.ast_ty_to_ty_cache.borrow_mut().insert(id, ty);
}
}
fn resolve<T>(&self, x: &T, reason: ResolveReason) -> T::Lifted
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
{
@ -505,6 +514,7 @@ enum ResolveReason {
ResolvingFieldTypes(ast::NodeId),
ResolvingAnonTy(DefId),
ResolvingDeferredObligation(Span),
ResolvingTyNode(ast::NodeId),
}
impl<'a, 'gcx, 'tcx> ResolveReason {
@ -516,10 +526,9 @@ impl<'a, 'gcx, 'tcx> ResolveReason {
ResolvingUpvar(upvar_id) => {
tcx.expr_span(upvar_id.closure_expr_id)
}
ResolvingFnSig(id) => {
tcx.map.span(id)
}
ResolvingFieldTypes(id) => {
ResolvingFnSig(id) |
ResolvingFieldTypes(id) |
ResolvingTyNode(id) => {
tcx.map.span(id)
}
ResolvingClosure(did) |
@ -601,7 +610,8 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> {
ResolvingFnSig(_) |
ResolvingFieldTypes(_) |
ResolvingDeferredObligation(_) => {
ResolvingDeferredObligation(_) |
ResolvingTyNode(_) => {
// any failures here should also fail when
// resolving the patterns, closure types, or
// something else.

View file

@ -111,7 +111,7 @@ use rustc::infer::InferOk;
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
use session::{config, CompileResult};
use session::config;
use util::common::time;
use syntax::ast;
@ -314,7 +314,7 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> CompileResult {
-> Result<NodeMap<Ty<'tcx>>, usize> {
let time_passes = tcx.sess.time_passes();
let ccx = CrateCtxt {
ast_ty_to_ty_cache: RefCell::new(NodeMap()),
@ -358,7 +358,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
let err_count = tcx.sess.err_count();
if err_count == 0 {
Ok(())
Ok(ccx.ast_ty_to_ty_cache.into_inner())
} else {
Err(err_count)
}

View file

@ -1782,13 +1782,16 @@ impl Clean<Type> for hir::Ty {
}
}
TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => {
let mut def = Def::Err;
if let Some(ty) = cx.hir_ty_to_ty.get(&self.id) {
if let ty::TyProjection(proj) = ty.sty {
def = Def::Trait(proj.trait_ref.def_id);
}
}
let trait_path = hir::Path {
span: self.span,
global: false,
def: cx.tcx_opt().map_or(Def::Err, |tcx| {
let def_id = tcx.tables().type_relative_path_defs[&self.id].def_id();
Def::Trait(tcx.associated_item(def_id).container.id())
}),
def: def,
segments: vec![].into(),
};
Type::QPath {

View file

@ -15,10 +15,10 @@ use rustc::session::{self, config};
use rustc::hir::def_id::DefId;
use rustc::hir::def::{Def, ExportMap};
use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt};
use rustc::ty::{self, TyCtxt, Ty};
use rustc::hir::map as hir_map;
use rustc::lint;
use rustc::util::nodemap::FxHashMap;
use rustc::util::nodemap::{FxHashMap, NodeMap};
use rustc_trans::back::link;
use rustc_resolve as resolve;
use rustc_metadata::cstore::CStore;
@ -65,6 +65,9 @@ pub struct DocContext<'a, 'tcx: 'a> {
/// Table node id of lifetime parameter definition -> substituted lifetime
pub lt_substs: RefCell<FxHashMap<ast::NodeId, clean::Lifetime>>,
pub export_map: ExportMap,
/// Table from HIR Ty nodes to their resolved Ty.
pub hir_ty_to_ty: NodeMap<Ty<'tcx>>,
}
impl<'a, 'tcx> DocContext<'a, 'tcx> {
@ -172,7 +175,7 @@ pub fn run_core(search_paths: SearchPaths,
sess.fatal("Compilation failed, aborting rustdoc");
}
let ty::CrateAnalysis { access_levels, export_map, .. } = analysis;
let ty::CrateAnalysis { access_levels, export_map, hir_ty_to_ty, .. } = analysis;
// Convert from a NodeId set to a DefId set since we don't always have easy access
// to the map from defid -> nodeid
@ -192,6 +195,7 @@ pub fn run_core(search_paths: SearchPaths,
ty_substs: Default::default(),
lt_substs: Default::default(),
export_map: export_map,
hir_ty_to_ty: hir_ty_to_ty,
};
debug!("crate: {:?}", tcx.map.krate());