From 0340a865b9e7a3aa17a69555f0cc22ba3ad92c73 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 15 Feb 2025 09:19:17 -0800 Subject: [PATCH 01/17] Add test for doctest runtool --- .../doctest/auxiliary/doctest-runtool.rs | 21 +++++++++++++++++++ tests/rustdoc/doctest/doctest-runtool.rs | 14 +++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/rustdoc/doctest/auxiliary/doctest-runtool.rs create mode 100644 tests/rustdoc/doctest/doctest-runtool.rs diff --git a/tests/rustdoc/doctest/auxiliary/doctest-runtool.rs b/tests/rustdoc/doctest/auxiliary/doctest-runtool.rs new file mode 100644 index 0000000000000..a21ae0664fe63 --- /dev/null +++ b/tests/rustdoc/doctest/auxiliary/doctest-runtool.rs @@ -0,0 +1,21 @@ +// For some reason on Windows, the PATH to the libstd dylib doesn't seem to +// carry over to running the runtool. +//@ no-prefer-dynamic + +use std::path::Path; +use std::process::Command; + +fn main() { + let args: Vec<_> = std::env::args().collect(); + eprintln!("{args:#?}"); + assert_eq!(args.len(), 4); + assert_eq!(args[1], "arg1"); + assert_eq!(args[2], "arg2 with space"); + let path = Path::new(&args[3]); + let output = Command::new(path).output().unwrap(); + // Should fail without env var. + assert!(!output.status.success()); + let output = Command::new(path).env("DOCTEST_RUNTOOL_CHECK", "xyz").output().unwrap(); + // Should pass with env var. + assert!(output.status.success()); +} diff --git a/tests/rustdoc/doctest/doctest-runtool.rs b/tests/rustdoc/doctest/doctest-runtool.rs new file mode 100644 index 0000000000000..f54dc06fb203a --- /dev/null +++ b/tests/rustdoc/doctest/doctest-runtool.rs @@ -0,0 +1,14 @@ +// Tests that the --runtool argument works. + +//@ ignore-cross-compile +//@ aux-bin: doctest-runtool.rs +//@ compile-flags: --test +//@ compile-flags: --runtool=auxiliary/bin/doctest-runtool +//@ compile-flags: --runtool-arg=arg1 --runtool-arg +//@ compile-flags: 'arg2 with space' +//@ compile-flags: -Zunstable-options + +/// ``` +/// assert_eq!(std::env::var("DOCTEST_RUNTOOL_CHECK"), Ok("xyz".to_string())); +/// ``` +pub fn main() {} From ec25e3300b930b9d2873fe589ed3cbfa55db3ffe Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 15 Feb 2025 10:50:47 -0800 Subject: [PATCH 02/17] Rename `--runtool` and `--runtool-arg` This renames `--runtool` and `--runtool-arg` to `--test-runtool` and `--test-runtool-arg` to maintain consistency with other `--test-*` arguments. --- src/doc/rustdoc/src/unstable-features.md | 6 +++--- src/librustdoc/config.rs | 16 ++++++++-------- src/librustdoc/doctest.rs | 4 ++-- src/librustdoc/lib.rs | 4 ++-- src/tools/miri/cargo-miri/src/main.rs | 2 +- src/tools/miri/cargo-miri/src/phases.rs | 10 +++++----- tests/run-make/doctests-runtool/rmake.rs | 6 +++--- .../rustdoc-default-output/output-default.stdout | 4 ++-- tests/rustdoc/doctest/doctest-runtool.rs | 6 +++--- 9 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index d4ff69a99338b..144f1c61b34b1 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -666,21 +666,21 @@ struct Foo; In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will override `ignore`. -## `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it +## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) Using these options looks like this: ```bash -$ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing +$ rustdoc src/lib.rs -Z unstable-options --test-runtool runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing ``` These options can be used to run the doctest under a program, and also pass arguments to that program. For example, if you want to run your doctests under valgrind you might run ```bash -$ rustdoc src/lib.rs -Z unstable-options --runtool valgrind +$ rustdoc src/lib.rs -Z unstable-options --test-runtool valgrind ``` Another use case would be to run a test inside an emulator, or through a Virtual Machine. diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 23a2bcd9011ee..0eb620c01d9b8 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -124,9 +124,9 @@ pub(crate) struct Options { /// temporary directory if not set. pub(crate) persist_doctests: Option, /// Runtool to run doctests with - pub(crate) runtool: Option, + pub(crate) test_runtool: Option, /// Arguments to pass to the runtool - pub(crate) runtool_args: Vec, + pub(crate) test_runtool_args: Vec, /// Whether to allow ignoring doctests on a per-target basis /// For example, using ignore-foo to ignore running the doctest on any target that /// contains "foo" as a substring @@ -215,8 +215,8 @@ impl fmt::Debug for Options { .field("persist_doctests", &self.persist_doctests) .field("show_coverage", &self.show_coverage) .field("crate_version", &self.crate_version) - .field("runtool", &self.runtool) - .field("runtool_args", &self.runtool_args) + .field("test_runtool", &self.test_runtool) + .field("test_runtool_args", &self.test_runtool_args) .field("enable-per-target-ignores", &self.enable_per_target_ignores) .field("run_check", &self.run_check) .field("no_run", &self.no_run) @@ -779,8 +779,8 @@ impl Options { let unstable_opts_strs = matches.opt_strs("Z"); let lib_strs = matches.opt_strs("L"); let extern_strs = matches.opt_strs("extern"); - let runtool = matches.opt_str("runtool"); - let runtool_args = matches.opt_strs("runtool-arg"); + let test_runtool = matches.opt_str("test-runtool"); + let test_runtool_args = matches.opt_strs("test-runtool-arg"); let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores"); let document_private = matches.opt_present("document-private-items"); let document_hidden = matches.opt_present("document-hidden-items"); @@ -843,8 +843,8 @@ impl Options { crate_version, test_run_directory, persist_doctests, - runtool, - runtool_args, + test_runtool, + test_runtool_args, enable_per_target_ignores, test_builder, run_check, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a2808bddb3acc..ae4863dd82b86 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -781,10 +781,10 @@ fn run_test( let mut cmd; let output_file = make_maybe_absolute_path(output_file); - if let Some(tool) = &rustdoc_options.runtool { + if let Some(tool) = &rustdoc_options.test_runtool { let tool = make_maybe_absolute_path(tool.into()); cmd = Command::new(tool); - cmd.args(&rustdoc_options.runtool_args); + cmd.args(&rustdoc_options.test_runtool_args); cmd.arg(&output_file); } else { cmd = Command::new(&output_file); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4fe5e13c3afe0..daa8e72edb82f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -518,7 +518,7 @@ fn opts() -> Vec { Unstable, Opt, "", - "runtool", + "test-runtool", "", "The tool to run tests with when building for a different target than host", ), @@ -526,7 +526,7 @@ fn opts() -> Vec { Unstable, Multi, "", - "runtool-arg", + "test-runtool-arg", "", "One (of possibly many) arguments to pass to the runtool", ), diff --git a/src/tools/miri/cargo-miri/src/main.rs b/src/tools/miri/cargo-miri/src/main.rs index 7d9f77f3752d9..322ef0a6c2aa8 100644 --- a/src/tools/miri/cargo-miri/src/main.rs +++ b/src/tools/miri/cargo-miri/src/main.rs @@ -53,7 +53,7 @@ fn main() { // with `RustcPhase::Rustdoc`. There we perform a check-build (needed to get the expected // build failures for `compile_fail` doctests) and then store a JSON file with the // information needed to run this test. - // - We also set `--runtool` to ourselves, which ends up in `phase_runner` with + // - We also set `--test-runtool` to ourselves, which ends up in `phase_runner` with // `RunnerPhase::Rustdoc`. There we parse the JSON file written in `phase_rustc` and invoke // the Miri driver for interpretation. diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index d7b4421061c6b..477e82f21a29d 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -666,8 +666,8 @@ pub fn phase_rustdoc(mut args: impl Iterator) { if arg == "--extern" { // Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files. forward_patched_extern_arg(&mut args, &mut cmd); - } else if arg == "--runtool" { - // An existing --runtool flag indicates cargo is running in cross-target mode, which we don't support. + } else if arg == "--test-runtool" { + // An existing --test-runtool flag indicates cargo is running in cross-target mode, which we don't support. // Note that this is only passed when cargo is run with the unstable -Zdoctest-xcompile flag; // otherwise, we won't be called as rustdoc at all. show_error!("cross-interpreting doctests is not currently supported by Miri."); @@ -693,8 +693,8 @@ pub fn phase_rustdoc(mut args: impl Iterator) { // to let phase_cargo_rustc know to expect that. We'll use this environment variable as a flag: cmd.env("MIRI_CALLED_FROM_RUSTDOC", "1"); - // The `--test-builder` and `--runtool` arguments are unstable rustdoc features, - // which are disabled by default. We first need to enable them explicitly: + // The `--test-builder` is an unstable rustdoc features, + // which is disabled by default. We first need to enable them explicitly: cmd.arg("-Zunstable-options"); // rustdoc needs to know the right sysroot. @@ -705,7 +705,7 @@ pub fn phase_rustdoc(mut args: impl Iterator) { // Make rustdoc call us back. let cargo_miri_path = env::current_exe().expect("current executable path invalid"); cmd.arg("--test-builder").arg(&cargo_miri_path); // invoked by forwarding most arguments - cmd.arg("--runtool").arg(&cargo_miri_path); // invoked with just a single path argument + cmd.arg("--test-runtool").arg(&cargo_miri_path); // invoked with just a single path argument debug_cmd("[cargo-miri rustdoc]", verbose, &cmd); exec(cmd) diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs index c7be829c215e1..817001c514b52 100644 --- a/tests/run-make/doctests-runtool/rmake.rs +++ b/tests/run-make/doctests-runtool/rmake.rs @@ -1,4 +1,4 @@ -// Tests behavior of rustdoc `--runtool`. +// Tests behavior of rustdoc `--test-runtool`. use std::path::PathBuf; @@ -11,7 +11,7 @@ fn mkdir(name: &str) -> PathBuf { dir } -// Behavior with --runtool with relative paths and --test-run-directory. +// Behavior with --test-runtool with relative paths and --test-run-directory. fn main() { let run_dir_name = "rundir"; let run_dir = mkdir(run_dir_name); @@ -27,7 +27,7 @@ fn main() { .arg("--test") .arg("--test-run-directory") .arg(run_dir_name) - .arg("--runtool") + .arg("--test-runtool") .arg(&run_tool_binary) .extern_("t", "libt.rlib") .run(); diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index 01f470f6e162b..b0ca5f3bf0807 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -141,9 +141,9 @@ Options: --enable-per-target-ignores parse ignore-foo for ignoring doctests on a per-target basis - --runtool The tool to run tests with when building for a different target than host + --test-runtool The tool to run tests with when building for a different target than host - --runtool-arg One (of possibly many) arguments to pass to the runtool + --test-runtool-arg One (of possibly many) arguments to pass to the runtool --test-builder PATH The rustc-like binary to use as the test builder diff --git a/tests/rustdoc/doctest/doctest-runtool.rs b/tests/rustdoc/doctest/doctest-runtool.rs index f54dc06fb203a..75568fab83e75 100644 --- a/tests/rustdoc/doctest/doctest-runtool.rs +++ b/tests/rustdoc/doctest/doctest-runtool.rs @@ -1,10 +1,10 @@ -// Tests that the --runtool argument works. +// Tests that the --test-runtool argument works. //@ ignore-cross-compile //@ aux-bin: doctest-runtool.rs //@ compile-flags: --test -//@ compile-flags: --runtool=auxiliary/bin/doctest-runtool -//@ compile-flags: --runtool-arg=arg1 --runtool-arg +//@ compile-flags: --test-runtool=auxiliary/bin/doctest-runtool +//@ compile-flags: --test-runtool-arg=arg1 --test-runtool-arg //@ compile-flags: 'arg2 with space' //@ compile-flags: -Zunstable-options From 6441701e5ce9c779aea5a121f9b314bfeb971a85 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 15 Feb 2025 10:56:49 -0800 Subject: [PATCH 03/17] Stabilize --test-runtool and --test-runtool-arg --- src/doc/rustdoc/src/command-line-arguments.md | 17 +++++++++++++++++ src/doc/rustdoc/src/unstable-features.md | 19 ------------------- src/librustdoc/lib.rs | 4 ++-- tests/rustdoc/doctest/doctest-runtool.rs | 1 - 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 872592d669d6d..ac5c7f5b6596f 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -222,6 +222,23 @@ For more, see [the chapter on documentation tests](write-documentation/documenta See also `--test`. +## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it + +Using these options looks like this: + +```bash +$ rustdoc src/lib.rs --test-runtool runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing +``` + +These options can be used to run the doctest under a program, and also pass arguments to +that program. For example, if you want to run your doctests under valgrind you might run + +```bash +$ rustdoc src/lib.rs --test-runtool valgrind +``` + +Another use case would be to run a test inside an emulator, or through a Virtual Machine. + ## `--target`: generate documentation for the specified target triple Using this flag looks like this: diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 144f1c61b34b1..8d56fc86f9453 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -666,25 +666,6 @@ struct Foo; In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will override `ignore`. -## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it - - * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) - -Using these options looks like this: - -```bash -$ rustdoc src/lib.rs -Z unstable-options --test-runtool runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing -``` - -These options can be used to run the doctest under a program, and also pass arguments to -that program. For example, if you want to run your doctests under valgrind you might run - -```bash -$ rustdoc src/lib.rs -Z unstable-options --test-runtool valgrind -``` - -Another use case would be to run a test inside an emulator, or through a Virtual Machine. - ## `--with-examples`: include examples of uses of items as documentation * Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index daa8e72edb82f..c51debdfd40e8 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -515,7 +515,7 @@ fn opts() -> Vec { "", ), opt( - Unstable, + Stable, Opt, "", "test-runtool", @@ -523,7 +523,7 @@ fn opts() -> Vec { "The tool to run tests with when building for a different target than host", ), opt( - Unstable, + Stable, Multi, "", "test-runtool-arg", diff --git a/tests/rustdoc/doctest/doctest-runtool.rs b/tests/rustdoc/doctest/doctest-runtool.rs index 75568fab83e75..c4fb02e5228cc 100644 --- a/tests/rustdoc/doctest/doctest-runtool.rs +++ b/tests/rustdoc/doctest/doctest-runtool.rs @@ -6,7 +6,6 @@ //@ compile-flags: --test-runtool=auxiliary/bin/doctest-runtool //@ compile-flags: --test-runtool-arg=arg1 --test-runtool-arg //@ compile-flags: 'arg2 with space' -//@ compile-flags: -Zunstable-options /// ``` /// assert_eq!(std::env::var("DOCTEST_RUNTOOL_CHECK"), Ok("xyz".to_string())); From 7251b466a4d4dd164db1b818681af1c8cf9a3e22 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 15 Feb 2025 11:18:29 -0800 Subject: [PATCH 04/17] Remove and stabilize --enable-per-target-ignores This removes the `--enable-per-target-ignores` and enables it unconditionally. --- src/doc/rustdoc/src/unstable-features.md | 35 ------------------- .../documentation-tests.md | 28 +++++++++++++++ src/librustdoc/config.rs | 7 ---- src/librustdoc/doctest.rs | 2 -- src/librustdoc/doctest/markdown.rs | 8 +---- src/librustdoc/doctest/rust.rs | 6 ++-- src/librustdoc/html/markdown.rs | 30 +++++----------- src/librustdoc/html/markdown/tests.rs | 4 +-- src/librustdoc/lib.rs | 8 ----- .../passes/calculate_doc_coverage.rs | 2 +- .../passes/check_doc_test_visibility.rs | 2 +- .../output-default.stdout | 3 -- 12 files changed, 43 insertions(+), 92 deletions(-) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 8d56fc86f9453..69e5a5adbec29 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -631,41 +631,6 @@ The generated output (formatted) will look like this: `--output-format html` has no effect, as the default output is HTML. This is accepted on stable, even though the other options for this flag aren't. -## `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests - - * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) - -Using this flag looks like this: - -```bash -$ rustdoc src/lib.rs -Z unstable-options --enable-per-target-ignores -``` - -This flag allows you to tag doctests with compiletest style `ignore-foo` filters that prevent -rustdoc from running that test if the target triple string contains foo. For example: - -```rust -///```ignore-foo,ignore-bar -///assert!(2 == 2); -///``` -struct Foo; -``` - -This will not be run when the build target is `super-awesome-foo` or `less-bar-awesome`. -If the flag is not enabled, then rustdoc will consume the filter, but do nothing with it, and -the above example will be run for all targets. -If you want to preserve backwards compatibility for older versions of rustdoc, you can use - -```rust -///```ignore,ignore-foo -///assert!(2 == 2); -///``` -struct Foo; -``` - -In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will -override `ignore`. - ## `--with-examples`: include examples of uses of items as documentation * Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791) diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md index b921f67785754..87e42fe1d3949 100644 --- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -427,6 +427,34 @@ should not be merged with the others. So the previous code should use it: In this case, it means that the line information will not change if you add/remove other doctests. +### Ignoring targets + +Attributes starting with `ignore-` can be used to ignore doctests for specific +targets. For example, `ignore-x86_64` will avoid building doctests when the +target name contains `x86_64`. + +```rust +/// ```ignore-x86_64 +/// assert!(2 == 2); +/// ``` +struct Foo; +``` + +This doctest will not be built for targets such as `x86_64-unknown-linux-gnu`. + +If you want to preserve backwards compatibility for older versions of rustdoc, +you can specify both `ignore` and `ignore-`, such as: + +```rust +/// ```ignore,ignore-x86_64 +/// assert!(2 == 2); +/// ``` +struct Foo; +``` + +In older versions, this will be ignored on all targets, but starting with +version CURRENT_RUSTC_VERSION, `ignore-x86_64` will override `ignore`. + ### Custom CSS classes for code blocks ```rust diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 0eb620c01d9b8..4ef73ff48edb5 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -127,10 +127,6 @@ pub(crate) struct Options { pub(crate) test_runtool: Option, /// Arguments to pass to the runtool pub(crate) test_runtool_args: Vec, - /// Whether to allow ignoring doctests on a per-target basis - /// For example, using ignore-foo to ignore running the doctest on any target that - /// contains "foo" as a substring - pub(crate) enable_per_target_ignores: bool, /// Do not run doctests, compile them if should_test is active. pub(crate) no_run: bool, /// What sources are being mapped. @@ -217,7 +213,6 @@ impl fmt::Debug for Options { .field("crate_version", &self.crate_version) .field("test_runtool", &self.test_runtool) .field("test_runtool_args", &self.test_runtool_args) - .field("enable-per-target-ignores", &self.enable_per_target_ignores) .field("run_check", &self.run_check) .field("no_run", &self.no_run) .field("test_builder_wrappers", &self.test_builder_wrappers) @@ -781,7 +776,6 @@ impl Options { let extern_strs = matches.opt_strs("extern"); let test_runtool = matches.opt_str("test-runtool"); let test_runtool_args = matches.opt_strs("test-runtool-arg"); - let enable_per_target_ignores = matches.opt_present("enable-per-target-ignores"); let document_private = matches.opt_present("document-private-items"); let document_hidden = matches.opt_present("document-hidden-items"); let run_check = matches.opt_present("check"); @@ -845,7 +839,6 @@ impl Options { persist_doctests, test_runtool, test_runtool_args, - enable_per_target_ignores, test_builder, run_check, no_run, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index ae4863dd82b86..39dd68937f81c 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -218,11 +218,9 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions let crate_name = tcx.crate_name(LOCAL_CRATE).to_string(); let crate_attrs = tcx.hir_attrs(CRATE_HIR_ID); let opts = scrape_test_config(crate_name, crate_attrs, args_path); - let enable_per_target_ignores = options.enable_per_target_ignores; let hir_collector = HirCollector::new( ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()), - enable_per_target_ignores, tcx, ); let tests = hir_collector.collect_crate(); diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index a0d39ce749d83..497a8d7c4a758 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -104,13 +104,7 @@ pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> { }; let codes = ErrorCodes::from(options.unstable_features.is_nightly_build()); - find_testable_code( - &input_str, - &mut md_collector, - codes, - options.enable_per_target_ignores, - None, - ); + find_testable_code(&input_str, &mut md_collector, codes, None); let mut collector = CreateRunnableDocTests::new(options.clone(), opts); md_collector.tests.into_iter().for_each(|t| collector.add_test(t)); diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 12f8b26b1e3c6..504e59d08e46c 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -63,19 +63,18 @@ impl DocTestVisitor for RustCollector { pub(super) struct HirCollector<'tcx> { codes: ErrorCodes, tcx: TyCtxt<'tcx>, - enable_per_target_ignores: bool, collector: RustCollector, } impl<'tcx> HirCollector<'tcx> { - pub fn new(codes: ErrorCodes, enable_per_target_ignores: bool, tcx: TyCtxt<'tcx>) -> Self { + pub fn new(codes: ErrorCodes, tcx: TyCtxt<'tcx>) -> Self { let collector = RustCollector { source_map: tcx.sess.psess.clone_source_map(), cur_path: vec![], position: DUMMY_SP, tests: vec![], }; - Self { codes, enable_per_target_ignores, tcx, collector } + Self { codes, tcx, collector } } pub fn collect_crate(mut self) -> Vec { @@ -131,7 +130,6 @@ impl HirCollector<'_> { &doc, &mut self.collector, self.codes, - self.enable_per_target_ignores, Some(&crate::html::markdown::ExtraInfo::new(self.tcx, def_id, span)), ); } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 0d547a6a0d92d..98dae535b352c 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -246,7 +246,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { match kind { CodeBlockKind::Fenced(ref lang) => { let parse_result = - LangString::parse_without_check(lang, self.check_error_codes, false); + LangString::parse_without_check(lang, self.check_error_codes); if !parse_result.rust { let added_classes = parse_result.added_classes; let lang_string = if let Some(lang) = parse_result.unknown.first() { @@ -707,17 +707,15 @@ pub(crate) fn find_testable_code( doc: &str, tests: &mut T, error_codes: ErrorCodes, - enable_per_target_ignores: bool, extra_info: Option<&ExtraInfo<'_>>, ) { - find_codes(doc, tests, error_codes, enable_per_target_ignores, extra_info, false) + find_codes(doc, tests, error_codes, extra_info, false) } pub(crate) fn find_codes( doc: &str, tests: &mut T, error_codes: ErrorCodes, - enable_per_target_ignores: bool, extra_info: Option<&ExtraInfo<'_>>, include_non_rust: bool, ) { @@ -733,12 +731,7 @@ pub(crate) fn find_codes( if lang.is_empty() { Default::default() } else { - LangString::parse( - lang, - error_codes, - enable_per_target_ignores, - extra_info, - ) + LangString::parse(lang, error_codes, extra_info) } } CodeBlockKind::Indented => Default::default(), @@ -1162,18 +1155,13 @@ impl Default for LangString { } impl LangString { - fn parse_without_check( - string: &str, - allow_error_code_check: ErrorCodes, - enable_per_target_ignores: bool, - ) -> Self { - Self::parse(string, allow_error_code_check, enable_per_target_ignores, None) + fn parse_without_check(string: &str, allow_error_code_check: ErrorCodes) -> Self { + Self::parse(string, allow_error_code_check, None) } fn parse( string: &str, allow_error_code_check: ErrorCodes, - enable_per_target_ignores: bool, extra: Option<&ExtraInfo<'_>>, ) -> Self { let allow_error_code_check = allow_error_code_check.as_bool(); @@ -1203,10 +1191,8 @@ impl LangString { LangStringToken::LangToken(x) if let Some(ignore) = x.strip_prefix("ignore-") => { - if enable_per_target_ignores { - ignores.push(ignore.to_owned()); - seen_rust_tags = !seen_other_tags; - } + ignores.push(ignore.to_owned()); + seen_rust_tags = !seen_other_tags; } LangStringToken::LangToken("rust") => { data.rust = true; @@ -1967,7 +1953,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec::new(); - find_testable_code(input, &mut lines, ErrorCodes::No, false, None); + find_testable_code(input, &mut lines, ErrorCodes::No, None); assert_eq!(lines, expect); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index c51debdfd40e8..d89cea4d5c9b7 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -506,14 +506,6 @@ fn opts() -> Vec { "calculate percentage of public items with documentation", "", ), - opt( - Unstable, - FlagMulti, - "", - "enable-per-target-ignores", - "parse ignore-foo for ignoring doctests on a per-target basis", - "", - ), opt( Stable, Opt, diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index f8f670f575bf4..4401a01440acb 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -212,7 +212,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { let has_docs = !i.attrs.doc_strings.is_empty(); let mut tests = Tests { found_tests: 0 }; - find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None); + find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, None); let has_doc_example = tests.found_tests != 0; let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap(); diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 0fefd13f76333..a885da180d694 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -122,7 +122,7 @@ pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) { let mut tests = Tests { found_tests: 0 }; - find_testable_code(dox, &mut tests, ErrorCodes::No, false, None); + find_testable_code(dox, &mut tests, ErrorCodes::No, None); if tests.found_tests == 0 && cx.tcx.features().rustdoc_missing_doc_code_examples() { if should_have_doc_example(cx, item) { diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index b0ca5f3bf0807..e06c7b75b0fcc 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -138,9 +138,6 @@ Options: --show-coverage calculate percentage of public items with documentation - --enable-per-target-ignores - parse ignore-foo for ignoring doctests on a per-target - basis --test-runtool The tool to run tests with when building for a different target than host --test-runtool-arg One (of possibly many) arguments to pass to the runtool From af2b4b94ed6f46392043f1c652f06f402d2713fc Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 27 Mar 2025 18:17:34 -0700 Subject: [PATCH 05/17] Show an example of using multiple ignore attributes --- .../src/write-documentation/documentation-tests.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md index 87e42fe1d3949..077b02d603d0f 100644 --- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -442,6 +442,15 @@ struct Foo; This doctest will not be built for targets such as `x86_64-unknown-linux-gnu`. +Multiple ignore attributes can be specified to ignore multiple targets: + +```rust +/// ```ignore-x86_64,ignore-windows +/// assert!(2 == 2); +/// ``` +struct Foo; +``` + If you want to preserve backwards compatibility for older versions of rustdoc, you can specify both `ignore` and `ignore-`, such as: From f535922f20d8061fc3c61b165cd7a4061500e751 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 27 Mar 2025 18:20:04 -0700 Subject: [PATCH 06/17] Try to more clearly specify exactly what the runtool flags do --- src/doc/rustdoc/src/command-line-arguments.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index ac5c7f5b6596f..b55ddf6e0e165 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -224,14 +224,19 @@ See also `--test`. ## `--test-runtool`, `--test-runtool-arg`: program to run tests with; args to pass to it +A doctest wrapper program can be specified with the `--test-runtool` flag. +Rustdoc will execute that wrapper instead of the doctest executable when +running tests. The first arguments to the wrapper will be any arguments +specified with the `--test-runtool-arg` flag, followed by the path to the +doctest executable to run. + Using these options looks like this: ```bash -$ rustdoc src/lib.rs --test-runtool runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing +$ rustdoc src/lib.rs --test-runtool path/to/runner --test-runtool-arg --do-thing --test-runtool-arg --do-other-thing ``` -These options can be used to run the doctest under a program, and also pass arguments to -that program. For example, if you want to run your doctests under valgrind you might run +For example, if you want to run your doctests under valgrind you might run: ```bash $ rustdoc src/lib.rs --test-runtool valgrind From 115341f767741ab1584b5daeafc2709a74612f59 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 14 Apr 2025 12:56:02 -0700 Subject: [PATCH 07/17] Fix grammar of --test-runtool-arg help text --- src/librustdoc/lib.rs | 2 +- tests/run-make/rustdoc-default-output/output-default.stdout | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index d89cea4d5c9b7..44bd96a7e4503 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -520,7 +520,7 @@ fn opts() -> Vec { "", "test-runtool-arg", "", - "One (of possibly many) arguments to pass to the runtool", + "One argument (of possibly many) to pass to the runtool", ), opt( Unstable, diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index e06c7b75b0fcc..563f8ec50cd61 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -140,7 +140,7 @@ Options: documentation --test-runtool The tool to run tests with when building for a different target than host - --test-runtool-arg One (of possibly many) arguments to pass to the runtool + --test-runtool-arg One argument (of possibly many) to pass to the runtool --test-builder PATH The rustc-like binary to use as the test builder From fdf2c47f83fd4eead8b4d39a8a712bf7d5e68fc6 Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Tue, 22 Apr 2025 22:55:19 -0400 Subject: [PATCH 08/17] [AIX] Handle AIX dynamic library extensions within c-link-to-rust-dylib run-make test Dynamic libraries on AIX have the ".a" extension. The c-link-to-rust-dylib run-make test checks for the extension explicitly, so the extension for AIX is also added to accommodate the test case on AIX. --- tests/run-make/c-link-to-rust-dylib/rmake.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/run-make/c-link-to-rust-dylib/rmake.rs b/tests/run-make/c-link-to-rust-dylib/rmake.rs index ab9aa445402b0..3a48af8a3665a 100644 --- a/tests/run-make/c-link-to-rust-dylib/rmake.rs +++ b/tests/run-make/c-link-to-rust-dylib/rmake.rs @@ -23,7 +23,11 @@ fn main() { if path.is_file() && path.extension().is_some_and(|ext| ext == expected_extension) && path.file_name().and_then(|name| name.to_str()).is_some_and(|name| { - name.ends_with(".so") || name.ends_with(".dll") || name.ends_with(".dylib") + if cfg!(target_os = "aix") { + name.ends_with(".a") + } else { + name.ends_with(".so") || name.ends_with(".dll") || name.ends_with(".dylib") + } }) { rfs::remove_file(path); From d88056c35ef8523afbd960a3927c71089d39d9f7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 23 Apr 2025 19:26:06 +1000 Subject: [PATCH 09/17] Derive `HashStable` for `DelimArgs`. --- compiler/rustc_ast/src/ast.rs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1532ca77f713e..8986430141be4 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1927,7 +1927,7 @@ impl AttrArgs { } /// Delimited arguments, as used in `#[attr()/[]/{}]` or `mac!()/[]/{}`. -#[derive(Clone, Encodable, Decodable, Debug)] +#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct DelimArgs { pub dspan: DelimSpan, pub delim: Delimiter, // Note: `Delimiter::Invisible` never occurs @@ -1942,18 +1942,6 @@ impl DelimArgs { } } -impl HashStable for DelimArgs -where - CTX: crate::HashStableContext, -{ - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let DelimArgs { dspan, delim, tokens } = self; - dspan.hash_stable(ctx, hasher); - delim.hash_stable(ctx, hasher); - tokens.hash_stable(ctx, hasher); - } -} - /// Represents a macro definition. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct MacroDef { From 7fe6bc57f5c9f1e40f82b4eefb4391149bc752e8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 23 Apr 2025 20:10:49 +1000 Subject: [PATCH 10/17] Use `clone` to clone `DelimArgs` in two places. --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_attr_parsing/src/context.rs | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c40987541f4a5..d23cf6cb2f1de 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -916,7 +916,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_delim_args(&self, args: &DelimArgs) -> DelimArgs { - DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.clone() } + args.clone() } /// Lower an associated item constraint. diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 63597b37cb5ee..55c3df003fe16 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -3,7 +3,7 @@ use std::collections::BTreeMap; use std::ops::Deref; use std::sync::LazyLock; -use rustc_ast::{self as ast, DelimArgs}; +use rustc_ast as ast; use rustc_attr_data_structures::AttributeKind; use rustc_errors::{DiagCtxtHandle, Diagnostic}; use rustc_feature::Features; @@ -315,11 +315,7 @@ impl<'sess> AttributeParser<'sess> { fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs { match args { ast::AttrArgs::Empty => AttrArgs::Empty, - ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(DelimArgs { - dspan: args.dspan, - delim: args.delim, - tokens: args.tokens.clone(), - }), + ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()), // This is an inert key-value attribute - it will never be visible to macros // after it gets lowered to HIR. Therefore, we can extract literals to handle // nonterminals in `#[doc]` (e.g. `#[doc = $e]`). From 18c3370e5d8fe47dfcbcca423544a26fb60553e4 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Wed, 23 Apr 2025 13:31:24 +0200 Subject: [PATCH 11/17] CI: use aws codebuild for job dist-arm-linux --- .github/workflows/ci.yml | 13 ++++++ src/ci/citool/src/jobs.rs | 33 +++++++++++++- .../host-x86_64/dist-arm-linux/Dockerfile | 2 +- src/ci/docker/run.sh | 2 +- src/ci/github-actions/jobs.yml | 11 ++++- src/ci/scripts/free-disk-space.sh | 43 +++++++++++++++---- 6 files changed, 91 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e83bbf643fee..7c46871569646 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,6 +91,17 @@ jobs: # Check the `calculate_matrix` job to see how is the matrix defined. include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }} steps: + - name: Install cargo in AWS CodeBuild + if: matrix.codebuild + run: | + # Check if cargo is installed + if ! command -v cargo &> /dev/null; then + echo "Cargo not found, installing Rust..." + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile=minimal + # Make cargo available in PATH + echo "$HOME/.cargo/bin" >> $GITHUB_PATH + fi + - name: disable git crlf conversion run: git config --global core.autocrlf false @@ -168,6 +179,8 @@ jobs: run: src/ci/scripts/install-ninja.sh - name: enable ipv6 on Docker + # Don't run on codebuild because systemctl is not available + if: ${{ !matrix.codebuild }} run: src/ci/scripts/enable-docker-ipv6.sh # Disable automatic line ending conversion (again). On Windows, when we're diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs index 13880ad466a6b..5600d7b4db59b 100644 --- a/src/ci/citool/src/jobs.rs +++ b/src/ci/citool/src/jobs.rs @@ -3,12 +3,15 @@ mod tests; use std::collections::BTreeMap; +use anyhow::Context as _; use serde_yaml::Value; use crate::GitHubContext; +use crate::utils::load_env_var; /// Representation of a job loaded from the `src/ci/github-actions/jobs.yml` file. #[derive(serde::Deserialize, Debug, Clone)] +#[serde(deny_unknown_fields)] pub struct Job { /// Name of the job, e.g. mingw-check pub name: String, @@ -26,6 +29,8 @@ pub struct Job { pub free_disk: Option, /// Documentation link to a resource that could help people debug this CI job. pub doc_url: Option, + /// Whether the job is executed on AWS CodeBuild. + pub codebuild: Option, } impl Job { @@ -80,7 +85,7 @@ impl JobDatabase { } pub fn load_job_db(db: &str) -> anyhow::Result { - let mut db: Value = serde_yaml::from_str(&db)?; + let mut db: Value = serde_yaml::from_str(db)?; // We need to expand merge keys (<<), because serde_yaml can't deal with them // `apply_merge` only applies the merge once, so do it a few times to unwrap nested merges. @@ -107,6 +112,29 @@ struct GithubActionsJob { free_disk: Option, #[serde(skip_serializing_if = "Option::is_none")] doc_url: Option, + #[serde(skip_serializing_if = "Option::is_none")] + codebuild: Option, +} + +/// Replace GitHub context variables with environment variables in job configs. +/// Used for codebuild jobs like +/// `codebuild-ubuntu-22-8c-$github.run_id-$github.run_attempt` +fn substitute_github_vars(jobs: Vec) -> anyhow::Result> { + let run_id = load_env_var("GITHUB_RUN_ID")?; + let run_attempt = load_env_var("GITHUB_RUN_ATTEMPT")?; + + let jobs = jobs + .into_iter() + .map(|mut job| { + job.os = job + .os + .replace("$github.run_id", &run_id) + .replace("$github.run_attempt", &run_attempt); + job + }) + .collect(); + + Ok(jobs) } /// Skip CI jobs that are not supposed to be executed on the given `channel`. @@ -177,6 +205,8 @@ fn calculate_jobs( } RunType::AutoJob => (db.auto_jobs.clone(), "auto", &db.envs.auto_env), }; + let jobs = substitute_github_vars(jobs.clone()) + .context("Failed to substitute GitHub context variables in jobs")?; let jobs = skip_jobs(jobs, channel); let jobs = jobs .into_iter() @@ -207,6 +237,7 @@ fn calculate_jobs( continue_on_error: job.continue_on_error, free_disk: job.free_disk, doc_url: job.doc_url, + codebuild: job.codebuild, } }) .collect(); diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile index 420c42bc9d807..3795859f308e6 100644 --- a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ghcr.io/rust-lang/ubuntu:22.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 00d791eeb6b38..36f7df2b06907 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -288,7 +288,7 @@ args="$args --privileged" # `LOCAL_USER_ID` (recognized in `src/ci/run.sh`) to ensure that files are all # read/written as the same user as the bare-metal user. if [ -f /.dockerenv ]; then - docker create -v /checkout --name checkout alpine:3.4 /bin/true + docker create -v /checkout --name checkout ghcr.io/rust-lang/alpine:3.4 /bin/true docker cp . checkout:/checkout args="$args --volumes-from checkout" else diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index cb2bec5a9dfa6..367e45ebe2006 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -56,6 +56,15 @@ runners: - &job-aarch64-linux-8c os: ubuntu-24.04-arm64-8core-32gb <<: *base-job + + # Codebuild runners are provisioned in + # https://github.com/rust-lang/simpleinfra/blob/b7ddd5e6bec8a93ec30510cdddec02c5666fefe9/terragrunt/accounts/ci-prod/ci-runners/terragrunt.hcl#L2 + - &job-linux-36c-codebuild + free_disk: true + codebuild: true + os: codebuild-ubuntu-22-36c-$github.run_id-$github.run_attempt + <<: *base-job + envs: env-x86_64-apple-tests: &env-x86_64-apple-tests SCRIPT: ./x.py check compiletest --set build.compiletest-use-stage0-libtest=true && ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact @@ -153,7 +162,7 @@ auto: <<: *job-linux-4c - name: dist-arm-linux - <<: *job-linux-8c + <<: *job-linux-36c-codebuild - name: dist-armhf-linux <<: *job-linux-4c diff --git a/src/ci/scripts/free-disk-space.sh b/src/ci/scripts/free-disk-space.sh index 055a6ac2211e3..ad7ee136e9c27 100755 --- a/src/ci/scripts/free-disk-space.sh +++ b/src/ci/scripts/free-disk-space.sh @@ -14,6 +14,17 @@ isX86() { fi } +# Check if we're on a GitHub hosted runner. +# In aws codebuild, the variable RUNNER_ENVIRONMENT is "self-hosted". +isGitHubRunner() { + # `:-` means "use the value of RUNNER_ENVIRONMENT if it exists, otherwise use an empty string". + if [[ "${RUNNER_ENVIRONMENT:-}" == "github-hosted" ]]; then + return 0 + else + return 1 + fi +} + # print a line of the specified character printSeparationLine() { for ((i = 0; i < 80; i++)); do @@ -32,7 +43,7 @@ getAvailableSpace() { # make Kb human readable (assume the input is Kb) # REF: https://unix.stackexchange.com/a/44087/60849 formatByteCount() { - numfmt --to=iec-i --suffix=B --padding=7 "$1"'000' + numfmt --to=iec-i --suffix=B --padding=7 "${1}000" } # macro to output saved space @@ -45,6 +56,11 @@ printSavedSpace() { after=$(getAvailableSpace) local saved=$((after - before)) + if [ "$saved" -lt 0 ]; then + echo "::warning::Saved space is negative: $saved. Using '0' as saved space." + saved=0 + fi + echo "" printSeparationLine "*" if [ -n "${title}" ]; then @@ -118,10 +134,14 @@ removeUnusedFilesAndDirs() { # Azure "/opt/az" "/usr/share/az_"* + ) + if [ -n "${AGENT_TOOLSDIRECTORY:-}" ]; then # Environment variable set by GitHub Actions - "$AGENT_TOOLSDIRECTORY" - ) + to_remove+=( + "${AGENT_TOOLSDIRECTORY}" + ) + fi for element in "${to_remove[@]}"; do if [ ! -e "$element" ]; then @@ -155,20 +175,25 @@ cleanPackages() { '^dotnet-.*' '^llvm-.*' '^mongodb-.*' - 'azure-cli' 'firefox' 'libgl1-mesa-dri' 'mono-devel' 'php.*' ) - if isX86; then + if isGitHubRunner; then packages+=( - 'google-chrome-stable' - 'google-cloud-cli' - 'google-cloud-sdk' - 'powershell' + azure-cli ) + + if isX86; then + packages+=( + 'google-chrome-stable' + 'google-cloud-cli' + 'google-cloud-sdk' + 'powershell' + ) + fi fi sudo apt-get -qq remove -y --fix-missing "${packages[@]}" From d2120e653e9acca9ab6f3053d0a173fa285fba04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= Date: Thu, 24 Apr 2025 01:25:46 +0800 Subject: [PATCH 12/17] Work around cygwin issue on timeout --- library/std/src/sys/pal/unix/sync/condvar.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/sync/condvar.rs b/library/std/src/sys/pal/unix/sync/condvar.rs index 73631053e9f47..efa6f8d776559 100644 --- a/library/std/src/sys/pal/unix/sync/condvar.rs +++ b/library/std/src/sys/pal/unix/sync/condvar.rs @@ -64,7 +64,10 @@ impl Condvar { // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c // // To work around this issue, the timeout is clamped to 1000 years. - #[cfg(target_vendor = "apple")] + // + // Cygwin implementation is based on NT API and a super large timeout + // makes the syscall block forever. + #[cfg(any(target_vendor = "apple", target_os = "cygwin"))] let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400)); let timeout = Timespec::now(Self::CLOCK).checked_add_duration(&dur); From c9deaf6aaa8e389e11e39abb9aca77e6340d176e Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Wed, 23 Apr 2025 15:58:50 +0500 Subject: [PATCH 13/17] fix for issue 135412 --- compiler/rustc_hir_typeck/src/cast.rs | 25 ++++++++++++---- tests/ui/coercion/issue-73886.stderr | 7 ++++- .../coercion/non-primitive-cast-135412.fixed | 10 +++++++ .../ui/coercion/non-primitive-cast-135412.rs | 10 +++++++ .../coercion/non-primitive-cast-135412.stderr | 29 +++++++++++++++++++ 5 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 tests/ui/coercion/non-primitive-cast-135412.fixed create mode 100644 tests/ui/coercion/non-primitive-cast-135412.rs create mode 100644 tests/ui/coercion/non-primitive-cast-135412.stderr diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index b19d9efe2c6f5..caf36ba47bd75 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -501,12 +501,25 @@ impl<'a, 'tcx> CastCheck<'tcx> { .must_apply_modulo_regions() { label = false; - err.span_suggestion( - self.span, - "consider using the `From` trait instead", - format!("{}::from({})", self.cast_ty, snippet), - Applicability::MaybeIncorrect, - ); + if let ty::Adt(def, args) = self.cast_ty.kind() { + err.span_suggestion_verbose( + self.span, + "consider using the `From` trait instead", + format!( + "{}::from({})", + fcx.tcx.value_path_str_with_args(def.did(), args), + snippet + ), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion( + self.span, + "consider using the `From` trait instead", + format!("{}::from({})", self.cast_ty, snippet), + Applicability::MaybeIncorrect, + ); + }; } } diff --git a/tests/ui/coercion/issue-73886.stderr b/tests/ui/coercion/issue-73886.stderr index a6f8ba65ab51a..0d4c90017cf11 100644 --- a/tests/ui/coercion/issue-73886.stderr +++ b/tests/ui/coercion/issue-73886.stderr @@ -8,9 +8,14 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>` --> $DIR/issue-73886.rs:4:13 | LL | let _ = 7u32 as Option<_>; - | ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)` + | ^^^^^^^^^^^^^^^^^ | = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object +help: consider using the `From` trait instead + | +LL - let _ = 7u32 as Option<_>; +LL + let _ = Option::<_>::from(7u32); + | error: aborting due to 2 previous errors diff --git a/tests/ui/coercion/non-primitive-cast-135412.fixed b/tests/ui/coercion/non-primitive-cast-135412.fixed new file mode 100644 index 0000000000000..5cadc9368d52e --- /dev/null +++ b/tests/ui/coercion/non-primitive-cast-135412.fixed @@ -0,0 +1,10 @@ +//@ run-rustfix + +use std::sync::Arc; + +fn main() { + let _ = Option::<_>::from(7u32); + //~^ ERROR non-primitive cast: `u32` as `Option<_>` + let _ = Arc::::from("String"); + //~^ ERROR non-primitive cast: `&'static str` as `Arc` +} diff --git a/tests/ui/coercion/non-primitive-cast-135412.rs b/tests/ui/coercion/non-primitive-cast-135412.rs new file mode 100644 index 0000000000000..67a3ef340d2f1 --- /dev/null +++ b/tests/ui/coercion/non-primitive-cast-135412.rs @@ -0,0 +1,10 @@ +//@ run-rustfix + +use std::sync::Arc; + +fn main() { + let _ = 7u32 as Option<_>; + //~^ ERROR non-primitive cast: `u32` as `Option<_>` + let _ = "String" as Arc; + //~^ ERROR non-primitive cast: `&'static str` as `Arc` +} diff --git a/tests/ui/coercion/non-primitive-cast-135412.stderr b/tests/ui/coercion/non-primitive-cast-135412.stderr new file mode 100644 index 0000000000000..7e5861f83e9c1 --- /dev/null +++ b/tests/ui/coercion/non-primitive-cast-135412.stderr @@ -0,0 +1,29 @@ +error[E0605]: non-primitive cast: `u32` as `Option<_>` + --> $DIR/non-primitive-cast-135412.rs:6:13 + | +LL | let _ = 7u32 as Option<_>; + | ^^^^^^^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object +help: consider using the `From` trait instead + | +LL - let _ = 7u32 as Option<_>; +LL + let _ = Option::<_>::from(7u32); + | + +error[E0605]: non-primitive cast: `&'static str` as `Arc` + --> $DIR/non-primitive-cast-135412.rs:8:13 + | +LL | let _ = "String" as Arc; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object +help: consider using the `From` trait instead + | +LL - let _ = "String" as Arc; +LL + let _ = Arc::::from("String"); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. From a224942d4cd234a20cf5521afb1debc7fc51eea9 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 23 Apr 2025 21:03:29 +0300 Subject: [PATCH 14/17] mention about `x.py setup` in `INSTALL.md` Signed-off-by: onur-ozkan --- INSTALL.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index 30e08201d6dfb..98eb825cd10f6 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -75,8 +75,31 @@ See [the rustc-dev-guide for more info][sysllvm]. 2. Configure the build settings: + If you're unsure which build configurations to use and need a good default, you + can run the interactive `x.py setup` command. This will guide you through selecting + a config profile, setting up the LSP, configuring a Git hook, etc. + + With `configure` script, you can handle multiple configurations in a single + command which is useful to create complex/advanced config files. For example: + ```sh - ./configure + ./configure --build=aarch64-unknown-linux-gnu \ + --enable-full-tools \ + --enable-profiler \ + --enable-sanitizers \ + --enable-compiler-docs \ + --set target.aarch64-unknown-linux-gnu.linker=clang \ + --set target.aarch64-unknown-linux-gnu.ar=/rustroot/bin/llvm-ar \ + --set target.aarch64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \ + --set llvm.link-shared=true \ + --set llvm.thin-lto=true \ + --set llvm.libzstd=true \ + --set llvm.ninja=false \ + --set rust.debug-assertions=false \ + --set rust.jemalloc \ + --set rust.use-lld=true \ + --set rust.lto=thin \ + --set rust.codegen-units=1 ``` If you plan to use `x.py install` to create an installation, you can either From 1feccc1edfbd799bffcb82b3c639cc28531efe5a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 24 Apr 2025 11:51:11 +0200 Subject: [PATCH 15/17] Make impl item info come before doc --- src/librustdoc/html/render/mod.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 7e17f09aecdcb..beaa6497b8caa 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2086,6 +2086,7 @@ fn render_impl( .split_summary_and_content() }) .unwrap_or((None, None)); + write!( w, "{}", @@ -2097,24 +2098,19 @@ fn render_impl( use_absolute, aliases, before_dox.as_deref(), + trait_.is_none() && impl_.items.is_empty(), ) )?; if toggled { w.write_str("")?; } - if before_dox.is_some() { - if trait_.is_none() && impl_.items.is_empty() { - w.write_str( - "
\ -
This impl block contains no items.
\ -
", - )?; - } - if let Some(after_dox) = after_dox { - write!(w, "
{after_dox}
")?; - } + if before_dox.is_some() + && let Some(after_dox) = after_dox + { + write!(w, "
{after_dox}
")?; } + if !default_impl_items.is_empty() || !impl_items.is_empty() { w.write_str("
")?; close_tags.push("
"); @@ -2182,6 +2178,7 @@ fn render_impl_summary( // in documentation pages for trait with automatic implementations like "Send" and "Sync". aliases: &[String], doc: Option<&str>, + impl_is_empty: bool, ) -> impl fmt::Display { fmt::from_fn(move |w| { let inner_impl = i.inner_impl(); @@ -2237,6 +2234,13 @@ fn render_impl_summary( } if let Some(doc) = doc { + if impl_is_empty { + w.write_str( + "
\ +
This impl block contains no items.
\ +
", + )?; + } write!(w, "
{doc}
")?; } From 7a895bd87a4d3a2229ae3c3b5e725f5dbecc1c13 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 24 Apr 2025 12:06:55 +0200 Subject: [PATCH 16/17] Fix indent of impl docs --- src/librustdoc/html/static/css/rustdoc.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index a6dd06b76ea97..19ac24a5d6e3d 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2319,7 +2319,10 @@ details.toggle > summary:not(.hideme)::before { doc block while aligning it with the impl block items. */ .implementors-toggle > .docblock, /* We indent trait items as well. */ -#main-content > .methods > :not(.item-info) { +#main-content > .methods > :not(.item-info), +.impl > .item-info, +.impl > .docblock, +.impl + .docblock { margin-left: var(--impl-items-indent); } From a29072a67afad6189603652fc30c146e6d9a45ce Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 24 Apr 2025 12:31:58 +0200 Subject: [PATCH 17/17] Add/update GUI test for impl indent fix --- .../rustdoc-gui/docblock-table-overflow.goml | 2 +- tests/rustdoc-gui/impl-doc-indent.goml | 16 ++++++++++++ tests/rustdoc-gui/item-info-overflow.goml | 2 +- tests/rustdoc-gui/src/test_docs/lib.rs | 26 +++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 tests/rustdoc-gui/impl-doc-indent.goml diff --git a/tests/rustdoc-gui/docblock-table-overflow.goml b/tests/rustdoc-gui/docblock-table-overflow.goml index 18e5b4d7f3590..e603c3a4d22e0 100644 --- a/tests/rustdoc-gui/docblock-table-overflow.goml +++ b/tests/rustdoc-gui/docblock-table-overflow.goml @@ -11,7 +11,7 @@ assert-property: (".top-doc .docblock table", {"scrollWidth": "1572"}) // Checking it works on other doc blocks as well... // Logically, the ".docblock" and the "

