Skip to content

Commit f690098

Browse files
committed
Auto merge of #62766 - alexcrichton:stabilize-pipelined-compilation, r=oli-obk
rustc: Stabilize options for pipelined compilation This commit stabilizes options in the compiler necessary for Cargo to enable "pipelined compilation" by default. The concept of pipelined compilation, how it's implemented, and what it means for rustc are documented in #60988. This PR is coupled with a PR against Cargo (rust-lang/cargo#7143) which updates Cargo's support for pipelined compliation to rustc, and also enables support by default in Cargo. (note that the Cargo PR cannot land until this one against rustc lands). The technical changes performed here were to stabilize the functionality proposed in #60419 and #60987, the underlying pieces to enable pipelined compilation support in Cargo. The issues have had some discussion during stabilization, but the newly stabilized surface area here is: * A new `--json` flag was added to the compiler. * The `--json` flag can be passed multiple times. * The value of the `--json` flag is a comma-separated list of directives. * The `--json` flag cannot be combined with `--color` * The `--json` flag must be combined with `--error-format=json` * The acceptable list of directives to `--json` are: * `diagnostic-short` - the `rendered` field of diagnostics will have a "short" rendering matching `--error-format=short` * `diagnostic-rendered-ansi` - the `rendered` field of diagnostics will be colorized with ansi color codes embedded in the string field * `artifacts` - JSON blobs will be emitted for artifacts being emitted by the compiler The unstable `-Z emit-artifact-notifications` and `--json-rendered` flags have also been removed during this commit as well. Closes #60419 Closes #60987 Closes #60988
2 parents 4eeaaa7 + 1731233 commit f690098

26 files changed

+237
-112
lines changed

src/bootstrap/test.rs

+3
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ impl Step for Cargo {
229229
cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
230230
// Disable a test that has issues with mingw.
231231
cargo.env("CARGO_TEST_DISABLE_GIT_CLI", "1");
232+
// Forcibly disable tests using nightly features since any changes to
233+
// those features won't be able to land.
234+
cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
232235

233236
try_run(
234237
builder,

src/doc/rustc/src/command-line-arguments.md

+33
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,36 @@ current directory out of pathnames emitted into the object files. The
271271
replacement is purely textual, with no consideration of the current system's
272272
pathname syntax. For example `--remap-path-prefix foo=bar` will match
273273
`foo/lib.rs` but not `./foo/lib.rs`.
274+
275+
## `--json`: configure json messages printed by the compiler
276+
277+
When the `--error-format=json` option is passed to rustc then all of the
278+
compiler's diagnostic output will be emitted in the form of JSON blobs. The
279+
`--json` argument can be used in conjunction with `--error-format=json` to
280+
configure what the JSON blobs contain as well as which ones are emitted.
281+
282+
With `--error-format=json` the compiler will always emit any compiler errors as
283+
a JSON blob, but the following options are also available to the `--json` flag
284+
to customize the output:
285+
286+
- `diagnostic-short` - json blobs for diagnostic messages should use the "short"
287+
rendering instead of the normal "human" default. This means that the output of
288+
`--error-format=short` will be embedded into the JSON diagnostics instead of
289+
the default `--error-format=human`.
290+
291+
- `diagnostic-rendered-ansi` - by default JSON blobs in their `rendered` field
292+
will contain a plain text rendering of the diagnostic. This option instead
293+
indicates that the diagnostic should have embedded ANSI color codes intended
294+
to be used to colorize the message in the manner rustc typically already does
295+
for terminal outputs. Note that this is usefully combined with crates like
296+
`fwdansi` to translate these ANSI codes on Windows to console commands or
297+
`strip-ansi-escapes` if you'd like to optionally remove the ansi colors
298+
afterwards.
299+
300+
- `artifacts` - this instructs rustc to emit a JSON blob for each artifact that
301+
is emitted. An artifact corresponds to a request from the `--emit` CLI
302+
argument, and as soon as the artifact is available on the filesystem a
303+
notification will be emitted.
304+
305+
Note that it is invalid to combine the `--json` argument with the `--color`
306+
argument, and it is required to combine `--json` with `--error-format=json`.

src/librustc/session/config.rs

+107-47
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,10 @@ top_level_options!(
438438
remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
439439

440440
edition: Edition [TRACKED],
441+
442+
// Whether or not we're emitting JSON blobs about each artifact produced
443+
// by the compiler.
444+
json_artifact_notifications: bool [TRACKED],
441445
}
442446
);
443447

@@ -625,6 +629,7 @@ impl Default for Options {
625629
cli_forced_thinlto_off: false,
626630
remap_path_prefix: Vec::new(),
627631
edition: DEFAULT_EDITION,
632+
json_artifact_notifications: false,
628633
}
629634
}
630635
}
@@ -1459,8 +1464,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
14591464
the same values as the target option of the same name"),
14601465
allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
14611466
"only allow the listed language features to be enabled in code (space separated)"),
1462-
emit_artifact_notifications: bool = (false, parse_bool, [UNTRACKED],
1463-
"emit notifications after each artifact has been output (only in the JSON format)"),
14641467
symbol_mangling_version: SymbolManglingVersion = (SymbolManglingVersion::Legacy,
14651468
parse_symbol_mangling_version, [TRACKED],
14661469
"which mangling version to use for symbol names"),
@@ -1818,11 +1821,11 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
18181821
"How errors and other messages are produced",
18191822
"human|json|short",
18201823
),
1821-
opt::opt(
1824+
opt::multi_s(
18221825
"",
1823-
"json-rendered",
1824-
"Choose `rendered` field of json diagnostics render scheme",
1825-
"plain|termcolor",
1826+
"json",
1827+
"Configure the JSON output of the compiler",
1828+
"CONFIG",
18261829
),
18271830
opt::opt_s(
18281831
"",
@@ -1918,10 +1921,9 @@ pub fn get_cmd_lint_options(matches: &getopts::Matches,
19181921
(lint_opts, describe_lints, lint_cap)
19191922
}
19201923

1921-
pub fn build_session_options_and_crate_config(
1922-
matches: &getopts::Matches,
1923-
) -> (Options, FxHashSet<(String, Option<String>)>) {
1924-
let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
1924+
/// Parse the `--color` flag
1925+
pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
1926+
match matches.opt_str("color").as_ref().map(|s| &s[..]) {
19251927
Some("auto") => ColorConfig::Auto,
19261928
Some("always") => ColorConfig::Always,
19271929
Some("never") => ColorConfig::Never,
@@ -1936,46 +1938,52 @@ pub fn build_session_options_and_crate_config(
19361938
arg
19371939
),
19381940
),
1939-
};
1941+
}
1942+
}
19401943

