Skip to content

Commit fd9fad6

Browse files
committed
Auto merge of #140869 - matthiaskrgr:rollup-r5k19w6, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #139863 (rustdoc: Replace unstable flag `--doctest-compilation-args` with a simpler one: `--doctest-build-arg`) - #140815 (also export metrics from librustdoc) - #140819 (Add regression test for 125877) - #140843 (Fix `broken-pipe-no-ice` run-make test for rpath-less builds) - #140848 (Improved error message for top-level or-patterns) - #140852 (Update the edition guide for let chains) - #140864 (Last minute relnotes fix) r? `@ghost` `@rustbot` modify labels: rollup
2 parents dcecb99 + 505e78a commit fd9fad6

29 files changed

+217
-189
lines changed

RELEASES.md

+76-76
Large diffs are not rendered by default.

compiler/rustc_parse/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -690,8 +690,8 @@ parse_nul_in_c_str = null characters in C string literals are not supported
690690
691691
parse_or_in_let_chain = `||` operators are not supported in let chain conditions
692692
693-
parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
694-
parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
693+
parse_or_pattern_not_allowed_in_fn_parameters = function parameters require top-level or-patterns in parentheses
694+
parse_or_pattern_not_allowed_in_let_binding = `let` bindings require top-level or-patterns in parentheses
695695
parse_out_of_range_hex_escape = out of range hex escape
696696
.label = must be a character in the range [\x00-\x7f]
697697

src/librustdoc/config.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ pub(crate) struct Options {
174174
pub(crate) expanded_args: Vec<String>,
175175

176176
/// Arguments to be used when compiling doctests.
177-
pub(crate) doctest_compilation_args: Vec<String>,
177+
pub(crate) doctest_build_args: Vec<String>,
178178
}
179179

