From bbed61d3d2489eb974d52e327b4fe63e361426ce Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 10 Apr 2018 23:01:24 +0900 Subject: [PATCH 1/4] Extend `ExternCrate` to cover externs inferred from `use` or paths --- src/librustc/ich/impls_cstore.rs | 27 +++++- src/librustc/middle/cstore.rs | 48 ++++++++--- src/librustc/ty/item_path.rs | 34 ++++---- src/librustc_metadata/creader.rs | 92 ++++++++++++++++++--- src/librustc_resolve/build_reduced_graph.rs | 8 +- src/librustc_resolve/lib.rs | 2 +- src/librustc_resolve/resolve_imports.rs | 7 +- src/librustc_save_analysis/lib.rs | 6 +- 8 files changed, 173 insertions(+), 51 deletions(-) diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs index 0071850e1052b..0e33c64333dab 100644 --- a/src/librustc/ich/impls_cstore.rs +++ b/src/librustc/ich/impls_cstore.rs @@ -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; @@ -47,12 +48,32 @@ impl_stable_hash_for!(enum middle::cstore::LinkagePreference { }); impl_stable_hash_for!(struct middle::cstore::ExternCrate { - def_id, + src, span, - direct, - path_len + direct }); +impl<'a> HashStable> for middle::cstore::ExternCrateSource { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { + 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, diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index add9b621596b6..6208a8a767c10 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -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 @@ impl CrateStore for DummyCrateStore { } 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 diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 1f23b0a27e33d..771bdcc55e397 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // `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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // 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; } _ => {}, diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 86f495c5fac3a..268624cf43093 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -25,7 +25,7 @@ use rustc_back::PanicStrategy; 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 @@ impl<'a> CrateLoader<'a> { 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 { + 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 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } } - 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 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { 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 } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 0542ca6fb24c2..f4e2136a5a115 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -252,10 +252,7 @@ impl<'a> Resolver<'a> { } 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 @@ impl<'a> Resolver<'a> { 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, _) => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2bf17cd1317d4..aeb31460416cd 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3258,7 +3258,7 @@ impl<'a> Resolver<'a> { 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); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 87738f7b79be5..37c62a7b0b45b 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -627,7 +627,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } 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); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 4f46fb3545b15..34a9b57c9dc3d 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -42,6 +42,7 @@ use rustc::hir; 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 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { 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()); From e986510bde5baeee952adaeac619dfcb2e62dfbc Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 10 Apr 2018 23:40:34 +0900 Subject: [PATCH 2/4] Add test --- .../save-analysis-rfc2126/Makefile | 8 ++++++++ .../extern_absolute_paths.rs | 18 ++++++++++++++++++ .../save-analysis-rfc2126/extern_in_paths.rs | 17 +++++++++++++++++ .../save-analysis-rfc2126/krate2.rs | 15 +++++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile create mode 100644 src/test/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs create mode 100644 src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs create mode 100644 src/test/run-make-fulldeps/save-analysis-rfc2126/krate2.rs diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile new file mode 100644 index 0000000000000..2f5ed6716d645 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile @@ -0,0 +1,8 @@ +-include ../tools.mk + +all: extern_absolute_paths.rs extern_in_paths.rs krate2 + $(RUSTC) extern_absolute_paths.rs -Zsave-analysis + $(RUSTC) extern_in_paths.rs -Zsave-analysis + +krate2: krate2.rs + $(RUSTC) $< diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs b/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs new file mode 100644 index 0000000000000..b1fe535766d21 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(extern_absolute_paths)] + +use krate2::hello; + +fn main() { + hello(); + ::krate2::hello(); +} diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs b/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs new file mode 100644 index 0000000000000..e48627e86bac5 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(extern_in_paths)] + +use extern::krate2; + +fn main() { + extern::krate2::hello(); +} diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/krate2.rs b/src/test/run-make-fulldeps/save-analysis-rfc2126/krate2.rs new file mode 100644 index 0000000000000..21fc57ccdf2de --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/krate2.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "krate2"] +#![crate_type = "lib"] + +pub fn hello() { +} From 2c7e83f746297578c3f31a7b1440e30fdfd67c67 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 13 Apr 2018 09:31:43 +0900 Subject: [PATCH 3/4] Move `path_len` to ExternCrate --- src/librustc/ich/impls_cstore.rs | 27 ++++++--------------------- src/librustc/middle/cstore.rs | 19 ++++++++----------- src/librustc/ty/item_path.rs | 4 ++-- src/librustc_metadata/creader.rs | 20 ++++++++------------ 4 files changed, 24 insertions(+), 46 deletions(-) diff --git a/src/librustc/ich/impls_cstore.rs b/src/librustc/ich/impls_cstore.rs index 0e33c64333dab..d885bd43bc89d 100644 --- a/src/librustc/ich/impls_cstore.rs +++ b/src/librustc/ich/impls_cstore.rs @@ -12,7 +12,6 @@ //! from rustc::middle::cstore in no particular order. use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; -use ich::StableHashingContext; use middle; @@ -50,29 +49,15 @@ impl_stable_hash_for!(enum middle::cstore::LinkagePreference { impl_stable_hash_for!(struct middle::cstore::ExternCrate { src, span, + path_len, direct }); -impl<'a> HashStable> for middle::cstore::ExternCrateSource { - fn hash_stable( - &self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher, - ) { - 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!(enum middle::cstore::ExternCrateSource { + Extern(def_id), + Use, + Path, +}); impl_stable_hash_for!(struct middle::cstore::CrateSource { dylib, diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 6208a8a767c10..81fe723deb905 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -153,6 +153,10 @@ pub struct ExternCrate { /// span of the extern crate that caused this to be loaded pub span: Span, + /// Number of links to reach the extern; + /// used to select the extern with the shortest path + pub path_len: usize, + /// If true, then this crate is the crate named by the extern /// crate referenced above. If false, then this crate is a dep /// of the crate. @@ -162,21 +166,14 @@ pub struct ExternCrate { #[derive(Copy, Clone, Debug)] pub enum ExternCrateSource { /// Crate is loaded by `extern crate`. - Extern { + 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, - }, + DefId, + ), // Crate is loaded by `use`. - Use { - path_len: usize, - }, + Use, /// Crate is implicitly loaded by an absolute or an `extern::` path. Path, } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 771bdcc55e397..8189064db6968 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -104,7 +104,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if cnum != LOCAL_CRATE { let opt_extern_crate = self.extern_crate(cnum.as_def_id()); if let Some(ExternCrate { - src: ExternCrateSource::Extern { def_id, .. }, + src: ExternCrateSource::Extern(def_id), direct: true, .. }) = *opt_extern_crate @@ -138,7 +138,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if cur_def.index == CRATE_DEF_INDEX { match *self.extern_crate(cur_def) { Some(ExternCrate { - src: ExternCrateSource::Extern { def_id, .. }, + src: ExternCrateSource::Extern(def_id), direct: true, .. }) => { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 268624cf43093..f6692579ffa33 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -367,14 +367,6 @@ impl<'a> CrateLoader<'a> { 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 { - 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); @@ -382,14 +374,14 @@ impl<'a> CrateLoader<'a> { let new_rank = ( true, extern_crate.direct, - path_len_reverse(extern_crate.src), + cmp::Reverse(extern_crate.path_len), ); let old_rank = match *old_extern_crate { None => (false, false, cmp::Reverse(usize::max_value())), Some(ref c) => ( true, c.direct, - path_len_reverse(c.src), + cmp::Reverse(c.path_len), ), }; if old_rank >= new_rank { @@ -1089,8 +1081,9 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { self.update_extern_crate( cnum, ExternCrate { - src: ExternCrateSource::Extern { def_id, path_len }, + src: ExternCrateSource::Extern(def_id), span: item.span, + path_len, direct: true, }, &mut FxHashSet(), @@ -1116,6 +1109,8 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { ExternCrate { src: ExternCrateSource::Path, span, + // to have the least priority in `update_extern_crate` + path_len: usize::max_value(), direct: true, }, &mut FxHashSet(), @@ -1141,8 +1136,9 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { self.update_extern_crate( cnum, ExternCrate { - src: ExternCrateSource::Use { path_len }, + src: ExternCrateSource::Use, span, + path_len, direct: true, }, &mut FxHashSet(), From c3dc014378e855bf41fd75e5b4ff956b67766656 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 15 Apr 2018 20:47:45 +0900 Subject: [PATCH 4/4] Check generated save-analysis, instead of `bug!()`ing Injected crates don't have extern info. Let's skip them. --- src/librustc_save_analysis/lib.rs | 3 ++- .../save-analysis-rfc2126/Makefile | 2 ++ .../save-analysis-rfc2126/validate_json.py | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/test/run-make-fulldeps/save-analysis-rfc2126/validate_json.py diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 34a9b57c9dc3d..f494e982f7f20 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -115,7 +115,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let span = match *self.tcx.extern_crate(n.as_def_id()) { Some(ExternCrate { span, .. }) => span, None => { - bug!("no data for crate {}", n); + debug!("Skipping crate {}, no data", n); + continue; } }; let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo()); diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile index 2f5ed6716d645..a132668ec7c8a 100644 --- a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile @@ -2,7 +2,9 @@ all: extern_absolute_paths.rs extern_in_paths.rs krate2 $(RUSTC) extern_absolute_paths.rs -Zsave-analysis + cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py $(RUSTC) extern_in_paths.rs -Zsave-analysis + cat $(TMPDIR)/save-analysis/extern_in_paths.json | "$(PYTHON)" validate_json.py krate2: krate2.rs $(RUSTC) $< diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/validate_json.py b/src/test/run-make-fulldeps/save-analysis-rfc2126/validate_json.py new file mode 100644 index 0000000000000..caab8d0d62697 --- /dev/null +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/validate_json.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +# Copyright 2018 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import sys +import json + +crates = json.loads(sys.stdin.readline().strip())["prelude"]["external_crates"] +assert any(map(lambda c: c["id"]["name"] == "krate2", crates))