1941-
let edition = match matches.opt_str("edition") {
1942-
Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_|
1944+
/// Parse the `--json` flag.
1945+
///
1946+
/// The first value returned is how to render JSON diagnostics, and the second
1947+
/// is whether or not artifact notifications are enabled.
1948+
pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) {
1949+
let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType =
1950+
HumanReadableErrorType::Default;
1951+
let mut json_color = ColorConfig::Never;
1952+
let mut json_artifact_notifications = false;
1953+
for option in matches.opt_strs("json") {
1954+
// For now conservatively forbid `--color` with `--json` since `--json`
1955+
// won't actually be emitting any colors and anything colorized is
1956+
// embedded in a diagnostic message anyway.
1957+
if matches.opt_str("color").is_some() {
19431958
early_error(
19441959
ErrorOutputType::default(),
1945-
&format!(
1946-
"argument for --edition must be one of: \
1947-
{}. (instead was `{}`)",
1948-
EDITION_NAME_LIST,
1949-
arg
1950-
),
1951-
),
1952-
),
1953-
None => DEFAULT_EDITION,
1954-
};
1960+
"cannot specify the `--color` option with `--json`",
1961+
);
1962+
}
19551963

1956-
if !edition.is_stable() && !nightly_options::is_nightly_build() {
1957-
early_error(
1958-
ErrorOutputType::default(),
1959-
&format!(
1960-
"Edition {} is unstable and only \
1961-
available for nightly builds of rustc.",
1962-
edition,
1963-
)
1964-
)
1964+
for sub_option in option.split(',') {
1965+
match sub_option {
1966+
"diagnostic-short" => json_rendered = HumanReadableErrorType::Short,
1967+
"diagnostic-rendered-ansi" => json_color = ColorConfig::Always,
1968+
"artifacts" => json_artifact_notifications = true,
1969+
s => {
1970+
early_error(
1971+
ErrorOutputType::default(),
1972+
&format!("unknown `--json` option `{}`", s),
1973+
)
1974+
}
1975+
}
1976+
}
19651977
}
1978+
(json_rendered(json_color), json_artifact_notifications)
1979+
}
19661980

