From afc2149c05c7f56602fc63af64b4ffe6223e5114 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 12 Sep 2018 10:31:00 +0300 Subject: [PATCH 1/7] rustc: support extern crates loaded after query engine creation. --- src/librustc/ty/context.rs | 6 +++++- src/librustc/ty/query/plumbing.rs | 11 ++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d1f3725037972..6738267b5b8c8 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1247,7 +1247,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .collect(), hir, def_path_hash_to_def_id, - queries: query::Queries::new(providers, on_disk_query_result_cache), + queries: query::Queries::new( + providers, + extern_providers, + on_disk_query_result_cache, + ), rcache: Lock::new(FxHashMap()), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 3c26732fbac67..25e72f462e680 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -692,10 +692,12 @@ macro_rules! define_queries_inner { impl<$tcx> Queries<$tcx> { pub fn new( providers: IndexVec>, + fallback_extern_providers: Providers<$tcx>, on_disk_cache: OnDiskCache<'tcx>, ) -> Self { Queries { providers, + fallback_extern_providers: Box::new(fallback_extern_providers), on_disk_cache, $($name: Lock::new(QueryCache::new())),* } @@ -818,7 +820,13 @@ macro_rules! define_queries_inner { #[inline] fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value { __query_compute::$name(move || { - let provider = tcx.queries.providers[key.query_crate()].$name; + let provider = tcx.queries.providers.get(key.query_crate()) + // HACK(eddyb) it's possible crates may be loaded after + // the query engine is created, and because crate loading + // is not yet integrated with the query engine, such crates + // would be be missing appropriate entries in `providers`. + .unwrap_or(&tcx.queries.fallback_extern_providers) + .$name; provider(tcx.global_tcx(), key) }) } @@ -899,6 +907,7 @@ macro_rules! define_queries_struct { pub(crate) on_disk_cache: OnDiskCache<'tcx>, providers: IndexVec>, + fallback_extern_providers: Box>, $($(#[$attr])* $name: Lock>>,)* } From 26b1ed1b92a1c3ea9e511e81a456401777dbf425 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 24 Aug 2018 18:51:10 +0300 Subject: [PATCH 2/7] rustc: add unstable support for --extern crate_name without a path. --- src/librustc/session/config.rs | 43 ++++++++++++++++---------------- src/librustc_metadata/creader.rs | 3 ++- src/librustc_metadata/locator.rs | 7 +++++- src/librustdoc/lib.rs | 11 +++++--- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2a9732bf02c98..4c0eeba744150 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -275,18 +275,18 @@ impl OutputTypes { // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That // would break dependency tracking for commandline arguments. #[derive(Clone, Hash)] -pub struct Externs(BTreeMap>); +pub struct Externs(BTreeMap>>); impl Externs { - pub fn new(data: BTreeMap>) -> Externs { + pub fn new(data: BTreeMap>>) -> Externs { Externs(data) } - pub fn get(&self, key: &str) -> Option<&BTreeSet> { + pub fn get(&self, key: &str) -> Option<&BTreeSet>> { self.0.get(key) } - pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet> { + pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet>> { self.0.iter() } } @@ -2169,6 +2169,8 @@ pub fn build_session_options_and_crate_config( let cfg = parse_cfgspecs(matches.opt_strs("cfg")); let test = matches.opt_present("test"); + let is_unstable_enabled = nightly_options::is_unstable_enabled(matches); + prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { "crate-name" => PrintRequest::CrateName, "file-names" => PrintRequest::FileNames, @@ -2182,15 +2184,13 @@ pub fn build_session_options_and_crate_config( "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, "target-spec-json" => { - if nightly_options::is_unstable_enabled(matches) { + if is_unstable_enabled { PrintRequest::TargetSpec } else { early_error( error_format, - &format!( - "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option" - ), + "the `-Z unstable-options` flag must also be passed to \ + enable the target-spec-json print option", ); } } @@ -2220,18 +2220,19 @@ pub fn build_session_options_and_crate_config( Some(s) => s, None => early_error(error_format, "--extern value must not be empty"), }; - let location = match parts.next() { - Some(s) => s, - None => early_error( + let location = parts.next().map(|s| s.to_string()); + if location.is_none() && !is_unstable_enabled { + early_error( error_format, - "--extern value must be of the format `foo=bar`", - ), + "the `-Z unstable-options` flag must also be passed to \ + enable `--extern crate_name` without `=path`", + ); }; externs .entry(name.to_string()) .or_default() - .insert(location.to_string()); + .insert(location); } let crate_name = matches.opt_str("crate-name"); @@ -2687,33 +2688,33 @@ mod tests { v1.externs = Externs::new(mk_map(vec![ ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ( String::from("d"), - mk_set(vec![String::from("e"), String::from("f")]), + mk_set(vec![Some(String::from("e")), Some(String::from("f"))]), ), ])); v2.externs = Externs::new(mk_map(vec![ ( String::from("d"), - mk_set(vec![String::from("e"), String::from("f")]), + mk_set(vec![Some(String::from("e")), Some(String::from("f"))]), ), ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ])); v3.externs = Externs::new(mk_map(vec![ ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ( String::from("d"), - mk_set(vec![String::from("f"), String::from("e")]), + mk_set(vec![Some(String::from("f")), Some(String::from("e"))]), ), ])); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5eb541952150f..e28bb26082040 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -132,7 +132,8 @@ impl<'a> CrateLoader<'a> { // from the strings on the command line. let source = &self.cstore.get_crate_data(cnum).source; if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) { - let found = locs.iter().any(|l| { + // Only use `--extern crate_name=path` here, not `--extern crate_name`. + let found = locs.iter().filter_map(|l| l.as_ref()).any(|l| { let l = fs::canonicalize(l).ok(); source.dylib.as_ref().map(|p| &p.0) == l.as_ref() || source.rlib.as_ref().map(|p| &p.0) == l.as_ref() diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 9492385957eab..02207c63b3464 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -438,7 +438,12 @@ impl<'a> Context<'a> { if self.hash.is_none() { self.should_match_name = false; if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) { - return self.find_commandline_library(s.iter()); + // Only use `--extern crate_name=path` here, not `--extern crate_name`. + if s.iter().any(|l| l.is_some()) { + return self.find_commandline_library( + s.iter().filter_map(|l| l.as_ref()), + ); + } } self.should_match_name = true; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index bc471d427048b..73057b19016c6 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -609,16 +609,19 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { /// Extracts `--extern CRATE=PATH` arguments from `matches` and /// returns a map mapping crate names to their paths or else an /// error message. +// FIXME(eddyb) This shouldn't be duplicated with `rustc::session`. fn parse_externs(matches: &getopts::Matches) -> Result { let mut externs: BTreeMap<_, BTreeSet<_>> = BTreeMap::new(); for arg in &matches.opt_strs("extern") { let mut parts = arg.splitn(2, '='); let name = parts.next().ok_or("--extern value must not be empty".to_string())?; - let location = parts.next() - .ok_or("--extern value must be of the format `foo=bar`" - .to_string())?; + let location = parts.next().map(|s| s.to_string()); + if location.is_none() && !nightly_options::is_unstable_enabled(matches) { + return Err("the `-Z unstable-options` flag must also be passed to \ + enable `--extern crate_name` without `=path`".to_string()); + } let name = name.to_string(); - externs.entry(name).or_default().insert(location.to_string()); + externs.entry(name).or_default().insert(location); } Ok(Externs::new(externs)) } From 9eb7a3c76fe826b646a0a5a747292a5643f9e197 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 24 Aug 2018 18:51:32 +0300 Subject: [PATCH 3/7] rustc_resolve: don't allow `::crate_name` to bypass `extern_prelude`. --- src/librustc_resolve/resolve_imports.rs | 12 ++++++++-- .../save-analysis-rfc2126/Makefile | 6 +++-- src/test/ui/issues/issue-52489.rs | 1 + src/test/ui/issues/issue-52489.stderr | 2 +- .../non-existent-1.rs | 2 +- .../non-existent-1.stderr | 8 +++---- .../non-existent-2.rs | 3 ++- .../non-existent-2.stderr | 8 +++---- .../non-existent-3.rs | 2 +- .../non-existent-3.stderr | 8 +++---- .../single-segment.rs | 1 + .../single-segment.stderr | 6 ++--- .../non-existent-1.rs | 2 +- .../non-existent-1.stderr | 8 +++---- .../non-existent-2.rs | 3 ++- .../non-existent-2.stderr | 8 +++---- .../non-existent-3.rs | 2 +- .../non-existent-3.stderr | 10 ++++---- .../single-segment.rs | 1 + .../single-segment.stderr | 6 ++--- .../ui/run-pass/issues/issue-52140/main.rs | 1 + .../ui/run-pass/issues/issue-52141/main.rs | 1 + .../ui/run-pass/issues/issue-52705/main.rs | 1 + .../rfc-2126-extern-absolute-paths/basic.rs | 1 + .../rfc-2126-extern-absolute-paths/extern.rs | 1 + .../extern-crate-idiomatic-in-2018.fixed | 1 + .../extern-crate-idiomatic-in-2018.rs | 1 + .../extern-crate-idiomatic-in-2018.stderr | 6 ++--- .../ui/rust-2018/extern-crate-idiomatic.fixed | 1 + .../ui/rust-2018/extern-crate-idiomatic.rs | 1 + src/test/ui/rust-2018/issue-54006.rs | 23 +++++++++++++++++++ src/test/ui/rust-2018/issue-54006.stderr | 17 ++++++++++++++ .../ui/rust-2018/remove-extern-crate.fixed | 1 + src/test/ui/rust-2018/remove-extern-crate.rs | 1 + .../ui/rust-2018/remove-extern-crate.stderr | 8 +++---- 35 files changed, 115 insertions(+), 49 deletions(-) create mode 100644 src/test/ui/rust-2018/issue-54006.rs create mode 100644 src/test/ui/rust-2018/issue-54006.stderr diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e7d3a8ef66167..c86d430faceab 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -196,7 +196,11 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { } // Fall back to resolving to an external crate. - if !(ns == TypeNS && self.extern_prelude.contains(&ident.name)) { + if !( + ns == TypeNS && + !ident.is_path_segment_keyword() && + self.extern_prelude.contains(&ident.name) + ) { // ... unless the crate name is not in the `extern_prelude`. return binding; } @@ -211,7 +215,11 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { ) { self.resolve_crate_root(ident) - } else if ns == TypeNS && !ident.is_path_segment_keyword() { + } else if + ns == TypeNS && + !ident.is_path_segment_keyword() && + self.extern_prelude.contains(&ident.name) + { let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile index 6a67b5862a815..2b931d89f1fec 100644 --- a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile @@ -1,9 +1,11 @@ -include ../tools.mk all: extern_absolute_paths.rs extern_in_paths.rs krate2 - $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 + $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 \ + -Z unstable-options --extern krate2 cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py - $(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018 + $(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018 \ + -Z unstable-options --extern krate2 cat $(TMPDIR)/save-analysis/extern_in_paths.json | "$(PYTHON)" validate_json.py krate2: krate2.rs diff --git a/src/test/ui/issues/issue-52489.rs b/src/test/ui/issues/issue-52489.rs index c43cc12ca0229..f26392e82acbd 100644 --- a/src/test/ui/issues/issue-52489.rs +++ b/src/test/ui/issues/issue-52489.rs @@ -10,6 +10,7 @@ // edition:2018 // aux-build:issue-52489.rs +// compile-flags:--extern issue_52489 use issue_52489; //~^ ERROR use of unstable library feature 'issue_52489_unstable' diff --git a/src/test/ui/issues/issue-52489.stderr b/src/test/ui/issues/issue-52489.stderr index 5b38a0789ad7f..b8c41d82643e8 100644 --- a/src/test/ui/issues/issue-52489.stderr +++ b/src/test/ui/issues/issue-52489.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature 'issue_52489_unstable' - --> $DIR/issue-52489.rs:14:5 + --> $DIR/issue-52489.rs:15:5 | LL | use issue_52489; | ^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs index 826bf675bd699..a259266420a1d 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs @@ -10,6 +10,6 @@ // edition:2018 -use xcrate::S; //~ ERROR can't find crate for `xcrate` +use xcrate::S; //~ ERROR unresolved import `xcrate` fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr index 27a69ec1b1faf..1a8ceec5dac06 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `xcrate` +error[E0432]: unresolved import `xcrate` --> $DIR/non-existent-1.rs:13:5 | -LL | use xcrate::S; //~ ERROR can't find crate for `xcrate` - | ^^^^^^ can't find crate +LL | use xcrate::S; //~ ERROR unresolved import `xcrate` + | ^^^^^^ Could not find `xcrate` in `{{root}}` error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs index 053bf92f4d196..41adb974f2176 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs @@ -11,5 +11,6 @@ // edition:2018 fn main() { - let s = ::xcrate::S; //~ ERROR can't find crate for `xcrate` + let s = ::xcrate::S; + //~^ ERROR failed to resolve. Could not find `xcrate` in `{{root}}` } diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr index eb96d5f05d7a6..b46576b014367 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `xcrate` +error[E0433]: failed to resolve. Could not find `xcrate` in `{{root}}` --> $DIR/non-existent-2.rs:14:15 | -LL | let s = ::xcrate::S; //~ ERROR can't find crate for `xcrate` - | ^^^^^^ can't find crate +LL | let s = ::xcrate::S; + | ^^^^^^ Could not find `xcrate` in `{{root}}` error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs index 1b9e5a75e8307..0cbeb8cf50fe3 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs @@ -10,6 +10,6 @@ // edition:2018 -use ycrate; //~ ERROR can't find crate for `ycrate` +use ycrate; //~ ERROR unresolved import `ycrate` fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr index 434bde79a8322..31486e14bd2a8 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `ycrate` +error[E0432]: unresolved import `ycrate` --> $DIR/non-existent-3.rs:13:5 | -LL | use ycrate; //~ ERROR can't find crate for `ycrate` - | ^^^^^^ can't find crate +LL | use ycrate; //~ ERROR unresolved import `ycrate` + | ^^^^^^ no `ycrate` external crate error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs index 69fc4b4f7f8fc..b5b1485f662c5 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.rs @@ -9,6 +9,7 @@ // except according to those terms. // aux-build:xcrate.rs +// compile-flags:--extern xcrate // edition:2018 use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;` diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr index cfb1a0ac39ac2..b49291b9c0c61 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/single-segment.stderr @@ -1,17 +1,17 @@ error: crate root imports need to be explicitly named: `use crate as name;` - --> $DIR/single-segment.rs:14:5 + --> $DIR/single-segment.rs:15:5 | LL | use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;` | ^^^^^ error: cannot glob-import all possible crates - --> $DIR/single-segment.rs:15:5 + --> $DIR/single-segment.rs:16:5 | LL | use *; //~ ERROR cannot glob-import all possible crates | ^ error[E0423]: expected value, found module `xcrate` - --> $DIR/single-segment.rs:18:13 + --> $DIR/single-segment.rs:19:13 | LL | let s = ::xcrate; //~ ERROR expected value, found module `xcrate` | ^^^^^^^^ not a value diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs index 7eba02ed444bb..c17e74c547c18 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs @@ -10,6 +10,6 @@ #![feature(extern_in_paths)] -use extern::xcrate::S; //~ ERROR can't find crate for `xcrate` +use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate` fn main() {} diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr index c25698c395e1c..55b8b6255073e 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `xcrate` +error[E0432]: unresolved import `extern::xcrate` --> $DIR/non-existent-1.rs:13:13 | -LL | use extern::xcrate::S; //~ ERROR can't find crate for `xcrate` - | ^^^^^^ can't find crate +LL | use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate` + | ^^^^^^ Could not find `xcrate` in `extern` error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs index 4d09a05253ec2..128ecf41a303d 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs @@ -11,5 +11,6 @@ #![feature(extern_in_paths)] fn main() { - let s = extern::xcrate::S; //~ ERROR can't find crate for `xcrate` + let s = extern::xcrate::S; + //~^ ERROR failed to resolve. Could not find `xcrate` in `extern` } diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr index b7ca8890c1942..7fbe50a92022b 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `xcrate` +error[E0433]: failed to resolve. Could not find `xcrate` in `extern` --> $DIR/non-existent-2.rs:14:21 | -LL | let s = extern::xcrate::S; //~ ERROR can't find crate for `xcrate` - | ^^^^^^ can't find crate +LL | let s = extern::xcrate::S; + | ^^^^^^ Could not find `xcrate` in `extern` error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs index 402d294b2e324..350cca70487f3 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs @@ -10,6 +10,6 @@ #![feature(extern_in_paths)] -use extern::ycrate; //~ ERROR can't find crate for `ycrate` +use extern::ycrate; //~ ERROR unresolved import `extern::ycrate` fn main() {} diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr index fbea89ae93a97..0a49d1721695b 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr +++ b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr @@ -1,9 +1,9 @@ -error[E0463]: can't find crate for `ycrate` - --> $DIR/non-existent-3.rs:13:13 +error[E0432]: unresolved import `extern::ycrate` + --> $DIR/non-existent-3.rs:13:5 | -LL | use extern::ycrate; //~ ERROR can't find crate for `ycrate` - | ^^^^^^ can't find crate +LL | use extern::ycrate; //~ ERROR unresolved import `extern::ycrate` + | ^^^^^^^^^^^^^^ no `ycrate` external crate error: aborting due to previous error -For more information about this error, try `rustc --explain E0463`. +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs b/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs index 017844a0252e2..ea4488637031e 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs +++ b/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs @@ -9,6 +9,7 @@ // except according to those terms. // aux-build:xcrate.rs +// compile-flags:--extern xcrate #![feature(extern_in_paths)] diff --git a/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr b/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr index 8b1dd89fe3ca7..033bedb3b938b 100644 --- a/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr +++ b/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr @@ -1,17 +1,17 @@ error: cannot glob-import all possible crates - --> $DIR/single-segment.rs:17:5 + --> $DIR/single-segment.rs:18:5 | LL | use extern::*; //~ ERROR cannot glob-import all possible crates | ^^^^^^^^^ error[E0432]: unresolved import `extern` - --> $DIR/single-segment.rs:15:5 + --> $DIR/single-segment.rs:16:5 | LL | use extern; //~ ERROR unresolved import `extern` | ^^^^^^ no `extern` in the root error[E0423]: expected value, found module `extern::xcrate` - --> $DIR/single-segment.rs:20:13 + --> $DIR/single-segment.rs:21:13 | LL | let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate` | ^^^^^^^^^^^^^^ not a value diff --git a/src/test/ui/run-pass/issues/issue-52140/main.rs b/src/test/ui/run-pass/issues/issue-52140/main.rs index c17a4796555c7..3d727e2ad1b56 100644 --- a/src/test/ui/run-pass/issues/issue-52140/main.rs +++ b/src/test/ui/run-pass/issues/issue-52140/main.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:some_crate.rs +// compile-flags:--extern some_crate // edition:2018 mod foo { diff --git a/src/test/ui/run-pass/issues/issue-52141/main.rs b/src/test/ui/run-pass/issues/issue-52141/main.rs index d1003bb2908af..20705dc38e1ae 100644 --- a/src/test/ui/run-pass/issues/issue-52141/main.rs +++ b/src/test/ui/run-pass/issues/issue-52141/main.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:some_crate.rs +// compile-flags:--extern some_crate // edition:2018 use some_crate as some_name; diff --git a/src/test/ui/run-pass/issues/issue-52705/main.rs b/src/test/ui/run-pass/issues/issue-52705/main.rs index 3d828ba60d3cd..00cb5ac103a91 100644 --- a/src/test/ui/run-pass/issues/issue-52705/main.rs +++ b/src/test/ui/run-pass/issues/issue-52705/main.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:png2.rs +// compile-flags:--extern png2 // edition:2018 mod png { diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs index c5a356d979d31..b13602297a4af 100644 --- a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs +++ b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:xcrate.rs +// compile-flags:--extern xcrate // edition:2018 use xcrate::Z; diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs index 3d31c2d3a4dd1..0d84ccc3d3221 100644 --- a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs +++ b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:xcrate.rs +// compile-flags:--extern xcrate #![feature(extern_in_paths)] diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed index fc81ab08f624d..36a837509c50c 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed @@ -10,6 +10,7 @@ // aux-build:edition-lint-paths.rs // run-rustfix +// compile-flags:--extern edition_lint_paths // edition:2018 // The "normal case". Ideally we would remove the `extern crate` here, diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs index 72751f2080cc9..9daa4145630b7 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs @@ -10,6 +10,7 @@ // aux-build:edition-lint-paths.rs // run-rustfix +// compile-flags:--extern edition_lint_paths // edition:2018 // The "normal case". Ideally we would remove the `extern crate` here, diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr index 0ecfd4e4a2ca3..b3afa2bd1d592 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr @@ -1,18 +1,18 @@ error: unused extern crate - --> $DIR/extern-crate-idiomatic-in-2018.rs:21:1 + --> $DIR/extern-crate-idiomatic-in-2018.rs:22:1 | LL | extern crate edition_lint_paths; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here - --> $DIR/extern-crate-idiomatic-in-2018.rs:18:9 + --> $DIR/extern-crate-idiomatic-in-2018.rs:19:9 | LL | #![deny(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ = note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)] error: `extern crate` is not idiomatic in the new edition - --> $DIR/extern-crate-idiomatic-in-2018.rs:24:1 + --> $DIR/extern-crate-idiomatic-in-2018.rs:25:1 | LL | extern crate edition_lint_paths as bar; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use` diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic.fixed index a874a62220298..0be1f2cc72bb0 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic.fixed +++ b/src/test/ui/rust-2018/extern-crate-idiomatic.fixed @@ -10,6 +10,7 @@ // run-pass // aux-build:edition-lint-paths.rs +// compile-flags:--extern edition_lint_paths // run-rustfix // The "normal case". Ideally we would remove the `extern crate` here, diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic.rs b/src/test/ui/rust-2018/extern-crate-idiomatic.rs index a874a62220298..0be1f2cc72bb0 100644 --- a/src/test/ui/rust-2018/extern-crate-idiomatic.rs +++ b/src/test/ui/rust-2018/extern-crate-idiomatic.rs @@ -10,6 +10,7 @@ // run-pass // aux-build:edition-lint-paths.rs +// compile-flags:--extern edition_lint_paths // run-rustfix // The "normal case". Ideally we would remove the `extern crate` here, diff --git a/src/test/ui/rust-2018/issue-54006.rs b/src/test/ui/rust-2018/issue-54006.rs new file mode 100644 index 0000000000000..ee58d240fcb83 --- /dev/null +++ b/src/test/ui/rust-2018/issue-54006.rs @@ -0,0 +1,23 @@ +// 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. + +// edition:2018 + +#![no_std] +#![crate_type = "lib"] + +use alloc::vec; +//~^ ERROR unresolved import `alloc` + +pub fn foo() { + let mut xs = vec![]; + //~^ ERROR cannot determine resolution for the macro `vec` + xs.push(0); +} diff --git a/src/test/ui/rust-2018/issue-54006.stderr b/src/test/ui/rust-2018/issue-54006.stderr new file mode 100644 index 0000000000000..1183dc9794a22 --- /dev/null +++ b/src/test/ui/rust-2018/issue-54006.stderr @@ -0,0 +1,17 @@ +error[E0432]: unresolved import `alloc` + --> $DIR/issue-54006.rs:16:5 + | +LL | use alloc::vec; + | ^^^^^ Could not find `alloc` in `{{root}}` + +error: cannot determine resolution for the macro `vec` + --> $DIR/issue-54006.rs:20:18 + | +LL | let mut xs = vec![]; + | ^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed index 995be4290b887..895da74afd767 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.fixed +++ b/src/test/ui/rust-2018/remove-extern-crate.fixed @@ -12,6 +12,7 @@ // edition:2018 // compile-pass // aux-build:remove-extern-crate.rs +// compile-flags:--extern remove_extern_crate --extern core #![warn(rust_2018_idioms)] diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs index 3ab97a7428704..c03431a6b8852 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.rs +++ b/src/test/ui/rust-2018/remove-extern-crate.rs @@ -12,6 +12,7 @@ // edition:2018 // compile-pass // aux-build:remove-extern-crate.rs +// compile-flags:--extern remove_extern_crate --extern core #![warn(rust_2018_idioms)] diff --git a/src/test/ui/rust-2018/remove-extern-crate.stderr b/src/test/ui/rust-2018/remove-extern-crate.stderr index 752a7b180de13..064a853625f74 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.stderr +++ b/src/test/ui/rust-2018/remove-extern-crate.stderr @@ -1,24 +1,24 @@ warning: unused extern crate - --> $DIR/remove-extern-crate.rs:18:1 + --> $DIR/remove-extern-crate.rs:19:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here - --> $DIR/remove-extern-crate.rs:16:9 + --> $DIR/remove-extern-crate.rs:17:9 | LL | #![warn(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)] warning: `extern crate` is not idiomatic in the new edition - --> $DIR/remove-extern-crate.rs:19:1 + --> $DIR/remove-extern-crate.rs:20:1 | LL | extern crate core as another_name; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use` warning: `extern crate` is not idiomatic in the new edition - --> $DIR/remove-extern-crate.rs:32:5 + --> $DIR/remove-extern-crate.rs:33:5 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ help: convert it to a `use` From 38c82a2180eee975e88017d26fa86726b3594d7a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 10 Sep 2018 19:41:30 +0300 Subject: [PATCH 4/7] rustc_resolve: always include core, std and meta in the extern prelude. --- src/librustc_metadata/creader.rs | 81 ++++++++++++++----- src/librustc_resolve/lib.rs | 51 ++++++------ .../ui/rfc-2126-extern-absolute-paths/meta.rs | 17 ++++ .../meta.stderr | 9 +++ .../not-whitelisted.rs | 19 +++++ .../not-whitelisted.stderr | 21 +++++ .../whitelisted.rs | 24 ++++++ .../ui/rust-2018/remove-extern-crate.fixed | 2 +- src/test/ui/rust-2018/remove-extern-crate.rs | 2 +- 9 files changed, 181 insertions(+), 45 deletions(-) create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/meta.rs create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs create mode 100644 src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr create mode 100644 src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index e28bb26082040..6eef2397f9c6e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -100,6 +100,18 @@ enum LoadResult { Loaded(Library), } +enum LoadError<'a> { + LocatorError(locator::Context<'a>), +} + +impl<'a> LoadError<'a> { + fn report(self) -> ! { + match self { + LoadError::LocatorError(mut locate_ctxt) => locate_ctxt.report_errs(), + } + } +} + impl<'a> CrateLoader<'a> { pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self { CrateLoader { @@ -268,16 +280,17 @@ impl<'a> CrateLoader<'a> { (cnum, cmeta) } - fn resolve_crate(&mut self, - root: &Option, - ident: Symbol, - name: Symbol, - hash: Option<&Svh>, - extra_filename: Option<&str>, - span: Span, - path_kind: PathKind, - mut dep_kind: DepKind) - -> (CrateNum, Lrc) { + fn resolve_crate<'b>( + &'b mut self, + root: &'b Option, + ident: Symbol, + name: Symbol, + hash: Option<&'b Svh>, + extra_filename: Option<&'b str>, + span: Span, + path_kind: PathKind, + mut dep_kind: DepKind, + ) -> Result<(CrateNum, Lrc), LoadError<'b>> { info!("resolving crate `extern crate {} as {}`", name, ident); let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { LoadResult::Previous(cnum) @@ -321,7 +334,7 @@ impl<'a> CrateLoader<'a> { }; self.load(&mut proc_macro_locator) - }).unwrap_or_else(|| locate_ctxt.report_errs()) + }).ok_or_else(move || LoadError::LocatorError(locate_ctxt))? }; match result { @@ -333,10 +346,10 @@ impl<'a> CrateLoader<'a> { data.dep_kind.with_lock(|data_dep_kind| { *data_dep_kind = cmp::max(*data_dep_kind, dep_kind); }); - (cnum, data) + Ok((cnum, data)) } LoadResult::Loaded(library) => { - self.register_crate(root, ident, span, library, dep_kind) + Ok(self.register_crate(root, ident, span, library, dep_kind)) } } } @@ -441,7 +454,7 @@ impl<'a> CrateLoader<'a> { let (local_cnum, ..) = self.resolve_crate( root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span, PathKind::Dependency, dep_kind, - ); + ).unwrap_or_else(|err| err.report()); local_cnum })).collect() } @@ -695,7 +708,8 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Implicit; let (cnum, data) = - self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind); + self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. @@ -803,7 +817,8 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Explicit; let (_, data) = self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, - PathKind::Crate, dep_kind); + PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime if !data.root.sanitizer_runtime { @@ -826,7 +841,8 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Implicit; let (_, data) = self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, - PathKind::Crate, dep_kind); + PathKind::Crate, dep_kind) + .unwrap_or_else(|err| err.report()); // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.root.profiler_runtime { @@ -946,7 +962,8 @@ impl<'a> CrateLoader<'a> { None, DUMMY_SP, PathKind::Crate, - DepKind::Implicit); + DepKind::Implicit) + .unwrap_or_else(|err| err.report()); self.sess.injected_allocator.set(Some(cnum)); data }) @@ -1103,7 +1120,7 @@ impl<'a> CrateLoader<'a> { let (cnum, ..) = self.resolve_crate( &None, item.ident.name, orig_name, None, None, item.span, PathKind::Crate, dep_kind, - ); + ).unwrap_or_else(|err| err.report()); let def_id = definitions.opt_local_def_id(item.id).unwrap(); let path_len = definitions.def_path(def_id.index).data.len(); @@ -1131,7 +1148,7 @@ impl<'a> CrateLoader<'a> { ) -> CrateNum { let cnum = self.resolve_crate( &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit - ).0; + ).unwrap_or_else(|err| err.report()).0; self.update_extern_crate( cnum, @@ -1147,4 +1164,28 @@ impl<'a> CrateLoader<'a> { cnum } + + pub fn maybe_process_path_extern( + &mut self, + name: Symbol, + span: Span, + ) -> Option { + let cnum = self.resolve_crate( + &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit + ).ok()?.0; + + self.update_extern_crate( + cnum, + ExternCrate { + src: ExternCrateSource::Path, + span, + // to have the least priority in `update_extern_crate` + path_len: usize::max_value(), + direct: true, + }, + &mut FxHashSet(), + ); + + Some(cnum) + } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f0ff8c419fd46..10dddfed6a577 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1674,13 +1674,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let mut extern_prelude: FxHashSet = session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(); - if !attr::contains_name(&krate.attrs, "no_core") { - if !attr::contains_name(&krate.attrs, "no_std") { - extern_prelude.insert(Symbol::intern("std")); - } else { - extern_prelude.insert(Symbol::intern("core")); - } - } + + // HACK(eddyb) this ignore the `no_{core,std}` attributes. + // FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`. + // if !attr::contains_name(&krate.attrs, "no_core") { + // if !attr::contains_name(&krate.attrs, "no_std") { + extern_prelude.insert(Symbol::intern("core")); + extern_prelude.insert(Symbol::intern("std")); + extern_prelude.insert(Symbol::intern("meta")); let mut invocations = FxHashMap(); invocations.insert(Mark::root(), @@ -1982,7 +1983,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { "access to extern crates through prelude is experimental").emit(); } - let crate_root = self.load_extern_prelude_crate_if_needed(ident); + let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); + let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); + self.populate_module_if_necessary(&crate_root); let binding = (crate_root, ty::Visibility::Public, ident.span, Mark::root()).to_name_binding(self.arenas); @@ -2010,13 +2013,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { None } - fn load_extern_prelude_crate_if_needed(&mut self, ident: Ident) -> Module<'a> { - let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); - let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); - self.populate_module_if_necessary(&crate_root); - crate_root - } - fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span) -> Option> { if !module.expansion.is_descendant_of(span.ctxt().outer()) { @@ -4427,15 +4423,24 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { if self.session.features_untracked().extern_prelude { let extern_prelude_names = self.extern_prelude.clone(); - for &krate_name in extern_prelude_names.iter() { - let krate_ident = Ident::with_empty_ctxt(krate_name); - let external_prelude_module = self.load_extern_prelude_crate_if_needed(krate_ident); + for &name in extern_prelude_names.iter() { + let ident = Ident::with_empty_ctxt(name); + match self.crate_loader.maybe_process_path_extern(name, ident.span) { + Some(crate_id) => { + let crate_root = self.get_module(DefId { + krate: crate_id, + index: CRATE_DEF_INDEX, + }); + self.populate_module_if_necessary(&crate_root); - suggestions.extend( - self.lookup_import_candidates_from_module( - lookup_name, namespace, external_prelude_module, krate_ident, &filter_fn - ) - ); + suggestions.extend( + self.lookup_import_candidates_from_module( + lookup_name, namespace, crate_root, ident, &filter_fn + ) + ); + } + None => {} + } } } diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs b/src/test/ui/rfc-2126-extern-absolute-paths/meta.rs new file mode 100644 index 0000000000000..499a322593c60 --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/meta.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. + +// edition:2018 + +// Tests that `meta` is whitelisted, even if the crate doesn't exist +// yet (i.e. it causes a different error than `not-whitelisted.rs`). +use meta; //~ ERROR can't find crate for `meta` + +fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr new file mode 100644 index 0000000000000..b8a9b54d26bca --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/meta.stderr @@ -0,0 +1,9 @@ +error[E0463]: can't find crate for `meta` + --> $DIR/meta.rs:15:5 + | +LL | use meta; //~ ERROR can't find crate for `meta` + | ^^^^ can't find crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs new file mode 100644 index 0000000000000..f95961d2a9b56 --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs @@ -0,0 +1,19 @@ +// 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. + +// edition:2018 + +// Tests that arbitrary crates (other than `core`, `std` and `meta`) +// aren't allowed without `--extern`, even if they're in the sysroot. +use alloc; //~ ERROR unresolved import `alloc` +use test; //~ ERROR unresolved import `test` +use proc_macro; //~ ERROR unresolved import `proc_macro` + +fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr new file mode 100644 index 0000000000000..0865bd6bea52a --- /dev/null +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `alloc` + --> $DIR/not-whitelisted.rs:15:5 + | +LL | use alloc; //~ ERROR unresolved import `alloc` + | ^^^^^ no `alloc` external crate + +error[E0432]: unresolved import `test` + --> $DIR/not-whitelisted.rs:16:5 + | +LL | use test; //~ ERROR unresolved import `test` + | ^^^^ no `test` external crate + +error[E0432]: unresolved import `proc_macro` + --> $DIR/not-whitelisted.rs:17:5 + | +LL | use proc_macro; //~ ERROR unresolved import `proc_macro` + | ^^^^^^^^^^ no `proc_macro` external crate + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs new file mode 100644 index 0000000000000..dfd9fbd27746b --- /dev/null +++ b/src/test/ui/run-pass/rfcs/rfc-2126-extern-absolute-paths/whitelisted.rs @@ -0,0 +1,24 @@ +// 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. + +// run-pass +// edition:2018 + +// Tests that `core` and `std` are always available. +use core::iter; +use std::io; +// FIXME(eddyb) Add a `meta` crate to the distribution. +// use meta; + +fn main() { + for _ in iter::once(()) { + io::stdout(); + } +} diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed index 895da74afd767..cdae815b200d5 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.fixed +++ b/src/test/ui/rust-2018/remove-extern-crate.fixed @@ -12,7 +12,7 @@ // edition:2018 // compile-pass // aux-build:remove-extern-crate.rs -// compile-flags:--extern remove_extern_crate --extern core +// compile-flags:--extern remove_extern_crate #![warn(rust_2018_idioms)] diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs index c03431a6b8852..4984da802c05b 100644 --- a/src/test/ui/rust-2018/remove-extern-crate.rs +++ b/src/test/ui/rust-2018/remove-extern-crate.rs @@ -12,7 +12,7 @@ // edition:2018 // compile-pass // aux-build:remove-extern-crate.rs -// compile-flags:--extern remove_extern_crate --extern core +// compile-flags:--extern remove_extern_crate #![warn(rust_2018_idioms)] From 653cd47c09454c150fd9a61ff654710bbd7ba5b8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 15 Sep 2018 17:52:59 +0300 Subject: [PATCH 5/7] rustc_resolve: use `continue` instead of `return` to "exit" a loop iteration. --- src/librustc_resolve/resolve_imports.rs | 4 +-- src/test/ui/run-pass/uniform-paths/basic.rs | 2 +- .../issue-54253.rs | 27 +++++++++++++++++ .../issue-54253.stderr | 9 ++++++ .../ui/rust-2018/uniform-paths/issue-54253.rs | 29 +++++++++++++++++++ .../uniform-paths/issue-54253.stderr | 9 ++++++ 6 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs create mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-54253.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-54253.stderr diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index c86d430faceab..dc4a76db69266 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -746,7 +746,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // Currently imports can't resolve in non-module scopes, // we only have canaries in them for future-proofing. if external_crate.is_none() && results.module_scope.is_none() { - return; + continue; } { @@ -761,7 +761,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let possible_resultions = 1 + all_results.filter(|&def| def != first).count(); if possible_resultions <= 1 { - return; + continue; } } diff --git a/src/test/ui/run-pass/uniform-paths/basic.rs b/src/test/ui/run-pass/uniform-paths/basic.rs index fbdac98d2582e..7d997fe493a7b 100644 --- a/src/test/ui/run-pass/uniform-paths/basic.rs +++ b/src/test/ui/run-pass/uniform-paths/basic.rs @@ -37,7 +37,7 @@ fn main() { { // Test that having `std_io` in a module scope and a non-module // scope is allowed, when both resolve to the same definition. - use std::io as std_io; + use ::std::io as std_io; use std_io::stdout; stdout(); } diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs new file mode 100644 index 0000000000000..1f19a05d7a7f6 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs @@ -0,0 +1,27 @@ +// 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. + +// edition:2018 + +// Dummy import to introduce `uniform_paths` canaries. +use std; + +// fn version() -> &'static str {""} + +mod foo { + // Error wasn't reported, despite `version` being commented out above. + use crate::version; //~ ERROR unresolved import `crate::version` + + fn bar() { + version(); + } +} + +fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr new file mode 100644 index 0000000000000..6dcc451c60a61 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `crate::version` + --> $DIR/issue-54253.rs:20:9 + | +LL | use crate::version; //~ ERROR unresolved import `crate::version` + | ^^^^^^^^^^^^^^ no `version` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/uniform-paths/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths/issue-54253.rs new file mode 100644 index 0000000000000..7ca5c9e9eaefd --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-54253.rs @@ -0,0 +1,29 @@ +// 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. + +// edition:2018 + +#![feature(uniform_paths)] + +// Dummy import to introduce `uniform_paths` canaries. +use std; + +// fn version() -> &'static str {""} + +mod foo { + // Error wasn't reported, despite `version` being commented out above. + use crate::version; //~ ERROR unresolved import `crate::version` + + fn bar() { + version(); + } +} + +fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr new file mode 100644 index 0000000000000..0016e21ef4d55 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-54253.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `crate::version` + --> $DIR/issue-54253.rs:22:9 + | +LL | use crate::version; //~ ERROR unresolved import `crate::version` + | ^^^^^^^^^^^^^^ no `version` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. From 4529d10636911ad5b8f13dec2401040bc85645e5 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 15 Sep 2018 11:40:25 +0300 Subject: [PATCH 6/7] Update submodules to include rust-lang-nursery/rust-clippy#3189 and rust-lang-nursery/rls#1054. --- src/Cargo.lock | 19 ++++++++++--------- src/tools/clippy | 2 +- src/tools/rls | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 989655ffb4f5c..9f9c58ef900ee 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -12,7 +12,7 @@ version = "0.0.0" dependencies = [ "compiler_builtins 0.0.0", "core 0.0.0", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -433,7 +433,7 @@ dependencies = [ name = "core" version = "0.0.0" dependencies = [ - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -475,7 +475,7 @@ dependencies = [ "crossbeam-epoch 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1444,7 +1444,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1644,7 +1644,7 @@ dependencies = [ [[package]] name = "rand" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1767,6 +1767,7 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rls-analysis 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2191,7 +2192,7 @@ version = "0.0.0" dependencies = [ "graphviz 0.0.0", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_fs_util 0.0.0", @@ -2627,7 +2628,7 @@ dependencies = [ "panic_abort 0.0.0", "panic_unwind 0.0.0", "profiler_builtins 0.0.0", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_asan 0.0.0", "rustc_lsan 0.0.0", "rustc_msan 0.0.0", @@ -2794,7 +2795,7 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3262,7 +3263,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum racer 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4bc3847329b20ff5ba56c298938c179ae9911af15c9c10553f683b65164533" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "12397506224b2f93e6664ffc4f664b29be8208e5157d3d90b44f09b5fae470ea" +"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" "checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1" "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" diff --git a/src/tools/clippy b/src/tools/clippy index daa922393c741..183639b70bacf 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit daa922393c7417dcee930a880c80668cda3e308a +Subproject commit 183639b70bacf457920694d78a19cefe3565e1c0 diff --git a/src/tools/rls b/src/tools/rls index fa922de1e5e1f..2b21611d38a16 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit fa922de1e5e1f02b576b7a5aa6ded16935693ec5 +Subproject commit 2b21611d38a16a775f55ea102d8f442dfc51cf6d From bde0a54737653776ce271ec38f65f07fe1bd4388 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 15 Sep 2018 22:48:38 +0300 Subject: [PATCH 7/7] Revert "Auto merge of #53527 - Emerentius:test_all, r=nrc" This reverts commit 9f53c87b4b1f097e111c9525d60470ed22631018, reversing changes made to cba0fdf43c22795822e1d7c751a69e6c85007221. --- src/libtest/lib.rs | 200 ++++++++++++++++++--------------------------- 1 file changed, 81 insertions(+), 119 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 95eca5ed7ff57..6ffa6e9be937d 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -81,7 +81,7 @@ const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in qu // to be used by rustc to compile tests in libtest pub mod test { pub use {assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static, - Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, ShouldPanic, + Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, ShouldPanic, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, TestOpts, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk}; } @@ -349,19 +349,12 @@ pub enum OutputFormat { Json, } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum RunIgnored { - Yes, - No, - Only, -} - #[derive(Debug)] pub struct TestOpts { pub list: bool, pub filter: Option, pub filter_exact: bool, - pub run_ignored: RunIgnored, + pub run_ignored: bool, pub run_tests: bool, pub bench_benchmarks: bool, pub logfile: Option, @@ -380,7 +373,7 @@ impl TestOpts { list: false, filter: None, filter_exact: false, - run_ignored: RunIgnored::No, + run_ignored: false, run_tests: false, bench_benchmarks: false, logfile: None, @@ -399,8 +392,7 @@ pub type OptRes = Result; fn optgroups() -> getopts::Options { let mut opts = getopts::Options::new(); - opts.optflag("", "include-ignored", "Run ignored and not ignored tests") - .optflag("", "ignored", "Run only ignored tests") + opts.optflag("", "ignored", "Run ignored tests") .optflag("", "test", "Run tests and not benchmarks") .optflag("", "bench", "Run benchmarks instead of tests") .optflag("", "list", "List all tests and benchmarks") @@ -499,8 +491,8 @@ Test Attributes: contain: #[should_panic(expected = "foo")]. #[ignore] - When applied to a function which is already attributed as a test, then the test runner will ignore these tests during - normal test runs. Running with --ignored or --include-ignored will run - these tests."#, + normal test runs. Running with --ignored will run these + tests."#, usage = options.usage(&message) ); } @@ -553,21 +545,7 @@ pub fn parse_opts(args: &[String]) -> Option { None }; - let include_ignored = matches.opt_present("include-ignored"); - if !allow_unstable && include_ignored { - return Some(Err( - "The \"include-ignored\" flag is only accepted on the nightly compiler".into() - )); - } - - let run_ignored = match (include_ignored, matches.opt_present("ignored")) { - (true, true) => return Some(Err( - "the options --include-ignored and --ignored are mutually exclusive".into() - )), - (true, false) => RunIgnored::Yes, - (false, true) => RunIgnored::Only, - (false, false) => RunIgnored::No, - }; + let run_ignored = matches.opt_present("ignored"); let quiet = matches.opt_present("quiet"); let exact = matches.opt_present("exact"); let list = matches.opt_present("list"); @@ -1319,36 +1297,55 @@ fn get_concurrency() -> usize { pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec { let mut filtered = tests; - let matches_filter = |test: &TestDescAndFn, filter: &str| { - let test_name = test.desc.name.as_slice(); - - match opts.filter_exact { - true => test_name == filter, - false => test_name.contains(filter), - } - }; - // Remove tests that don't match the test filter - if let Some(ref filter) = opts.filter { - filtered.retain(|test| matches_filter(test, filter)); - } + filtered = match opts.filter { + None => filtered, + Some(ref filter) => filtered + .into_iter() + .filter(|test| { + if opts.filter_exact { + test.desc.name.as_slice() == &filter[..] + } else { + test.desc.name.as_slice().contains(&filter[..]) + } + }) + .collect(), + }; // Skip tests that match any of the skip filters - filtered.retain(|test| { - !opts.skip.iter().any(|sf| matches_filter(test, sf)) - }); - - // maybe unignore tests - match opts.run_ignored { - RunIgnored::Yes => { - filtered.iter_mut().for_each(|test| test.desc.ignore = false); - }, - RunIgnored::Only => { - filtered.retain(|test| test.desc.ignore); - filtered.iter_mut().for_each(|test| test.desc.ignore = false); + filtered = filtered + .into_iter() + .filter(|t| { + !opts.skip.iter().any(|sf| { + if opts.filter_exact { + t.desc.name.as_slice() == &sf[..] + } else { + t.desc.name.as_slice().contains(&sf[..]) + } + }) + }) + .collect(); + + // Maybe pull out the ignored test and unignore them + filtered = if !opts.run_ignored { + filtered + } else { + fn filter(test: TestDescAndFn) -> Option { + if test.desc.ignore { + let TestDescAndFn { desc, testfn } = test; + Some(TestDescAndFn { + desc: TestDesc { + ignore: false, + ..desc + }, + testfn, + }) + } else { + None + } } - RunIgnored::No => {} - } + filtered.into_iter().filter_map(filter).collect() + }; // Sort the tests alphabetically filtered.sort_by(|t1, t2| t1.desc.name.as_slice().cmp(t2.desc.name.as_slice())); @@ -1737,37 +1734,13 @@ pub mod bench { #[cfg(test)] mod tests { - use test::{filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, - ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, - TrFailedMsg, TrIgnored, TrOk}; + use test::{filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, ShouldPanic, + StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg, + TrIgnored, TrOk}; use std::sync::mpsc::channel; use bench; use Bencher; - - fn one_ignored_one_unignored_test() -> Vec { - vec![ - TestDescAndFn { - desc: TestDesc { - name: StaticTestName("1"), - ignore: true, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }, - TestDescAndFn { - desc: TestDesc { - name: StaticTestName("2"), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }, - ] - } - #[test] pub fn do_not_run_ignored_tests() { fn f() { @@ -1893,20 +1866,11 @@ mod tests { "filter".to_string(), "--ignored".to_string(), ]; - let opts = parse_opts(&args).unwrap().unwrap(); - assert_eq!(opts.run_ignored, RunIgnored::Only); - } - - #[test] - fn parse_include_ignored_flag() { - let args = vec![ - "progname".to_string(), - "filter".to_string(), - "-Zunstable-options".to_string(), - "--include-ignored".to_string(), - ]; - let opts = parse_opts(&args).unwrap().unwrap(); - assert_eq!(opts.run_ignored, RunIgnored::Yes); + let opts = match parse_opts(&args) { + Some(Ok(o)) => o, + _ => panic!("Malformed arg in parse_ignored_flag"), + }; + assert!((opts.run_ignored)); } #[test] @@ -1916,9 +1880,28 @@ mod tests { let mut opts = TestOpts::new(); opts.run_tests = true; - opts.run_ignored = RunIgnored::Only; + opts.run_ignored = true; - let tests = one_ignored_one_unignored_test(); + let tests = vec![ + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("1"), + ignore: true, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("2"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + ]; let filtered = filter_tests(&opts, tests); assert_eq!(filtered.len(), 1); @@ -1926,23 +1909,6 @@ mod tests { assert!(!filtered[0].desc.ignore); } - #[test] - pub fn run_include_ignored_option() { - // When we "--include-ignored" tests, the ignore flag should be set to false on - // all tests and no test filtered out - - let mut opts = TestOpts::new(); - opts.run_tests = true; - opts.run_ignored = RunIgnored::Yes; - - let tests = one_ignored_one_unignored_test(); - let filtered = filter_tests(&opts, tests); - - assert_eq!(filtered.len(), 2); - assert!(!filtered[0].desc.ignore); - assert!(!filtered[1].desc.ignore); - } - #[test] pub fn exact_filter_match() { fn tests() -> Vec { @@ -2050,9 +2016,7 @@ mod tests { "test::ignored_tests_result_in_ignored".to_string(), "test::first_free_arg_should_be_a_filter".to_string(), "test::parse_ignored_flag".to_string(), - "test::parse_include_ignored_flag".to_string(), "test::filter_for_ignored_option".to_string(), - "test::run_include_ignored_option".to_string(), "test::sort_tests".to_string(), ]; let tests = { @@ -2083,8 +2047,6 @@ mod tests { "test::first_free_arg_should_be_a_filter".to_string(), "test::ignored_tests_result_in_ignored".to_string(), "test::parse_ignored_flag".to_string(), - "test::parse_include_ignored_flag".to_string(), - "test::run_include_ignored_option".to_string(), "test::sort_tests".to_string(), ];