]> git.lizzy.rs Git - rust.git/commitdiff
rustc_typeck: save the type cache for rustdoc and save-analysis.
authorEduard Burtescu <edy.burt@gmail.com>
Sat, 29 Oct 2016 10:19:59 +0000 (13:19 +0300)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Mon, 28 Nov 2016 02:18:10 +0000 (04:18 +0200)
src/librustc/ty/mod.rs
src/librustc_driver/driver.rs
src/librustc_driver/pretty.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/base.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs

index ee7cf0788e57087694f4e693225383f2bd1a0194..3719090e922d0ee6f88f77cba81e3780545a4944 100644 (file)
@@ -29,8 +29,7 @@
 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)]
index a1d1d1105278cc3e8700632edc43e7f8be3b734d..0b148771f4fc84b6e8c7f562a3f02b4439c84e4b 100644 (file)
@@ -25,7 +25,7 @@
 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 @@ pub fn basic() -> 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 @@ fn empty(input: &'a Input,
     }
 
     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 @@ fn state_after_parse(input: &'a Input,
     }
 
     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 @@ fn state_after_expand(input: &'a Input,
     }
 
     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 @@ fn state_after_hir_lowering(input: &'a Input,
     }
 
     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 @@ fn state_after_analysis(input: &'a Input,
 
 
     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 @@ fn state_after_llvm(input: &'a Input,
     }
 
     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 @@ macro_rules! try_with_f {
              || 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",
index 6c99c9d71b81585da2090b0be656b88873703bf5..4759394aff169f37693a6e1f1c44f6698cb231ea 100644 (file)
@@ -200,7 +200,7 @@ fn call_with_pp_support<'tcx, A, B, F>(&self,
     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>,
index 3e7ca155da08469755fedebba7e0a4b433d59fce..c3b1649662a45086db8d8f4424eacb5ccfccaeb7 100644 (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 @@ fn visit_item(&mut self, item: &ast::Item) {
                     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() {
index e79ca6721db9a45a846553d2f4ebd3ddd2f5db6b..389892193c330cf289134a5e409d59ca907768d5 100644 (file)
@@ -85,6 +85,7 @@ pub enum Row {
 
 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 @@ pub fn get_path_def(&self, id: NodeId) -> Def {
                 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 @@ fn extension(&self) -> &'static str {
 
 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);
index d697a5bafb79ed5a6d9503fb88269c5fdb6fabab..c94c25e0b056cb2bcb78b11e360d5552fca139b8 100644 (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,
index 979ce82ff4ecd27524f9a3ed8a3801aabe994bf7..1e26d1b80d31e5df3544d291eaf970a47d9657c8 100644 (file)
@@ -43,6 +43,7 @@ pub fn resolve_type_vars_in_expr(&self, e: &hir::Expr, item_id: ast::NodeId) {
         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 @@ 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();
     }
 }
 
@@ -478,6 +480,13 @@ fn visit_deferred_obligations(&self, item_id: ast::NodeId) {
         }
     }
 
+    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 @@ fn span(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Span {
             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 @@ fn report_error(&self, e: FixupError) {
 
                 ResolvingFnSig(_) |
                 ResolvingFieldTypes(_) |
-                ResolvingDeferredObligation(_) => {
+                ResolvingDeferredObligation(_) |
+                ResolvingTyNode(_) => {
                     // any failures here should also fail when
                     // resolving the patterns, closure types, or
                     // something else.
index a1ee69791169e818c03abe7ab1d4ef7721d56e38..049add6f0620cd40b070b5b9a65e526df181901e 100644 (file)
 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)
     }
index 0fda1f4bf100aa1b8e49a9afd4fb187c0ac52ac3..e233613ee629e8844652371a4fd86ec96ec82f99 100644 (file)
@@ -1782,13 +1782,16 @@ fn clean(&self, cx: &DocContext) -> Type {
                 }
             }
             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 {
index 7d7b7fead5854d9fbd9944dc32f7e904fb6e8d32..4c2487e2b42a0b855f565caf4c87562955dcc250 100644 (file)
 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());