1967-
let json_rendered = matches.opt_str("json-rendered").and_then(|s| match s.as_str() {
1968-
"plain" => None,
1969-
"termcolor" => Some(HumanReadableErrorType::Default(ColorConfig::Always)),
1970-
_ => early_error(
1971-
ErrorOutputType::default(),
1972-
&format!(
1973-
"argument for --json-rendered must be `plain` or `termcolor` (instead was `{}`)",
1974-
s,
1975-
),
1976-
),
1977-
}).unwrap_or(HumanReadableErrorType::Default(ColorConfig::Never));
1978-
1981+
/// Parse the `--error-format` flag
1982+
pub fn parse_error_format(
1983+
matches: &getopts::Matches,
1984+
color: ColorConfig,
1985+
json_rendered: HumanReadableErrorType,
1986+
) -> ErrorOutputType {
19791987
// We need the opts_present check because the driver will send us Matches
19801988
// with only stable options if no unstable options are used. Since error-format
19811989
// is unstable, it will not be present. We have to use opts_present not
@@ -2004,6 +2012,60 @@ pub fn build_session_options_and_crate_config(
20042012
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
20052013
};
20062014

2015+
match error_format {
2016+
ErrorOutputType::Json { .. } => {}
2017+
2018+
// Conservatively require that the `--json` argument is coupled with
2019+
// `--error-format=json`. This means that `--json` is specified we
2020+
// should actually be emitting JSON blobs.
2021+
_ if matches.opt_strs("json").len() > 0 => {
2022+
early_error(
2023+
ErrorOutputType::default(),
2024+
"using `--json` requires also using `--error-format=json`",
2025+
);
2026+
}
2027+
2028+
_ => {}
2029+
}
2030+
2031+
return error_format;
2032+
}
2033+
2034+
pub fn build_session_options_and_crate_config(
2035+
matches: &getopts::Matches,
2036+
) -> (Options, FxHashSet<(String, Option<String>)>) {
2037+
let color = parse_color(matches);
2038+
2039+
let edition = match matches.opt_str("edition") {
2040+
Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_|
2041+
early_error(
2042+
ErrorOutputType::default(),
2043+
&format!(
2044+
"argument for --edition must be one of: \
2045+
{}. (instead was `{}`)",
2046+
EDITION_NAME_LIST,
2047+
arg
2048+
),
2049+
),
2050+
),
2051+
None => DEFAULT_EDITION,
2052+
};
2053+
2054+
if !edition.is_stable() && !nightly_options::is_nightly_build() {
2055+
early_error(
2056+
ErrorOutputType::default(),
2057+
&format!(
2058+
"Edition {} is unstable and only \
2059+
available for nightly builds of rustc.",
2060+
edition,
2061+
)
2062+
)
2063+
}
2064+
2065+
let (json_rendered, json_artifact_notifications) = parse_json(matches);
2066+
2067+
let error_format = parse_error_format(matches, color, json_rendered);
2068+
20072069
let unparsed_crate_types = matches.opt_strs("crate-type");
20082070
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
20092071
.unwrap_or_else(|e| early_error(error_format, &e[..]));
@@ -2014,9 +2076,6 @@ pub fn build_session_options_and_crate_config(
20142076
let mut debugging_opts = build_debugging_options(matches, error_format);
20152077

20162078
if !debugging_opts.unstable_options {
2017-
if matches.opt_str("json-rendered").is_some() {
2018-
early_error(error_format, "`--json-rendered=x` is unstable");
2019-
}
20202079
if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
20212080
early_error(
20222081
ErrorOutputType::Json { pretty: false, json_rendered },
@@ -2441,6 +2500,7 @@ pub fn build_session_options_and_crate_config(
24412500
cli_forced_thinlto_off: disable_thinlto,
24422501
remap_path_prefix,
24432502
edition,
2503+
json_artifact_notifications,
24442504
},
24452505
cfg,
24462506
)

src/librustc_codegen_ssa/back/link.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
9595
);
9696
}
9797
}
98-
if sess.opts.debugging_opts.emit_artifact_notifications {
98+
if sess.opts.json_artifact_notifications {
9999
sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link");
100100
}
101101
}

