diff --git a/src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile b/src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile deleted file mode 100644 index fc39691c507e..000000000000 --- a/src/test/run-make-fulldeps/use-suggestions-rust-2018/Makefile +++ /dev/null @@ -1,7 +0,0 @@ --include ../tools.mk - -all: - $(RUSTC) ep-nested-lib.rs - - $(RUSTC) use-suggestions.rs --edition=2018 --extern ep_nested_lib=$(TMPDIR)/libep_nested_lib.rlib 2>&1 | $(CGREP) "use ep_nested_lib::foo::bar::Baz" - diff --git a/src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs b/src/test/ui/auxiliary/baz.rs similarity index 91% rename from src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs rename to src/test/ui/auxiliary/baz.rs index 62730a5653f3..80bf1f2108ad 100644 --- a/src/test/run-make-fulldeps/use-suggestions-rust-2018/use-suggestions.rs +++ b/src/test/ui/auxiliary/baz.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { - let x = Baz{}; -} +#![crate_type="lib"] + +pub struct Yellow; diff --git a/src/test/ui/issue-53737.rs b/src/test/ui/issue-53737.rs new file mode 100644 index 000000000000..5578afa33a83 --- /dev/null +++ b/src/test/ui/issue-53737.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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-crate:myfoo=baz.rs +// edition:2018 + + +use myfoo::Yellow; + +fn main() { + let x = Yellow{}; +} diff --git a/src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs b/src/test/ui/rust-2018/auxiliary/ep-nested-lib.rs similarity index 95% rename from src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs rename to src/test/ui/rust-2018/auxiliary/ep-nested-lib.rs index c0bce6e3371d..2c741e70238e 100644 --- a/src/test/run-make-fulldeps/use-suggestions-rust-2018/ep-nested-lib.rs +++ b/src/test/ui/rust-2018/auxiliary/ep-nested-lib.rs @@ -12,6 +12,6 @@ pub mod foo { pub mod bar { - pub struct Baz; + pub struct Bazz; } } diff --git a/src/test/ui/rust-2018/use-suggestions-extern-prelude.rs b/src/test/ui/rust-2018/use-suggestions-extern-prelude.rs new file mode 100644 index 000000000000..3f80cc305f77 --- /dev/null +++ b/src/test/ui/rust-2018/use-suggestions-extern-prelude.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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// edition:2018 +// aux-crate:netted=ep-nested-lib.rs + +fn main() { + let _x = Bazz{}; + //~^ ERROR cannot find struct, variant or union type `Bazz` in this scope +} diff --git a/src/test/ui/rust-2018/use-suggestions-extern-prelude.stderr b/src/test/ui/rust-2018/use-suggestions-extern-prelude.stderr new file mode 100644 index 000000000000..755b24b676a5 --- /dev/null +++ b/src/test/ui/rust-2018/use-suggestions-extern-prelude.stderr @@ -0,0 +1,13 @@ +error[E0422]: cannot find struct, variant or union type `Bazz` in this scope + --> $DIR/use-suggestions-extern-prelude.rs:15:14 + | +LL | let _x = Bazz{}; + | ^^^^ not found in this scope +help: possible candidate is found in another module, you can import it into scope + | +LL | use netted::foo::bar::Bazz; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 06eeef61a194..8ffc79e6c77d 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -77,6 +77,7 @@ pub struct EarlyProps { pub ignore: Ignore, pub should_fail: bool, pub aux: Vec<String>, + pub aux_crate: Vec<KeyValue>, pub revisions: Vec<String>, } @@ -86,6 +87,7 @@ impl EarlyProps { ignore: Ignore::Run, should_fail: false, aux: Vec::new(), + aux_crate: Vec::new(), revisions: vec![], }; @@ -137,6 +139,10 @@ impl EarlyProps { props.aux.push(s); } + if let Some(s) = config.parse_aux_crate(ln) { + props.aux_crate.push(s); + } + if let Some(r) = config.parse_revisions(ln) { props.revisions.extend(r); } @@ -268,6 +274,8 @@ pub struct TestProps { // directory as the test, but for backwards compatibility reasons // we also check the auxiliary directory) pub aux_builds: Vec<String>, + // crates that should be compiled and exposed as the given alias + pub aux_crates: Vec<KeyValue>, // Environment settings to use for compiling pub rustc_env: Vec<(String, String)>, // Environment settings to use during execution @@ -327,6 +335,7 @@ impl TestProps { run_flags: None, pp_exact: None, aux_builds: vec![], + aux_crates: vec![], revisions: vec![], rustc_env: vec![], exec_env: vec![], @@ -442,6 +451,10 @@ impl TestProps { self.aux_builds.push(ab); } + if let Some(ab) = config.parse_aux_crate(ln) { + self.aux_crates.push(ab); + } + if let Some(ee) = config.parse_env(ln, "exec-env") { self.exec_env.push(ee); } @@ -576,6 +589,10 @@ impl Config { self.parse_name_value_directive(line, "aux-build") } + fn parse_aux_crate(&self, line: &str) -> Option<KeyValue> { + self.parse_name_kv_directive(line, "aux-crate") + } + fn parse_compile_flags(&self, line: &str) -> Option<String> { self.parse_name_value_directive(line, "compile-flags") } @@ -772,14 +789,11 @@ impl Config { } pub fn parse_name_value_directive(&self, line: &str, directive: &str) -> Option<String> { - let colon = directive.len(); - if line.starts_with(directive) && line.as_bytes().get(colon) == Some(&b':') { - let value = line[(colon + 1)..].to_owned(); - debug!("{}: {}", directive, value); - Some(expand_variables(value, self)) - } else { - None - } + internal_parse_name_value_directive(line, directive).map(|v| expand_variables(v, self)) + } + + pub fn parse_name_kv_directive(&self, line: &str, directive: &str) -> Option<KeyValue> { + internal_parse_name_kv_directive(line, directive) } pub fn find_rust_src_root(&self) -> Option<PathBuf> { @@ -816,6 +830,47 @@ pub fn lldb_version_to_int(version_string: &str) -> isize { version_string.parse().expect(&error_string) } +#[test] +fn test_parse_name_value_directive() { + assert_eq!(Some("foo.rs".to_owned()), + internal_parse_name_value_directive("aux-build:foo.rs", "aux-build")); + assert_eq!(None, internal_parse_name_value_directive("faux-build:foo.rs", "aux-build")); +} + +#[derive(Clone, Debug, PartialEq)] +pub struct KeyValue { + pub key: String, + pub value: String, +} + +#[test] +fn test_parse_name_kv_directive() { + let value = internal_parse_name_kv_directive("crate-aux-build:baz=foo.rs", "crate-aux-build"); + assert_eq!(Some(KeyValue{key:"baz".to_owned(), value:"foo.rs".to_owned()}), value); +} + +fn internal_parse_name_kv_directive(line: &str, directive: &str) -> Option<KeyValue> { + if let Some(value) = internal_parse_name_value_directive(line, directive) { + let parts = value.split("=").collect::<Vec<&str>>(); + if parts.len() == 2 { + let (k,v) = (parts[0], parts[1]); + return Some(KeyValue{key:k.to_string(),value:v.to_string()}); + } + } + None +} + +fn internal_parse_name_value_directive(line: &str, directive: &str) -> Option<String> { + let colon = directive.len(); + if line.starts_with(directive) && line.as_bytes().get(colon) == Some(&b':') { + let value = line[(colon + 1)..].to_owned(); + debug!("{}: {}", directive, value); + Some(value) + } else { + None + } +} + fn expand_variables(mut value: String, config: &Config) -> String { const CWD: &'static str = "{{cwd}}"; const SRC_BASE: &'static str = "{{src-base}}"; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8c3b1bb4df33..efd3d0aff140 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -36,6 +36,7 @@ use std::io::{self, BufReader}; use std::path::{Path, PathBuf}; use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::str; +use std::env::consts::DLL_EXTENSION; use extract_gdb_version; use is_android_gdb_target; @@ -1563,66 +1564,25 @@ impl<'test> TestCx<'test> { } for rel_ab in &self.props.aux_builds { - let aux_testpaths = self.compute_aux_test_paths(rel_ab); - let aux_props = - self.props - .from_aux_file(&aux_testpaths.file, self.revision, self.config); - let aux_output = TargetLocation::ThisDirectory(self.aux_output_dir_name()); - let aux_cx = TestCx { - config: self.config, - props: &aux_props, - testpaths: &aux_testpaths, - revision: self.revision, - }; - // Create the directory for the stdout/stderr files. - create_dir_all(aux_cx.output_base_dir()).unwrap(); - let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output); - - let crate_type = if aux_props.no_prefer_dynamic { - None - } else if self.config.target.contains("cloudabi") - || self.config.target.contains("emscripten") - || (self.config.target.contains("musl") && !aux_props.force_host) - || self.config.target.contains("wasm32") - { - // We primarily compile all auxiliary libraries as dynamic libraries - // to avoid code size bloat and large binaries as much as possible - // for the test suite (otherwise including libstd statically in all - // executables takes up quite a bit of space). - // - // For targets like MUSL or Emscripten, however, there is no support for - // dynamic libraries so we just go back to building a normal library. Note, - // however, that for MUSL if the library is built with `force_host` then - // it's ok to be a dylib as the host should always support dylibs. - Some("lib") - } else { - Some("dylib") - }; + build_auxiliary(self, rel_ab, &aux_dir); + } - if let Some(crate_type) = crate_type { - aux_rustc.args(&["--crate-type", crate_type]); - } + for rel_ab in &self.props.aux_crates { + build_auxiliary(self, &rel_ab.value, &aux_dir); + } - aux_rustc.arg("-L").arg(&aux_dir); + rustc.envs(self.props.rustc_env.clone()); - let auxres = aux_cx.compose_and_run( - aux_rustc, - aux_cx.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), - None, - ); - if !auxres.status.success() { - self.fatal_proc_rec( - &format!( - "auxiliary build of {:?} failed to compile: ", - aux_testpaths.file.display() - ), - &auxres, - ); - } + for aux_crate in &self.props.aux_crates { + rustc.arg("--extern"); + rustc.arg(format!("{}={}/lib{}", + aux_crate.key, + aux_dir.display(), + aux_crate.value.replace(".rs", &format!(".{}", DLL_EXTENSION)) + .replace("-","_") + )); } - rustc.envs(self.props.rustc_env.clone()); self.compose_and_run( rustc, self.config.compile_lib_path.to_str().unwrap(), @@ -3249,6 +3209,66 @@ impl<'test> TestCx<'test> { } } +fn build_auxiliary(test_cx: &TestCx, rel_ab: &str, aux_dir: &Path) { + let aux_testpaths = test_cx.compute_aux_test_paths(rel_ab); + let aux_props = + test_cx.props + .from_aux_file(&aux_testpaths.file, test_cx.revision, test_cx.config); + let aux_output = TargetLocation::ThisDirectory(test_cx.aux_output_dir_name()); + let aux_cx = TestCx { + config: test_cx.config, + props: &aux_props, + testpaths: &aux_testpaths, + revision: test_cx.revision, + }; + // Create the directory for the stdout/stderr files. + create_dir_all(aux_cx.output_base_dir()).unwrap(); + let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output); + + let crate_type = if aux_props.no_prefer_dynamic { + None + } else if test_cx.config.target.contains("cloudabi") + || test_cx.config.target.contains("emscripten") + || (test_cx.config.target.contains("musl") && !aux_props.force_host) + || test_cx.config.target.contains("wasm32") + { + // We primarily compile all auxiliary libraries as dynamic libraries + // to avoid code size bloat and large binaries as much as possible + // for the test suite (otherwise including libstd statically in all + // executables takes up quite a bit of space). + // + // For targets like MUSL or Emscripten, however, there is no support for + // dynamic libraries so we just go back to building a normal library. Note, + // however, that for MUSL if the library is built with `force_host` then + // it's ok to be a dylib as the host should always support dylibs. + Some("lib") + } else { + Some("dylib") + }; + + if let Some(crate_type) = crate_type { + aux_rustc.args(&["--crate-type", crate_type]); + } + + aux_rustc.arg("-L").arg(&aux_dir); + + let auxres = aux_cx.compose_and_run( + aux_rustc, + aux_cx.config.compile_lib_path.to_str().unwrap(), + Some(aux_dir.to_str().unwrap()), + None, + ); + if !auxres.status.success() { + test_cx.fatal_proc_rec( + &format!( + "auxiliary build of {:?} failed to compile: ", + aux_testpaths.file.display() + ), + &auxres, + ); + } +} + struct ProcArgs { prog: String, args: Vec<String>,