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;
/// 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)]
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};
/// 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>,
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,
}
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)),
}
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),
}
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),
}
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),
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),
}
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)
// 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,
}
/// 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();
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,
/// 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
{
|| 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",
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,
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,
// 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>,
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>,
}
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,
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() {
pub struct SaveContext<'l, 'tcx: 'l> {
tcx: TyCtxt<'l, 'tcx, 'tcx>,
+ analysis: &'l ty::CrateAnalysis<'tcx>,
span_utils: SpanUtils<'tcx>,
}
);
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,
}
}
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
}
}
}
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) {
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);
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,
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,
wbcx.visit_fru_field_types();
wbcx.visit_anon_types();
wbcx.visit_deferred_obligations(item_id);
+ wbcx.visit_type_nodes();
}
}
}
}
+ 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>
{
ResolvingFieldTypes(ast::NodeId),
ResolvingAnonTy(DefId),
ResolvingDeferredObligation(Span),
+ ResolvingTyNode(ast::NodeId),
}
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) |
ResolvingFnSig(_) |
ResolvingFieldTypes(_) |
- ResolvingDeferredObligation(_) => {
+ ResolvingDeferredObligation(_) |
+ ResolvingTyNode(_) => {
// any failures here should also fail when
// resolving the patterns, closure types, or
// something else.
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;
}
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()),
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)
}
}
}
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 {
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;
/// 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> {
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
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());