180180
impl fmt::Debug for Options {
@@ -802,7 +802,7 @@ impl Options {
802802
let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
803803
let with_examples = matches.opt_strs("with-examples");
804804
let call_locations = crate::scrape_examples::load_call_locations(with_examples, dcx);
805-
let doctest_compilation_args = matches.opt_strs("doctest-compilation-args");
805+
let doctest_build_args = matches.opt_strs("doctest-build-arg");
806806

807807
let unstable_features =
808808
rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
@@ -851,7 +851,7 @@ impl Options {
851851
scrape_examples_options,
852852
unstable_features,
853853
expanded_args: args,
854-
doctest_compilation_args,
854+
doctest_build_args,
855855
};
856856
let render_options = RenderOptions {
857857
output,

src/librustdoc/doctest.rs

+1-43
Original file line numberDiff line numberDiff line change
@@ -51,46 +51,6 @@ pub(crate) struct GlobalTestOptions {
5151
pub(crate) args_file: PathBuf,
5252
}
5353

54-
/// Function used to split command line arguments just like a shell would.
55-
fn split_args(args: &str) -> Vec<String> {
56-
let mut out = Vec::new();
57-
let mut iter = args.chars();
58-
let mut current = String::new();
59-
60-
while let Some(c) = iter.next() {
61-
if c == '\\' {
62-
if let Some(c) = iter.next() {
63-
// If it's escaped, even a quote or a whitespace will be ignored.
64-
current.push(c);
65-
}
66-
} else if c == '"' || c == '\'' {
67-
while let Some(new_c) = iter.next() {
68-
if new_c == c {
69-
break;
70-
} else if new_c == '\\' {
71-
if let Some(c) = iter.next() {
72-
// If it's escaped, even a quote will be ignored.
73-
current.push(c);
74-
}
75-
} else {
76-
current.push(new_c);
77-
}
78-
}
79-
} else if " \n\t\r".contains(c) {
80-
if !current.is_empty() {
81-
out.push(current.clone());
82-
current.clear();
83-
}
84-
} else {
85-
current.push(c);
86-
}
87-
}
88-
if !current.is_empty() {
89-
out.push(current);
90-
}
91-
out
92-
}
93-
9454
pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) -> Result<(), String> {
9555
let mut file = File::create(file_path)
9656
.map_err(|error| format!("failed to create args file: {error:?}"))?;
@@ -119,9 +79,7 @@ pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) ->
11979
content.push(format!("-Z{unstable_option_str}"));
12080
}
12181

122-
for compilation_args in &options.doctest_compilation_args {
123-
content.extend(split_args(compilation_args));
124-
}
82+
content.extend(options.doctest_build_args.clone());
12583

12684
let content = content.join("\n");
12785

src/librustdoc/doctest/tests.rs

-22
Original file line numberDiff line numberDiff line change
@@ -381,28 +381,6 @@ fn main() {
381381
assert_eq!((output, len), (expected, 1));
382382
}
383383

384-
#[test]
385-
fn check_split_args() {
386-
fn compare(input: &str, expected: &[&str]) {
387-
let output = super::split_args(input);
388-
let expected = expected.iter().map(|s| s.to_string()).collect::<Vec<_>>();
389-
assert_eq!(expected, output, "test failed for {input:?}");
390-
}
391-
392-
compare("'a' \"b\"c", &["a", "bc"]);
393-
compare("'a' \"b \"c d", &["a", "b c", "d"]);
394-
compare("'a' \"b\\\"c\"", &["a", "b\"c"]);
395-
compare("'a\"'", &["a\""]);
396-
compare("\"a'\"", &["a'"]);
397-
compare("\\ a", &[" a"]);
398-
compare("\\\\", &["\\"]);
399-
compare("a'", &["a"]);
400-
compare("a ", &["a"]);
401-
compare("a b", &["a", "b"]);
402-
compare("a\n\t \rb", &["a", "b"]);
403-
compare("a\n\t1 \rb", &["a", "1", "b"]);
404-
}
405-
406384
#[test]
407385
fn comment_in_attrs() {
408386
// If there is an inline code comment after attributes, we need to ensure that

src/librustdoc/lib.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,11 @@ extern crate tikv_jemalloc_sys as jemalloc_sys;
7373

7474
use std::env::{self, VarError};
7575
use std::io::{self, IsTerminal};
76+
use std::path::Path;
7677
use std::process;
7778

7879
use rustc_errors::DiagCtxtHandle;
80+
use rustc_hir::def_id::LOCAL_CRATE;
7981
use rustc_interface::interface;
8082
use rustc_middle::ty::TyCtxt;
8183
use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option};
@@ -654,9 +656,9 @@ fn opts() -> Vec<RustcOptGroup> {
654656
Unstable,
655657
Multi,
656658
"",
657-
"doctest-compilation-args",
658-
"",
659-
"add arguments to be used when compiling doctests",
659+
"doctest-build-arg",
660+
"One argument (of possibly many) to be used when compiling doctests",
661+
"ARG",
660662
),
661663
opt(
662664
Unstable,
@@ -904,6 +906,10 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
904906
rustc_interface::passes::write_dep_info(tcx);
905907
}
906908

909+
if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir {
910+
dump_feature_usage_metrics(tcx, metrics_dir);
911+
}
912+
907913
if run_check {
908914
// Since we're in "check" mode, no need to generate anything beyond this point.
909915
return;
@@ -923,3 +929,16 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
923929
})
924930
})
925931
}
932+
933+
fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) {
934+
let hash = tcxt.crate_hash(LOCAL_CRATE);
935+
let crate_name = tcxt.crate_name(LOCAL_CRATE);
936+
let metrics_file_name = format!("unstable_feature_usage_metrics-{crate_name}-{hash}.json");
937+
let metrics_path = metrics_dir.join(metrics_file_name);
938+
if let Err(error) = tcxt.features().dump_feature_usage_metrics(metrics_path) {
939+
// FIXME(yaahc): once metrics can be enabled by default we will want "failure to emit
940+
// default metrics" to only produce a warning when metrics are enabled by default and emit
941+
// an error only when the user manually enables metrics
942+
tcxt.dcx().err(format!("cannot emit feature usage metrics: {error}"));
943+
}
944+
}

src/tools/run-make-support/src/command.rs

+6
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ impl Command {
6363
}
6464
}
6565

66+
// Internal-only.
67+
pub(crate) fn into_raw_command(mut self) -> std::process::Command {
68+
self.drop_bomb.defuse();
69+
self.cmd
70+
}
71+
6672
/// Specify a stdin input buffer. This is a convenience helper,
6773
pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
6874
self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice());

src/tools/run-make-support/src/external_deps/rustdoc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::command::Command;
55
use crate::env::env_var;
66
use crate::util::set_host_compiler_dylib_path;
77

8-
/// Construct a new `rustdoc` invocation.
8+
/// Construct a new `rustdoc` invocation. This will configure the host compiler runtime libs.
99
#[track_caller]
1010
pub fn rustdoc() -> Rustdoc {
1111
Rustdoc::new()
@@ -28,7 +28,7 @@ fn setup_common() -> Command {
2828
}
2929

3030
impl Rustdoc {
31-
/// Construct a bare `rustdoc` invocation.
31+
/// Construct a bare `rustdoc` invocation. This will configure the host compiler runtime libs.
3232
#[track_caller]
3333
pub fn new() -> Self {
3434
let cmd = setup_common();

src/tools/run-make-support/src/macros.rs

+12
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@
2828
macro_rules! impl_common_helpers {
2929
($wrapper: ident) => {
3030
impl $wrapper {
31+
/// In very rare circumstances, you may need a e.g. `bare_rustc()` or `bare_rustdoc()`
32+
/// with host runtime libs configured, but want the underlying raw
33+
/// [`std::process::Command`] (e.g. for manipulating pipes or whatever). This function
34+
/// will consume the command wrapper and extract the underlying
35+
/// [`std::process::Command`].
36+
///
37+
/// Caution: this will mean that you can no longer use the convenience methods on the
38+
/// command wrapper. Use as a last resort.
39+
pub fn into_raw_command(self) -> ::std::process::Command {
40+
self.cmd.into_raw_command()
41+
}
42+
3143
/// Specify an environment variable.
3244
pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Self
3345
where

tests/run-make/broken-pipe-no-ice/rmake.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use std::io::Read;
1515
use std::process::{Command, Stdio};
1616

17-
use run_make_support::env_var;
17+
use run_make_support::{bare_rustc, rustdoc};
1818

1919
#[derive(Debug, PartialEq)]
2020
enum Binary {
@@ -67,11 +67,13 @@ fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) {
6767
}
6868

6969
fn main() {
70-
let mut rustc = Command::new(env_var("RUSTC"));
70+
let mut rustc = bare_rustc();
7171
rustc.arg("--print=sysroot");
72+
let rustc = rustc.into_raw_command();
7273
check_broken_pipe_handled_gracefully(Binary::Rustc, rustc);
7374

74-
let mut rustdoc = Command::new(env_var("RUSTDOC"));
75+
let mut rustdoc = rustdoc();
7576
rustdoc.arg("--version");
77+
let rustdoc = rustdoc.into_raw_command();
7678
check_broken_pipe_handled_gracefully(Binary::Rustdoc, rustdoc);
7779
}

tests/run-make/rustdoc-default-output/output-default.stdout

+3-2
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,9 @@ Options:
188188
from provided path. Only use with --merge=finalize
189189
--html-no-source
190190
Disable HTML source code pages generation
191-
--doctest-compilation-args add arguments to be used when compiling doctests
192-
191+
--doctest-build-arg ARG
192+
One argument (of possibly many) to be used when
193+
compiling doctests
193194
--disable-minification
194195
disable the minification of CSS/JS files
195196
(perma-unstable, do not use with cached files)

tests/rustdoc-ui/doctest/rustflags-multiple-args.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
// This test checks that the test behave when `--doctest-compilation-args` is passed
2-
// multiple times.
1+
// This test checks that the test behave when `--doctest-build-arg` is passed multiple times.
32

43
//@ check-pass
5-
//@ compile-flags: --test -Zunstable-options --doctest-compilation-args=--cfg=testcase_must_be_present
6-
//@ compile-flags: --doctest-compilation-args=--cfg=another
4+
//@ compile-flags: --test -Zunstable-options --doctest-build-arg=--cfg=testcase_must_be_present
5+
//@ compile-flags: --doctest-build-arg=--cfg=another
76
//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
87
//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
98

Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
running 1 test
3-
test $DIR/rustflags-multiple-args.rs - Bar (line 10) ... ok
3+
test $DIR/rustflags-multiple-args.rs - Bar (line 9) ... ok
44

55
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
66

tests/rustdoc-ui/doctest/rustflags.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//@ check-pass
2-
//@ compile-flags: --test -Zunstable-options --doctest-compilation-args=--cfg=testcase_must_be_present
2+
//@ compile-flags: --test -Zunstable-options --doctest-build-arg=--cfg=testcase_must_be_present
33
//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
44
//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
55

tests/ui/or-patterns/fn-param-wrap-parens.fixed

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ enum E { A, B }
1010
use E::*;
1111

1212
#[cfg(false)]
13-
fn fun1((A | B): E) {} //~ ERROR top-level or-patterns are not allowed
13+
fn fun1((A | B): E) {} //~ ERROR function parameters require top-level or-patterns in parentheses

tests/ui/or-patterns/fn-param-wrap-parens.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ enum E { A, B }
1010
use E::*;
1111

1212
#[cfg(false)]
13-
fn fun1(A | B: E) {} //~ ERROR top-level or-patterns are not allowed
13+
fn fun1(A | B: E) {} //~ ERROR function parameters require top-level or-patterns in parentheses

tests/ui/or-patterns/fn-param-wrap-parens.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: top-level or-patterns are not allowed in function parameters
1+
error: function parameters require top-level or-patterns in parentheses
22
--> $DIR/fn-param-wrap-parens.rs:13:9
33
|
44
LL | fn fun1(A | B: E) {}

tests/ui/or-patterns/nested-undelimited-precedence.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn foo() {
1717
let b @ (A | B): E = A;
1818

1919
let b @ A | B: E = A; //~ERROR `b` is not bound in all patterns
20-
//~^ ERROR top-level or-patterns are not allowed
20+
//~^ ERROR `let` bindings require top-level or-patterns in parentheses
2121
}
2222

2323
enum F {
@@ -32,13 +32,13 @@ fn bar() {
3232
let (A(x) | B(x)): F = A(3);
3333

3434
let &A(_) | B(_): F = A(3); //~ERROR mismatched types
35-
//~^ ERROR top-level or-patterns are not allowed
35+
//~^ ERROR `let` bindings require top-level or-patterns in parentheses
3636
let &&A(_) | B(_): F = A(3); //~ERROR mismatched types
37-
//~^ ERROR top-level or-patterns are not allowed
37+
//~^ ERROR `let` bindings require top-level or-patterns in parentheses
3838
let &mut A(_) | B(_): F = A(3); //~ERROR mismatched types
39-
//~^ ERROR top-level or-patterns are not allowed
39+
//~^ ERROR `let` bindings require top-level or-patterns in parentheses
4040
let &&mut A(_) | B(_): F = A(3); //~ERROR mismatched types
41-
//~^ ERROR top-level or-patterns are not allowed
41+
//~^ ERROR `let` bindings require top-level or-patterns in parentheses
4242
}
4343

4444
fn main() {}

tests/ui/or-patterns/nested-undelimited-precedence.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: top-level or-patterns are not allowed in `let` bindings
1+
error: `let` bindings require top-level or-patterns in parentheses
22
--> $DIR/nested-undelimited-precedence.rs:19:9
33
|
44
LL | let b @ A | B: E = A;
@@ -9,7 +9,7 @@ help: wrap the pattern in parentheses
99
LL | let (b @ A | B): E = A;
1010
| + +
1111

12-
error: top-level or-patterns are not allowed in `let` bindings
12+
error: `let` bindings require top-level or-patterns in parentheses
1313
--> $DIR/nested-undelimited-precedence.rs:34:9
1414
|
1515
LL | let &A(_) | B(_): F = A(3);
@@ -20,7 +20,7 @@ help: wrap the pattern in parentheses
2020
LL | let (&A(_) | B(_)): F = A(3);
2121
| + +
2222

23-
error: top-level or-patterns are not allowed in `let` bindings
23+
error: `let` bindings require top-level or-patterns in parentheses
2424
--> $DIR/nested-undelimited-precedence.rs:36:9
2525
|
2626
LL | let &&A(_) | B(_): F = A(3);
@@ -31,7 +31,7 @@ help: wrap the pattern in parentheses
3131
LL | let (&&A(_) | B(_)): F = A(3);
3232
| + +
3333

34-
error: top-level or-patterns are not allowed in `let` bindings
34+
error: `let` bindings require top-level or-patterns in parentheses
3535
--> $DIR/nested-undelimited-precedence.rs:38:9
3636
|
3737
LL | let &mut A(_) | B(_): F = A(3);
@@ -42,7 +42,7 @@ help: wrap the pattern in parentheses
4242
LL | let (&mut A(_) | B(_)): F = A(3);
4343
| + +
4444

45-
error: top-level or-patterns are not allowed in `let` bindings
45+
error: `let` bindings require top-level or-patterns in parentheses
4646
--> $DIR/nested-undelimited-precedence.rs:40:9
4747
|
4848
LL | let &&mut A(_) | B(_): F = A(3);

0 commit comments

Comments
 (0)