From 9a2ee0aaef1dfe835c65359b2b07721953ea7040 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu <edy.burt@gmail.com> Date: Thu, 2 May 2019 05:05:58 +0300 Subject: [PATCH 1/5] serialize: add missing Encodable impl for Path. --- src/libserialize/serialize.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 8ef8c2b4c0a22..36a1628014ddb 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -764,12 +764,18 @@ macro_rules! tuple { tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } -impl Encodable for path::PathBuf { +impl Encodable for path::Path { fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> { self.to_str().unwrap().encode(e) } } +impl Encodable for path::PathBuf { + fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> { + path::Path::encode(self, e) + } +} + impl Decodable for path::PathBuf { fn decode<D: Decoder>(d: &mut D) -> Result<path::PathBuf, D::Error> { let bytes: String = Decodable::decode(d)?; From f0e43fc98671f76f7cdcc07cfa17fb2362c132ea Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu <edy.burt@gmail.com> Date: Thu, 2 May 2019 05:06:08 +0300 Subject: [PATCH 2/5] compiletest: only use `make_exe_name` for tests that end up being executed. --- .../const-eval/unused-broken-const.stderr | 2 -- src/test/ui/emit-directives.rs | 6 ----- src/test/ui/emit-directives.stderr | 2 +- ...n-projection-output-repeated-supertrait.rs | 3 +++ src/tools/compiletest/src/runtest.rs | 26 +++++++++++++++---- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/test/ui/consts/const-eval/unused-broken-const.stderr b/src/test/ui/consts/const-eval/unused-broken-const.stderr index 603efe449f143..e45ce65d8bb35 100644 --- a/src/test/ui/consts/const-eval/unused-broken-const.stderr +++ b/src/test/ui/consts/const-eval/unused-broken-const.stderr @@ -1,5 +1,3 @@ -warning: due to multiple output types requested, the explicitly specified output file name will be adapted for each output type - error: any use of this value will cause an error --> $DIR/unused-broken-const.rs:5:18 | diff --git a/src/test/ui/emit-directives.rs b/src/test/ui/emit-directives.rs index 088280e358ae7..924569d3e232d 100644 --- a/src/test/ui/emit-directives.rs +++ b/src/test/ui/emit-directives.rs @@ -1,11 +1,5 @@ -// ignore-tidy-linelength // compile-flags:--emit=metadata --error-format=json -Z emit-directives // compile-pass -// -// Normalization is required to eliminated minor path and filename differences -// across platforms. -// normalize-stderr-test: "metadata file written: .*/emit-directives" -> "metadata file written: .../emit-directives" -// normalize-stderr-test: "emit-directives(\.\w*)?/a(\.\w*)?" -> "emit-directives/a" // A very basic test for the emission of build directives in JSON output. diff --git a/src/test/ui/emit-directives.stderr b/src/test/ui/emit-directives.stderr index b8a4b96f4bf25..068745edb8dc0 100644 --- a/src/test/ui/emit-directives.stderr +++ b/src/test/ui/emit-directives.stderr @@ -1 +1 @@ -{"directive":"metadata file written: .../emit-directives/a"} +{"directive":"metadata file written: $TEST_BUILD_DIR/emit-directives/libemit_directives.rmeta"} diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs index 46c083f930591..3e9f612a2afee 100644 --- a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs @@ -1,5 +1,8 @@ // compile-pass +// FIXME(eddyb) shorten the name so windows doesn't choke on it. +#![crate_name = "trait_test"] + // Regression test related to #56288. Check that a supertrait projection (of // `Output`) that references `Self` is ok if there is another occurence of // the same supertrait that specifies the projection explicitly, even if diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 42f9cdb7886fd..649679e9b3cc0 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1422,10 +1422,21 @@ impl<'test> TestCx<'test> { } fn compile_test(&self) -> ProcRes { - let mut rustc = self.make_compile_args( - &self.testpaths.file, - TargetLocation::ThisFile(self.make_exe_name()), - ); + // Only use `make_exe_name` when the test ends up being executed. + let will_execute = match self.config.mode { + RunPass | Ui => self.should_run_successfully(), + Incremental => self.revision.unwrap().starts_with("r"), + RunFail | RunPassValgrind | MirOpt | + DebugInfoBoth | DebugInfoGdb | DebugInfoLldb => true, + _ => false, + }; + let output_file = if will_execute { + TargetLocation::ThisFile(self.make_exe_name()) + } else { + TargetLocation::ThisDirectory(self.output_base_dir()) + }; + + let mut rustc = self.make_compile_args(&self.testpaths.file, output_file); rustc.arg("-L").arg(&self.aux_output_dir_name()); @@ -1882,7 +1893,12 @@ impl<'test> TestCx<'test> { rustc.arg("-o").arg(path); } TargetLocation::ThisDirectory(path) => { - rustc.arg("--out-dir").arg(path); + if is_rustdoc { + // `rustdoc` uses `-o` for the output directory. + rustc.arg("-o").arg(path); + } else { + rustc.arg("--out-dir").arg(path); + } } } From 1618c079abc7cb97afe3cbcf5a7ff1f9412775bc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu <edy.burt@gmail.com> Date: Thu, 2 May 2019 05:06:33 +0300 Subject: [PATCH 3/5] rustc: rename -Z emit-directives to -Z emit-artifact-notifications and simplify the output. --- src/librustc/session/config.rs | 4 ++-- src/librustc_errors/emitter.rs | 8 +++++--- src/librustc_errors/lib.rs | 18 ++++++------------ src/librustc_interface/passes.rs | 13 +++++-------- src/libsyntax/json.rs | 13 +++++++------ .../ui/emit-artifact-notifications.nll.stderr | 1 + src/test/ui/emit-artifact-notifications.rs | 6 ++++++ src/test/ui/emit-artifact-notifications.stderr | 1 + src/test/ui/emit-directives.rs | 6 ------ src/test/ui/emit-directives.stderr | 1 - src/tools/compiletest/src/json.rs | 10 +++++----- 11 files changed, 38 insertions(+), 43 deletions(-) create mode 100644 src/test/ui/emit-artifact-notifications.nll.stderr create mode 100644 src/test/ui/emit-artifact-notifications.rs create mode 100644 src/test/ui/emit-artifact-notifications.stderr delete mode 100644 src/test/ui/emit-directives.rs delete mode 100644 src/test/ui/emit-directives.stderr diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 084a5429f26fa..12427daa38381 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1462,8 +1462,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, the same values as the target option of the same name"), allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED], "only allow the listed language features to be enabled in code (space separated)"), - emit_directives: bool = (false, parse_bool, [UNTRACKED], - "emit build directives if producing JSON output"), + emit_artifact_notifications: bool = (false, parse_bool, [UNTRACKED], + "emit notifications after each artifact has been output (only in the JSON format)"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index bfc9113c2d41e..59cbd65f05c68 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -16,6 +16,7 @@ use std::borrow::Cow; use std::io::prelude::*; use std::io; use std::cmp::{min, Reverse}; +use std::path::Path; use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi}; use termcolor::{WriteColor, Color, Buffer}; @@ -52,9 +53,10 @@ pub trait Emitter { /// Emit a structured diagnostic. fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>); - /// Emit a JSON directive. The default is to do nothing; this should only - /// be emitted with --error-format=json. - fn maybe_emit_json_directive(&mut self, _directive: String) {} + /// Emit a notification that an artifact has been output. + /// This is currently only supported for the JSON format, + /// other formats can, and will, simply ignore it. + fn emit_artifact_notification(&mut self, _path: &Path) {} /// Checks if should show explanations about "rustc --explain" fn should_show_explain(&self) -> bool { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index e173e1060cc10..3aa87fad07174 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -26,6 +26,7 @@ use std::borrow::Cow; use std::cell::Cell; use std::{error, fmt}; use std::panic; +use std::path::Path; use termcolor::{ColorSpec, Color}; @@ -294,16 +295,9 @@ impl error::Error for ExplicitBug { pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString, DiagnosticId}; pub use diagnostic_builder::DiagnosticBuilder; -/// A handler deals with two kinds of compiler output. -/// - Errors: certain errors (fatal, bug, unimpl) may cause immediate exit, -/// others log errors for later reporting. -/// - Directives: with --error-format=json, the compiler produces directives -/// that indicate when certain actions have completed, which are useful for -/// Cargo. They may change at any time and should not be considered a public -/// API. -/// -/// This crate's name (rustc_errors) doesn't encompass the directives, because -/// directives were added much later. +/// A handler deals with errors and other compiler output. +/// Certain errors (fatal, bug, unimpl) may cause immediate exit, +/// others log errors for later reporting. pub struct Handler { pub flags: HandlerFlags, @@ -775,8 +769,8 @@ impl Handler { } } - pub fn maybe_emit_json_directive(&self, directive: String) { - self.emitter.borrow_mut().maybe_emit_json_directive(directive); + pub fn emit_artifact_notification(&self, path: &Path) { + self.emitter.borrow_mut().emit_artifact_notification(path); } } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 8543cca1dd545..54b3e73420560 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -1048,14 +1048,11 @@ fn encode_and_write_metadata<'tcx>( tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)) }); let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir); - match std::fs::rename(&metadata_filename, &out_filename) { - Ok(_) => { - if tcx.sess.opts.debugging_opts.emit_directives { - tcx.sess.parse_sess.span_diagnostic.maybe_emit_json_directive( - format!("metadata file written: {}", out_filename.display())); - } - } - Err(e) => tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)), + if let Err(e) = fs::rename(&metadata_filename, &out_filename) { + tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + } + if tcx.sess.opts.debugging_opts.emit_artifact_notifications { + tcx.sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); } } diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 65f8d0e77d7be..2dd2ecb749300 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -19,6 +19,7 @@ use errors::emitter::{Emitter, HumanReadableErrorType}; use syntax_pos::{MacroBacktrace, Span, SpanLabel, MultiSpan}; use rustc_data_structures::sync::{self, Lrc}; use std::io::{self, Write}; +use std::path::Path; use std::vec; use std::sync::{Arc, Mutex}; @@ -91,15 +92,15 @@ impl Emitter for JsonEmitter { } } - fn maybe_emit_json_directive(&mut self, directive: String) { - let data = Directive { directive }; + fn emit_artifact_notification(&mut self, path: &Path) { + let data = ArtifactNotification { artifact: path }; let result = if self.pretty { writeln!(&mut self.dst, "{}", as_pretty_json(&data)) } else { writeln!(&mut self.dst, "{}", as_json(&data)) }; if let Err(e) = result { - panic!("failed to print message: {:?}", e); + panic!("failed to print notification: {:?}", e); } } } @@ -181,9 +182,9 @@ struct DiagnosticCode { } #[derive(RustcEncodable)] -struct Directive { - /// The directive itself. - directive: String, +struct ArtifactNotification<'a> { + /// The path of the artifact. + artifact: &'a Path, } impl Diagnostic { diff --git a/src/test/ui/emit-artifact-notifications.nll.stderr b/src/test/ui/emit-artifact-notifications.nll.stderr new file mode 100644 index 0000000000000..347d9aeac2307 --- /dev/null +++ b/src/test/ui/emit-artifact-notifications.nll.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta"} diff --git a/src/test/ui/emit-artifact-notifications.rs b/src/test/ui/emit-artifact-notifications.rs new file mode 100644 index 0000000000000..c2c930c8b1bae --- /dev/null +++ b/src/test/ui/emit-artifact-notifications.rs @@ -0,0 +1,6 @@ +// compile-flags:--emit=metadata --error-format=json -Z emit-artifact-notifications +// compile-pass + +// A very basic test for the emission of artifact notifications in JSON output. + +fn main() {} diff --git a/src/test/ui/emit-artifact-notifications.stderr b/src/test/ui/emit-artifact-notifications.stderr new file mode 100644 index 0000000000000..56c977181ff51 --- /dev/null +++ b/src/test/ui/emit-artifact-notifications.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta"} diff --git a/src/test/ui/emit-directives.rs b/src/test/ui/emit-directives.rs deleted file mode 100644 index 924569d3e232d..0000000000000 --- a/src/test/ui/emit-directives.rs +++ /dev/null @@ -1,6 +0,0 @@ -// compile-flags:--emit=metadata --error-format=json -Z emit-directives -// compile-pass - -// A very basic test for the emission of build directives in JSON output. - -fn main() {} diff --git a/src/test/ui/emit-directives.stderr b/src/test/ui/emit-directives.stderr deleted file mode 100644 index 068745edb8dc0..0000000000000 --- a/src/test/ui/emit-directives.stderr +++ /dev/null @@ -1 +0,0 @@ -{"directive":"metadata file written: $TEST_BUILD_DIR/emit-directives/libemit_directives.rmeta"} diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 26a3c4dee40aa..d651b9a92b649 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -4,7 +4,7 @@ use crate::errors::{Error, ErrorKind}; use crate::runtest::ProcRes; use serde_json; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::str::FromStr; #[derive(Deserialize)] @@ -18,9 +18,9 @@ struct Diagnostic { } #[derive(Deserialize)] -struct Directive { +struct ArtifactNotification { #[allow(dead_code)] - directive: String, + artifact: PathBuf, } #[derive(Deserialize, Clone)] @@ -75,8 +75,8 @@ pub fn extract_rendered(output: &str) -> String { if line.starts_with('{') { if let Ok(diagnostic) = serde_json::from_str::<Diagnostic>(line) { diagnostic.rendered - } else if let Ok(_directive) = serde_json::from_str::<Directive>(line) { - // Swallow the directive. + } else if let Ok(_) = serde_json::from_str::<ArtifactNotification>(line) { + // Ignore the notification. None } else { print!( From bb1c67dde4ef2936b4f9b39cf4963584608d3c12 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu <edy.burt@gmail.com> Date: Thu, 2 May 2019 05:49:57 +0300 Subject: [PATCH 4/5] rustc_codegen_ssa: emit artifact notifications for the main link product too. --- src/librustc_codegen_ssa/back/link.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index f25891d77ce53..8a751b02b78dd 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -95,6 +95,9 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, ); } } + if sess.opts.debugging_opts.emit_artifact_notifications { + sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); + } } if sess.opts.cg.save_temps { From c89a13179ea1d8431868508d79d57ab3c6ce0ac7 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu <edy.burt@gmail.com> Date: Tue, 7 May 2019 04:49:26 +0300 Subject: [PATCH 5/5] compiletest: uniformly normalize paths, so they all work on all platforms. --- src/tools/compiletest/src/runtest.rs | 32 +++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 649679e9b3cc0..0e4946736fb7c 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3154,42 +3154,40 @@ impl<'test> TestCx<'test> { } fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String { - let parent_dir = self.testpaths.file.parent().unwrap(); let cflags = self.props.compile_flags.join(" "); let json = cflags.contains("--error-format json") || cflags.contains("--error-format pretty-json") || cflags.contains("--error-format=json") || cflags.contains("--error-format=pretty-json"); - let parent_dir_str = if json { - parent_dir.display().to_string().replace("\\", "\\\\") - } else { - parent_dir.display().to_string() + + let mut normalized = output.to_string(); + + let mut normalize_path = |from: &Path, to: &str| { + let mut from = from.display().to_string(); + if json { + from = from.replace("\\", "\\\\"); + } + normalized = normalized.replace(&from, to); }; - let mut normalized = output.replace(&parent_dir_str, "$DIR"); + let parent_dir = self.testpaths.file.parent().unwrap(); + normalize_path(parent_dir, "$DIR"); // Paths into the libstd/libcore let src_dir = self.config.src_base.parent().unwrap().parent().unwrap(); - let src_dir_str = if json { - src_dir.display().to_string().replace("\\", "\\\\") - } else { - src_dir.display().to_string() - }; - normalized = normalized.replace(&src_dir_str, "$SRC_DIR"); + normalize_path(src_dir, "$SRC_DIR"); // Paths into the build directory let test_build_dir = &self.config.build_base; let parent_build_dir = test_build_dir.parent().unwrap().parent().unwrap().parent().unwrap(); // eg. /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui - normalized = normalized.replace(test_build_dir.to_str().unwrap(), "$TEST_BUILD_DIR"); + normalize_path(test_build_dir, "$TEST_BUILD_DIR"); // eg. /home/user/rust/build - normalized = normalized.replace(&parent_build_dir.to_str().unwrap(), "$BUILD_DIR"); + normalize_path(parent_build_dir, "$BUILD_DIR"); // Paths into lib directory. - let mut lib_dir = parent_build_dir.parent().unwrap().to_path_buf(); - lib_dir.push("lib"); - normalized = normalized.replace(&lib_dir.to_str().unwrap(), "$LIB_DIR"); + normalize_path(&parent_build_dir.parent().unwrap().join("lib"), "$LIB_DIR"); if json { // escaped newlines in json strings should be readable