" should have the same scroll width (if we exclude the margin). -assert-property: ("#implementations-list > details .docblock", {"scrollWidth": 816}) +assert-property: ("#implementations-list > details .docblock", {"scrollWidth": 835}) assert-property: ("#implementations-list > details .docblock > p", {"scrollWidth": 835}) // However, since there is overflow in the , its scroll width is bigger. assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"}) diff --git a/tests/rustdoc-gui/impl-doc-indent.goml b/tests/rustdoc-gui/impl-doc-indent.goml new file mode 100644 index 0000000000000..d647fec6d732d --- /dev/null +++ b/tests/rustdoc-gui/impl-doc-indent.goml @@ -0,0 +1,16 @@ +// Checks the impl block docs have the correct indent. +go-to: "file://" + |DOC_PATH| + "/test_docs/impls_indent/struct.Context.html" + +// First we ensure that the impl items are indent (more on the right of the screen) than the +// impl itself. +store-position: ("#impl-Context", {"x": impl_x}) +store-position: ("#impl-Context > .item-info", {"x": impl_item_x}) +assert: |impl_x| < |impl_item_x| + +// And we ensure that all impl items have the same indent. +assert-position: ("#impl-Context > .docblock", {"x": |impl_item_x|}) +assert-position: ("#impl-Context + .docblock", {"x": |impl_item_x|}) + +// Same with the collapsible impl block. +assert-position: ("#impl-Context-1 > .docblock", {"x": |impl_item_x|}) +assert-position: (".implementors-toggle > summary + .docblock", {"x": |impl_item_x|}) diff --git a/tests/rustdoc-gui/item-info-overflow.goml b/tests/rustdoc-gui/item-info-overflow.goml index c325beb6d0669..2c4e06e297c7d 100644 --- a/tests/rustdoc-gui/item-info-overflow.goml +++ b/tests/rustdoc-gui/item-info-overflow.goml @@ -21,7 +21,7 @@ compare-elements-property: ( ) assert-property: ( "#impl-SimpleTrait-for-LongItemInfo2 .item-info", - {"scrollWidth": "916"}, + {"scrollWidth": "935"}, ) // Just to be sure we're comparing the correct "item-info": assert-text: ( diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs index 31f6b7f09b7d0..bb0015b8f9c43 100644 --- a/tests/rustdoc-gui/src/test_docs/lib.rs +++ b/tests/rustdoc-gui/src/test_docs/lib.rs @@ -740,3 +740,29 @@ pub mod SidebarSort { impl Sort for Cell {} impl<'a> Sort for &'a str {} } + +pub mod impls_indent { + pub struct Context; + + /// Working with objects. + /// + /// # Safety + /// + /// Functions that take indices of locals do not check bounds on these indices; + /// the caller must ensure that the indices are less than the number of locals + /// in the current stack frame. + impl Context { + } + + /// Working with objects. + /// + /// # Safety + /// + /// Functions that take indices of locals do not check bounds on these indices; + /// the caller must ensure that the indices are less than the number of locals + /// in the current stack frame. + impl Context { + /// bla + pub fn bar() {} + } +}