Skip to content

Commit 1731233

Browse files
committed
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
1 parent 1a56336 commit 1731233

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
}
@@ -1463,8 +1468,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
14631468
the same values as the target option of the same name"),
14641469
allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
14651470
"only allow the listed language features to be enabled in code (space separated)"),
1466-
emit_artifact_notifications: bool = (false, parse_bool, [UNTRACKED],
1467-
"emit notifications after each artifact has been output (only in the JSON format)"),
14681471
symbol_mangling_version: SymbolManglingVersion = (SymbolManglingVersion::Legacy,
14691472
parse_symbol_mangling_version, [TRACKED],
14701473
"which mangling version to use for symbol names"),
@@ -1822,11 +1825,11 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
18221825
"How errors and other messages are produced",
18231826
"human|json|short",
18241827
),
1825-
opt::opt(
1828+
opt::multi_s(
18261829
"",
1827-
"json-rendered",
1828-
"Choose `rendered` field of json diagnostics render scheme",
1829-
"plain|termcolor",
1830+
"json",
1831+
"Configure the JSON output of the compiler",
1832+
"CONFIG",
18301833
),
18311834
opt::opt_s(
18321835
"",
@@ -1922,10 +1925,9 @@ pub fn get_cmd_lint_options(matches: &getopts::Matches,
19221925
(lint_opts, describe_lints, lint_cap)
19231926
}
19241927

1925-
pub fn build_session_options_and_crate_config(
1926-
matches: &getopts::Matches,
1927-
) -> (Options, FxHashSet<(String, Option<String>)>) {
1928-
let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
1928+
/// Parse the `--color` flag
1929+
pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
1930+
match matches.opt_str("color").as_ref().map(|s| &s[..]) {
19291931
Some("auto") => ColorConfig::Auto,
19301932
Some("always") => ColorConfig::Always,
19311933
Some("never") => ColorConfig::Never,
@@ -1940,46 +1942,52 @@ pub fn build_session_options_and_crate_config(
19401942
arg
19411943
),
19421944
),
1943-
};
1945+
}
1946+
}
19441947

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

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

1971-
let json_rendered = matches.opt_str("json-rendered").and_then(|s| match s.as_str() {
1972-
"plain" => None,
1973-
"termcolor" => Some(HumanReadableErrorType::Default(ColorConfig::Always)),
1974-
_ => early_error(
1975-
ErrorOutputType::default(),
1976-
&format!(
1977-
"argument for --json-rendered must be `plain` or `termcolor` (instead was `{}`)",
1978-
s,
1979-
),
1980-
),
1981-
}).unwrap_or(HumanReadableErrorType::Default(ColorConfig::Never));
1982-
1985+
/// Parse the `--error-format` flag
1986+
pub fn parse_error_format(
1987+
matches: &getopts::Matches,
1988+
color: ColorConfig,
1989+
json_rendered: HumanReadableErrorType,
1990+
) -> ErrorOutputType {
19831991
// We need the opts_present check because the driver will send us Matches
19841992
// with only stable options if no unstable options are used. Since error-format
19851993
// is unstable, it will not be present. We have to use opts_present not
@@ -2008,6 +2016,60 @@ pub fn build_session_options_and_crate_config(
20082016
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
20092017
};
20102018

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

20202082
if !debugging_opts.unstable_options {
2021-
if matches.opt_str("json-rendered").is_some() {
2022-
early_error(error_format, "`--json-rendered=x` is unstable");
2023-
}
20242083
if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
20252084
early_error(
20262085
ErrorOutputType::Json { pretty: false, json_rendered },
@@ -2445,6 +2504,7 @@ pub fn build_session_options_and_crate_config(
24452504
cli_forced_thinlto_off: disable_thinlto,
24462505
remap_path_prefix,
24472506
edition,
2507+
json_artifact_notifications,
24482508
},
24492509
cfg,
24502510
)

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
@@ -1087,7 +1087,7 @@ impl<'a> SaveHandler for DumpHandler<'a> {
10871087
file_name
10881088
};
10891089

1090-
if sess.opts.debugging_opts.emit_artifact_notifications {
1090+
if sess.opts.json_artifact_notifications {
10911091
sess.parse_sess.span_diagnostic
10921092
.emit_artifact_notification(&file_name, "save-analysis");
10931093
}

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
@@ -289,6 +289,12 @@ fn opts() -> Vec<RustcOptGroup> {
289289
"How errors and other messages are produced",
290290
"human|json|short")
291291
}),
292+
stable("json", |o| {
293+
o.optopt("",
294+
"json",
295+
"Configure the structure of JSON diagnostics",
296+
"CONFIG")
297+
}),
292298
unstable("disable-minification", |o| {
293299
o.optflag("",
294300
"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)