src/librustc_interface/passes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ fn write_out_deps(compiler: &Compiler, outputs: &OutputFilenames, out_filenames:
696696

697697
match result {
698698
Ok(_) => {
699-
if sess.opts.debugging_opts.emit_artifact_notifications {
699+
if sess.opts.json_artifact_notifications {
700700
sess.parse_sess.span_diagnostic
701701
.emit_artifact_notification(&deps_filename, "dep-info");
702702
}
@@ -1059,7 +1059,7 @@ fn encode_and_write_metadata(
10591059
if let Err(e) = fs::rename(&metadata_filename, &out_filename) {
10601060
tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
10611061
}
1062-
if tcx.sess.opts.debugging_opts.emit_artifact_notifications {
1062+
if tcx.sess.opts.json_artifact_notifications {
10631063
tcx.sess.parse_sess.span_diagnostic
10641064
.emit_artifact_notification(&out_filename, "metadata");
10651065
}

src/librustc_save_analysis/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,7 @@ impl SaveHandler for DumpHandler<'_> {
10711071
error!("Can't serialize save-analysis: {:?}", e);
10721072
}
10731073

1074-
if sess.opts.debugging_opts.emit_artifact_notifications {
1074+
if sess.opts.json_artifact_notifications {
10751075
sess.parse_sess.span_diagnostic
10761076
.emit_artifact_notification(&file_name, "save-analysis");
10771077
}

src/librustdoc/config.rs

+4-32
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ use std::fmt;
33
use std::path::PathBuf;
44

55
use errors;
6-
use errors::emitter::{ColorConfig, HumanReadableErrorType};
76
use getopts;
87
use rustc::lint::Level;
9-
use rustc::session::early_error;
8+
use rustc::session;
109
use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
1110
use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options,
1211
get_cmd_lint_options, ExternEntry};
@@ -243,36 +242,9 @@ impl Options {
243242
return Err(0);
244243
}
245244

246-
let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
247-
Some("auto") => ColorConfig::Auto,
248-
Some("always") => ColorConfig::Always,
249-
Some("never") => ColorConfig::Never,
250-
None => ColorConfig::Auto,
251-
Some(arg) => {
252-
early_error(ErrorOutputType::default(),
253-
&format!("argument for `--color` must be `auto`, `always` or `never` \
254-
(instead was `{}`)", arg));
255-
}
256-
};
257-
// FIXME: deduplicate this code from the identical code in librustc/session/config.rs
258-
let error_format = match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
259-
None |
260-
Some("human") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
261-
Some("json") => ErrorOutputType::Json {
262-
pretty: false,
263-
json_rendered: HumanReadableErrorType::Default(ColorConfig::Never),
264-
},
265-
Some("pretty-json") => ErrorOutputType::Json {
266-
pretty: true,
267-
json_rendered: HumanReadableErrorType::Default(ColorConfig::Never),
268-
},
269-
Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)),
270-
Some(arg) => {
271-
early_error(ErrorOutputType::default(),
272-
&format!("argument for `--error-format` must be `human`, `json` or \
273-
`short` (instead was `{}`)", arg));
274-
}
275-
};
245+
let color = session::config::parse_color(&matches);
246+
let (json_rendered, _artifacts) = session::config::parse_json(&matches);
247+
let error_format = session::config::parse_error_format(&matches, color, json_rendered);
276248

277249
let codegen_options = build_codegen_options(matches, error_format);
278250
let debugging_options = build_debugging_options(matches, error_format);

src/librustdoc/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ fn opts() -> Vec<RustcOptGroup> {
286286
"How errors and other messages are produced",
287287
"human|json|short")
288288
}),
289+
stable("json", |o| {
290+
o.optopt("",
291+
"json",
292+
"Configure the structure of JSON diagnostics",
293+
"CONFIG")
294+
}),
289295
unstable("disable-minification", |o| {
290296
o.optflag("",
291297
"disable-minification",

src/test/ui/emit-artifact-notifications.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// compile-flags:--emit=metadata --error-format=json -Z emit-artifact-notifications
1+
// compile-flags:--emit=metadata --error-format=json --json artifacts
22
// build-pass (FIXME(62277): could be check-pass?)
33
// ignore-pass
44
// ^-- needed because `--pass check` does not emit the output needed.

src/test/ui/json-and-color.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// build-fail
2+
// compile-flags: --json=artifacts --error-format=json --color never
3+
4+
fn main() {}

src/test/ui/json-and-color.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: cannot specify the `--color` option with `--json`
2+

src/test/ui/json-and-error-format.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// build-fail
2+
// compile-flags: --json=artifacts --error-format=short
3+
4+
fn main() {}
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: using `--json` requires also using `--error-format=json`
2+

src/test/ui/json-invalid.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// build-fail
2+
// compile-flags: --json=foo --error-format=json
3+
4+
fn main() {}

0 commit comments

Comments
 (0)