]> git.lizzy.rs Git - rust.git/commitdiff
Extend `ExternCrate` to cover externs inferred from `use` or paths
authorShotaro Yamada <sinkuu@sinkuu.xyz>
Tue, 10 Apr 2018 14:01:24 +0000 (23:01 +0900)
committerShotaro Yamada <sinkuu@sinkuu.xyz>
Tue, 10 Apr 2018 16:17:59 +0000 (01:17 +0900)
src/librustc/ich/impls_cstore.rs
src/librustc/middle/cstore.rs
src/librustc/ty/item_path.rs
src/librustc_metadata/creader.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/lib.rs

index 0071850e1052b5a77292d68d50e34c1a64ca6e89..0e33c64333dab24155535ba75c98268cefd14d96 100644 (file)
@@ -12,6 +12,7 @@
 //! from rustc::middle::cstore in no particular order.
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+use ich::StableHashingContext;
 
 use middle;
 
 });
 
 impl_stable_hash_for!(struct middle::cstore::ExternCrate {
-    def_id,
+    src,
     span,
-    direct,
-    path_len
+    direct
 });
 
+impl<'a> HashStable<StableHashingContext<'a>> for middle::cstore::ExternCrateSource {
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>,
+    ) {
+        use middle::cstore::ExternCrateSource::*;
+
+        ::std::mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            Extern { def_id, path_len } => {
+                def_id.hash_stable(hcx, hasher);
+                path_len.hash_stable(hcx, hasher);
+            }
+            Use { path_len } => path_len.hash_stable(hcx, hasher),
+            Path => {}
+        }
+    }
+}
+
 impl_stable_hash_for!(struct middle::cstore::CrateSource {
     dylib,
     rlib,
index add9b621596b63219db2d406dab8020c0a4bb13a..6208a8a767c108b7d1cbb26f5481ad162c0780da 100644 (file)
@@ -148,10 +148,7 @@ pub enum LoadedMacro {
 
 #[derive(Copy, Clone, Debug)]
 pub struct ExternCrate {
-    /// def_id of an `extern crate` in the current crate that caused
-    /// this crate to be loaded; note that there could be multiple
-    /// such ids
-    pub def_id: DefId,
+    pub src: ExternCrateSource,
 
     /// span of the extern crate that caused this to be loaded
     pub span: Span,
@@ -160,11 +157,28 @@ pub struct ExternCrate {
     /// crate referenced above. If false, then this crate is a dep
     /// of the crate.
     pub direct: bool,
+}
 
-    /// Number of links to reach the extern crate `def_id`
-    /// declaration; used to select the extern crate with the shortest
-    /// path
-    pub path_len: usize,
+#[derive(Copy, Clone, Debug)]
+pub enum ExternCrateSource {
+    /// Crate is loaded by `extern crate`.
+    Extern {
+        /// def_id of the item in the current crate that caused
+        /// this crate to be loaded; note that there could be multiple
+        /// such ids
+        def_id: DefId,
+
+        /// Number of links to reach the extern crate `def_id`
+        /// declaration; used to select the extern crate with the shortest
+        /// path
+        path_len: usize,
+    },
+    // Crate is loaded by `use`.
+    Use {
+        path_len: usize,
+    },
+    /// Crate is implicitly loaded by an absolute or an `extern::` path.
+    Path,
 }
 
 pub struct EncodedMetadata {
@@ -357,9 +371,23 @@ fn metadata_loader(&self) -> &dyn MetadataLoader { bug!("metadata_loader") }
 }
 
 pub trait CrateLoader {
-    fn process_item(&mut self, item: &ast::Item, defs: &Definitions);
+    fn process_extern_crate(&mut self, item: &ast::Item, defs: &Definitions) -> CrateNum;
+
+    fn process_path_extern(
+        &mut self,
+        name: Symbol,
+        span: Span,
+    ) -> CrateNum;
+
+    fn process_use_extern(
+        &mut self,
+        name: Symbol,
+        span: Span,
+        id: ast::NodeId,
+        defs: &Definitions,
+    ) -> CrateNum;
+
     fn postprocess(&mut self, krate: &ast::Crate);
-    fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum;
 }
 
 // This method is used when generating the command line to pass through to
index 1f23b0a27e33de547d85402b0bf9301317978ce1..771bdcc55e39749e59c3ae1bc796fa2101e7946e 100644 (file)
@@ -11,6 +11,7 @@
 use hir::map::DefPathData;
 use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use ty::{self, Ty, TyCtxt};
+use middle::cstore::{ExternCrate, ExternCrateSource};
 use syntax::ast;
 use syntax::symbol::Symbol;
 use syntax::symbol::InternedString;
@@ -95,21 +96,20 @@ pub fn push_krate_path<T>(self, buffer: &mut T, cnum: CrateNum)
                 //    `extern crate` manually, we put the `extern
                 //    crate` as the parent. So you wind up with
                 //    something relative to the current crate.
-                // 2. for an indirect crate, where there is no extern
-                //    crate, we just prepend the crate name.
+                // 2. for an extern inferred from a path or an indirect crate,
+                //    where there is no explicit `extern crate`, we just prepend
+                //    the crate name.
                 //
                 // Returns `None` for the local crate.
                 if cnum != LOCAL_CRATE {
                     let opt_extern_crate = self.extern_crate(cnum.as_def_id());
-                    let opt_extern_crate = opt_extern_crate.and_then(|extern_crate| {
-                        if extern_crate.direct {
-                            Some(extern_crate.def_id)
-                        } else {
-                            None
-                        }
-                    });
-                    if let Some(extern_crate_def_id) = opt_extern_crate {
-                        self.push_item_path(buffer, extern_crate_def_id);
+                    if let Some(ExternCrate {
+                        src: ExternCrateSource::Extern { def_id, .. },
+                        direct: true,
+                        ..
+                    }) = *opt_extern_crate
+                    {
+                        self.push_item_path(buffer, def_id);
                     } else {
                         buffer.push(&self.crate_name(cnum).as_str());
                     }
@@ -137,14 +137,18 @@ pub fn try_push_visible_item_path<T>(self, buffer: &mut T, external_def_id: DefI
             // followed by the path to the item within the crate and return.
             if cur_def.index == CRATE_DEF_INDEX {
                 match *self.extern_crate(cur_def) {
-                    Some(ref extern_crate) if extern_crate.direct => {
-                        self.push_item_path(buffer, extern_crate.def_id);
-                        cur_path.iter().rev().map(|segment| buffer.push(&segment)).count();
+                    Some(ExternCrate {
+                        src: ExternCrateSource::Extern { def_id, .. },
+                        direct: true,
+                        ..
+                    }) => {
+                        self.push_item_path(buffer, def_id);
+                        cur_path.iter().rev().for_each(|segment| buffer.push(&segment));
                         return true;
                     }
                     None => {
                         buffer.push(&self.crate_name(cur_def.krate).as_str());
-                        cur_path.iter().rev().map(|segment| buffer.push(&segment)).count();
+                        cur_path.iter().rev().for_each(|segment| buffer.push(&segment));
                         return true;
                     }
                     _ => {},
index 86f495c5fac3a2782e245ed06bc2364d0184f2ad..268624cf430938508adc6b38c7def2a6a7de0e06 100644 (file)
@@ -25,7 +25,7 @@
 use rustc_back::target::TargetTriple;
 use rustc::session::search_paths::PathKind;
 use rustc::middle;
-use rustc::middle::cstore::{validate_crate_name, ExternCrate};
+use rustc::middle::cstore::{validate_crate_name, ExternCrate, ExternCrateSource};
 use rustc::util::common::record_time;
 use rustc::util::nodemap::FxHashSet;
 use rustc::hir::map::Definitions;
@@ -367,16 +367,31 @@ fn update_extern_crate(&mut self,
         let cmeta = self.cstore.get_crate_data(cnum);
         let mut old_extern_crate = cmeta.extern_crate.borrow_mut();
 
+        fn path_len_reverse(src: ExternCrateSource) -> cmp::Reverse<usize> {
+            cmp::Reverse(match src {
+                ExternCrateSource::Extern { path_len, .. } |
+                ExternCrateSource::Use { path_len } => path_len,
+                _ => usize::max_value(),
+            })
+        }
+
         // Prefer:
         // - something over nothing (tuple.0);
         // - direct extern crate to indirect (tuple.1);
         // - shorter paths to longer (tuple.2).
-        let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
+        let new_rank = (
+            true,
+            extern_crate.direct,
+            path_len_reverse(extern_crate.src),
+        );
         let old_rank = match *old_extern_crate {
-            None => (false, false, !0),
-            Some(ref c) => (true, c.direct, !c.path_len),
+            None => (false, false, cmp::Reverse(usize::max_value())),
+            Some(ref c) => (
+                true,
+                c.direct,
+                path_len_reverse(c.src),
+            ),
         };
-
         if old_rank >= new_rank {
             return; // no change needed
         }
@@ -1045,7 +1060,7 @@ fn postprocess(&mut self, krate: &ast::Crate) {
         }
     }
 
-    fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
+    fn process_extern_crate(&mut self, item: &ast::Item, definitions: &Definitions) -> CrateNum {
         match item.node {
             ast::ItemKind::ExternCrate(orig_name) => {
                 debug!("resolving extern crate stmt. ident: {} orig_name: {:?}",
@@ -1071,17 +1086,68 @@ fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
 
                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
                 let path_len = definitions.def_path(def_id.index).data.len();
-
-                let extern_crate = ExternCrate { def_id, span: item.span, direct: true, path_len };
-                self.update_extern_crate(cnum, extern_crate, &mut FxHashSet());
+                self.update_extern_crate(
+                    cnum,
+                    ExternCrate {
+                        src: ExternCrateSource::Extern { def_id, path_len },
+                        span: item.span,
+                        direct: true,
+                    },
+                    &mut FxHashSet(),
+                );
                 self.cstore.add_extern_mod_stmt_cnum(item.id, cnum);
+                cnum
             }
-            _ => {}
+            _ => bug!(),
         }
     }
 
-    fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum {
-        self.resolve_crate(&None, name, name, None, None, span, PathKind::Crate,
-                           DepKind::Explicit).0
+    fn process_path_extern(
+        &mut self,
+        name: Symbol,
+        span: Span,
+    ) -> CrateNum {
+        let cnum = self.resolve_crate(
+            &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
+        ).0;
+
+        self.update_extern_crate(
+            cnum,
+            ExternCrate {
+                src: ExternCrateSource::Path,
+                span,
+                direct: true,
+            },
+            &mut FxHashSet(),
+        );
+
+        cnum
+    }
+
+    fn process_use_extern(
+        &mut self,
+        name: Symbol,
+        span: Span,
+        id: ast::NodeId,
+        definitions: &Definitions,
+    ) -> CrateNum {
+        let cnum = self.resolve_crate(
+            &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
+        ).0;
+
+        let def_id = definitions.opt_local_def_id(id).unwrap();
+        let path_len = definitions.def_path(def_id.index).data.len();
+
+        self.update_extern_crate(
+            cnum,
+            ExternCrate {
+                src: ExternCrateSource::Use { path_len },
+                span,
+                direct: true,
+            },
+            &mut FxHashSet(),
+        );
+
+        cnum
     }
 }
index 0542ca6fb24c271c18fa282b459e5a0e6af78140..f4e2136a5a1153db3ab74c61294c719543c695dd 100644 (file)
@@ -252,10 +252,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
             }
 
             ItemKind::ExternCrate(orig_name) => {
-                self.crate_loader.process_item(item, &self.definitions);
-
-                // n.b. we don't need to look at the path option here, because cstore already did
-                let crate_id = self.cstore.extern_mod_stmt_cnum_untracked(item.id).unwrap();
+                let crate_id = self.crate_loader.process_extern_crate(item, &self.definitions);
                 let module =
                     self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                 self.populate_module_if_necessary(module);
@@ -302,7 +299,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 self.current_module = module;
             }
 
-            ItemKind::ForeignMod(..) => self.crate_loader.process_item(item, &self.definitions),
+            // Handled in `rustc_metadata::{native_libs,link_args}`
+            ItemKind::ForeignMod(..) => {}
 
             // These items live in the value namespace.
             ItemKind::Static(_, m, _) => {
index 2bf17cd1317d449d4fcc5d20200ebdda9d30a57b..aeb31460416cd86dded465df51c3e2db87feb047 100644 (file)
@@ -3258,7 +3258,7 @@ fn resolve_path(&mut self,
                        prev_name == keywords::CrateRoot.name() &&
                        self.session.features_untracked().extern_absolute_paths {
                         // `::extern_crate::a::b`
-                        let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span);
+                        let crate_id = self.crate_loader.process_path_extern(name, ident.span);
                         let crate_root =
                             self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                         self.populate_module_if_necessary(crate_root);
index 87738f7b79be530e6ecb482d10a4a26a5da90ca9..37c62a7b0b45b276ab49270c3987195583e32123 100644 (file)
@@ -627,7 +627,12 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                         }
                     } else if is_extern && !token::is_path_segment_keyword(source) {
                         let crate_id =
-                            self.crate_loader.resolve_crate_from_path(source.name, directive.span);
+                            self.resolver.crate_loader.process_use_extern(
+                                source.name,
+                                directive.span,
+                                directive.id,
+                                &self.resolver.definitions,
+                            );
                         let crate_root =
                             self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                         self.populate_module_if_necessary(crate_root);
index 4f46fb3545b15833f314e6d8ae1dda38067ac28a..34a9b57c9dc3de8a78f3e6515863925a475bf1f8 100644 (file)
@@ -42,6 +42,7 @@
 use rustc::hir::def::Def as HirDef;
 use rustc::hir::map::{Node, NodeItem};
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::middle::cstore::ExternCrate;
 use rustc::session::config::CrateType::CrateTypeExecutable;
 use rustc::ty::{self, TyCtxt};
 use rustc_typeck::hir_ty_to_ty;
@@ -112,10 +113,9 @@ pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
 
         for &n in self.tcx.crates().iter() {
             let span = match *self.tcx.extern_crate(n.as_def_id()) {
-                Some(ref c) => c.span,
+                Some(ExternCrate { span, .. }) => span,
                 None => {
-                    debug!("Skipping crate {}, no data", n);
-                    continue;
+                    bug!("no data for crate {}", n);
                 }
             };
             let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo());