Rollup merge of #153801 - ywxt:parallel-test, r=petrochenkov

Add the option to run UI tests with the parallel frontend

This PR adds two arguments for tests:

1. `--parallel-frontend-threads`: specify `-Zthread` to compile test case (currently UI tests only)
2. `--iteration-count`: the number of times to run each test

Also, due to the non-deterministic diagnostic orders and cycle errors, this PR adds the directive `//@ ignore-parallel-frontend` to ignore tests with cycle error when the parallel-frontend is enabled (by `--parallel-frontend-threads`) and enables `//@ compare-output-by-lines` by default.

Context: [#t-compiler/parallel-rustc > Add the parallel front-end test suite @ 💬](https://rust-lang.zulipchat.com/#narrow/channel/187679-t-compiler.2Fparallel-rustc/topic/Add.20the.20parallel.20front-end.20test.20suite/near/578781369)

This PR should work with https://github.com/rust-lang/rust/pull/153797 together.
This commit is contained in:
Jonathan Brouwer
2026-03-17 17:51:29 +01:00
committed by GitHub
110 changed files with 287 additions and 192 deletions
@@ -836,3 +836,20 @@ In CI, compare modes are only used in one Linux builder, and only with the follo
Note that compare modes are separate to [revisions](#revisions).
All revisions are tested when running `./x test tests/ui`, however compare-modes must be
manually run individually via the `--compare-mode` flag.
## Parallel frontend
Compiletest can be run with the `--parallel-frontend-threads` flag to run the compiler in parallel mode.
This can be used to check that the compiler produces the same output in parallel mode as in non-parallel mode, and to check for any issues that might arise in parallel mode.
To run the tests in parallel mode, you need to pass the `--parallel-frontend-threads` CLI flag:
```bash
./x test tests/ui -- --parallel-frontend-threads=N --iteration-count=M
```
Where `N` is the number of threads to use for the parallel frontend, and `M` is the number of times to run each test in parallel mode (to increase the chances of catching any non-determinism).
Also, when running with `--parallel-frontend-threads`, the `compare-output-by-lines` directive would be implied for all tests, since the output from the parallel frontend can be non-deterministic in terms of the order of lines.
The parallel frontend is available in UI tests only at the moment, and is not currently supported in other test suites.
@@ -148,6 +148,7 @@ Some examples of `X` in `ignore-X` or `only-X`:
- When [remote testing] is used: `remote`
- When particular debuggers are being tested: `cdb`, `gdb`, `lldb`
- When particular debugger versions are matched: `ignore-gdb-version`
- When the [parallel frontend] is enabled: `ignore-parallel-frontend`
- Specific [compare modes]: `compare-mode-polonius`, `compare-mode-chalk`,
`compare-mode-split-dwarf`, `compare-mode-split-dwarf-single`
- The two different test modes used by coverage tests:
@@ -233,6 +234,7 @@ The following directives will check LLVM support:
See also [Debuginfo tests](compiletest.md#debuginfo-tests) for directives for ignoring debuggers.
[remote testing]: running.md#running-tests-on-a-remote-machine
[parallel frontend]: compiletest.md#parallel-frontend
[compare modes]: ui.md#compare-modes
[`x86_64-gnu-debug`]: https://github.com/rust-lang/rust/blob/ab3dba92db355b8d97db915a2dca161a117e959c/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile#L32
[`aarch64-gnu-debug`]: https://github.com/rust-lang/rust/blob/20c909ff9cdd88d33768a4ddb8952927a675b0ad/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile#L32
+19
View File
@@ -721,9 +721,17 @@ pub struct Config {
///
/// This is forwarded from bootstrap's `jobs` configuration.
pub jobs: u32,
/// Number of parallel threads to use for the frontend when building test artifacts.
pub parallel_frontend_threads: u32,
/// Number of times to execute each test.
pub iteration_count: u32,
}
impl Config {
pub const DEFAULT_PARALLEL_FRONTEND_THREADS: u32 = 1;
pub const DEFAULT_ITERATION_COUNT: u32 = 1;
/// FIXME: this run scheme is... confusing.
pub fn run_enabled(&self) -> bool {
self.run.unwrap_or_else(|| {
@@ -834,6 +842,17 @@ pub fn has_subprocess_support(&self) -> bool {
|| self.target_cfg().os == "emscripten";
!unsupported_target
}
/// Whether the parallel frontend is enabled,
/// which is the case when `parallel_frontend_threads` is not set to `1`.
///
/// - `0` means auto-detect: use the number of available hardware threads on the host.
/// But we treat it as the parallel frontend being enabled in this case.
/// - `1` means single-threaded (parallel frontend disabled).
/// - `>1` means an explicitly configured thread count.
pub fn parallel_frontend_enabled(&self) -> bool {
self.parallel_frontend_threads != 1
}
}
/// Known widths of `target_has_atomic`.
+91 -75
View File
@@ -67,7 +67,7 @@ pub(crate) fn from_file_directives(
let mut props = EarlyProps::default();
iter_directives(
config.mode,
config,
file_directives,
// (dummy comment to force args into vertical layout)
&mut |ln: &DirectiveLine<'_>| {
@@ -362,7 +362,7 @@ fn load_from(&mut self, testfile: &Utf8Path, test_revision: Option<&str>, config
let file_directives = FileDirectives::from_file_contents(testfile, &file_contents);
iter_directives(
config.mode,
config,
&file_directives,
// (dummy comment to force args into vertical layout)
&mut |ln: &DirectiveLine<'_>| {
@@ -574,43 +574,51 @@ fn check_directive<'a>(
}
fn iter_directives(
mode: TestMode,
config: &Config,
file_directives: &FileDirectives<'_>,
it: &mut dyn FnMut(&DirectiveLine<'_>),
) {
let testfile = file_directives.path;
// Coverage tests in coverage-run mode always have these extra directives, without needing to
// specify them manually in every test file.
//
// FIXME(jieyouxu): I feel like there's a better way to do this, leaving for later.
if mode == TestMode::CoverageRun {
let extra_directives: &[&str] = &[
"//@ needs-profiler-runtime",
// FIXME(pietroalbini): this test currently does not work on cross-compiled targets
// because remote-test is not capable of sending back the *.profraw files generated by
// the LLVM instrumentation.
"//@ ignore-cross-compile",
];
// Process the extra implied directives, with a dummy line number of 0.
for directive_str in extra_directives {
let directive_line = line_directive(testfile, LineNumber::ZERO, directive_str)
.unwrap_or_else(|| panic!("bad extra-directive line: {directive_str:?}"));
it(&directive_line);
let extra_directives = match config.mode {
TestMode::CoverageRun => {
// Coverage tests in coverage-run mode always have these extra directives, without needing to
// specify them manually in every test file.
//
// FIXME(jieyouxu): I feel like there's a better way to do this, leaving for later.
vec![
"//@ needs-profiler-runtime",
// FIXME(pietroalbini): this test currently does not work on cross-compiled targets
// because remote-test is not capable of sending back the *.profraw files generated by
// the LLVM instrumentation.
"//@ ignore-cross-compile",
]
}
TestMode::Codegen if !file_directives.has_explicit_no_std_core_attribute => {
// Note: affects all codegen test suites under test mode `codegen`, e.g. `codegen-llvm`.
//
// Codegen tests automatically receive implied `//@ needs-target-std`, unless
// `#![no_std]`/`#![no_core]` attribute was explicitly seen. The rationale is basically to avoid
// having to manually maintain a bunch of `//@ needs-target-std` directives esp. for targets
// tested/built out-of-tree.
vec!["//@ needs-target-std"]
}
TestMode::Ui if config.parallel_frontend_enabled() => {
// UI tests in parallel-frontend mode always have this extra directive, without needing to
// specify it manually in every test file.
vec!["//@ compare-output-by-lines"]
}
}
// Note: affects all codegen test suites under test mode `codegen`, e.g. `codegen-llvm`.
//
// Codegen tests automatically receive implied `//@ needs-target-std`, unless
// `#![no_std]`/`#![no_core]` attribute was explicitly seen. The rationale is basically to avoid
// having to manually maintain a bunch of `//@ needs-target-std` directives esp. for targets
// tested/built out-of-tree.
if mode == TestMode::Codegen && !file_directives.has_explicit_no_std_core_attribute {
let implied_needs_target_std_line =
line_directive(testfile, LineNumber::ZERO, "//@ needs-target-std")
.expect("valid `needs-target-std` directive line");
it(&implied_needs_target_std_line);
_ => {
// No extra directives for other test modes.
vec![]
}
};
for directive_str in extra_directives {
let directive_line = line_directive(testfile, LineNumber::ZERO, directive_str)
.unwrap_or_else(|| panic!("bad extra-directive line: {directive_str:?}"));
it(&directive_line);
}
for directive_line in &file_directives.lines {
@@ -951,55 +959,52 @@ pub(crate) fn make_test_description(
let mut should_fail = false;
// Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives.
iter_directives(
config.mode,
file_directives,
&mut |ln @ &DirectiveLine { line_number, .. }| {
if !ln.applies_to_test_revision(test_revision) {
return;
}
iter_directives(config, file_directives, &mut |ln @ &DirectiveLine { line_number, .. }| {
if !ln.applies_to_test_revision(test_revision) {
return;
}
// Parse `aux-*` directives, for use by up-to-date checks.
parse_and_update_aux(config, ln, aux_props);
// Parse `aux-*` directives, for use by up-to-date checks.
parse_and_update_aux(config, ln, aux_props);
macro_rules! decision {
($e:expr) => {
match $e {
IgnoreDecision::Ignore { reason } => {
ignore = true;
ignore_message = Some(reason.into());
}
IgnoreDecision::Error { message } => {
error!("{path}:{line_number}: {message}");
*poisoned = true;
return;
}
IgnoreDecision::Continue => {}
macro_rules! decision {
($e:expr) => {
match $e {
IgnoreDecision::Ignore { reason } => {
ignore = true;
ignore_message = Some(reason.into());
}
};
}
IgnoreDecision::Error { message } => {
error!("{path}:{line_number}: {message}");
*poisoned = true;
return;
}
IgnoreDecision::Continue => {}
}
};
}
decision!(cfg::handle_ignore(&cache.cfg_conditions, ln));
decision!(cfg::handle_only(&cache.cfg_conditions, ln));
decision!(needs::handle_needs(&cache.needs, config, ln));
decision!(ignore_llvm(config, ln));
decision!(ignore_backends(config, ln));
decision!(needs_backends(config, ln));
decision!(ignore_cdb(config, ln));
decision!(ignore_gdb(config, ln));
decision!(ignore_lldb(config, ln));
decision!(cfg::handle_ignore(&cache.cfg_conditions, ln));
decision!(cfg::handle_only(&cache.cfg_conditions, ln));
decision!(needs::handle_needs(&cache.needs, config, ln));
decision!(ignore_llvm(config, ln));
decision!(ignore_backends(config, ln));
decision!(needs_backends(config, ln));
decision!(ignore_cdb(config, ln));
decision!(ignore_gdb(config, ln));
decision!(ignore_lldb(config, ln));
decision!(ignore_parallel_frontend(config, ln));
if config.target == "wasm32-unknown-unknown"
&& config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS)
{
decision!(IgnoreDecision::Ignore {
reason: "ignored on WASM as the run results cannot be checked there".into(),
});
}
if config.target == "wasm32-unknown-unknown"
&& config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS)
{
decision!(IgnoreDecision::Ignore {
reason: "ignored on WASM as the run results cannot be checked there".into(),
});
}
should_fail |= config.parse_name_directive(ln, "should-fail");
},
);
should_fail |= config.parse_name_directive(ln, "should-fail");
});
// The `should-fail` annotation doesn't apply to pretty tests,
// since we run the pretty printer across all tests by default.
@@ -1270,6 +1275,17 @@ fn ignore_llvm(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision {
IgnoreDecision::Continue
}
fn ignore_parallel_frontend(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision {
if config.parallel_frontend_enabled()
&& config.parse_name_directive(line, "ignore-parallel-frontend")
{
return IgnoreDecision::Ignore {
reason: "ignored when the parallel frontend is enabled".into(),
};
}
IgnoreDecision::Continue
}
enum IgnoreDecision {
Ignore { reason: String },
Continue,
@@ -11,6 +11,7 @@
"ignore-backends",
"ignore-gdb-version",
"ignore-llvm-version",
"ignore-parallel-frontend",
"ignore-pass",
// tidy-alphabetical-end
];
@@ -101,6 +101,7 @@
"ignore-nvptx64",
"ignore-nvptx64-nvidia-cuda",
"ignore-openbsd",
"ignore-parallel-frontend",
"ignore-pass",
"ignore-powerpc",
"ignore-powerpc64",
+25 -1
View File
@@ -219,7 +219,14 @@ fn parse_config(args: Vec<String>) -> Config {
"CODEGEN BACKEND [NAME | PATH]",
)
.optflag("", "bypass-ignore-backends", "ignore `//@ ignore-backends` directives")
.reqopt("", "jobs", "number of parallel jobs bootstrap was configured with", "JOBS");
.reqopt("", "jobs", "number of parallel jobs bootstrap was configured with", "JOBS")
.optopt(
"",
"parallel-frontend-threads",
"number of parallel threads to use for the frontend when building test artifacts",
"THREADS_COUNT",
)
.optopt("", "iteration-count", "number of times to execute each test", "COUNT");
let (argv0, args_) = args.split_first().unwrap();
if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
@@ -369,6 +376,20 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf {
None => panic!("`--jobs` is required"),
};
let parallel_frontend_threads = match matches.opt_str("parallel-frontend-threads") {
Some(threads) => {
threads.parse::<u32>().expect("expected `--parallel-frontend-threads` to be an `u32`")
}
None => Config::DEFAULT_PARALLEL_FRONTEND_THREADS,
};
let iteration_count = match matches.opt_str("iteration-count") {
Some(count) => {
count.parse::<u32>().expect("expected `--iteration-count` to be a positive integer")
}
None => Config::DEFAULT_ITERATION_COUNT,
};
assert!(iteration_count > 0, "`--iteration-count` must be a positive integer");
Config {
bless: matches.opt_present("bless"),
fail_fast: matches.opt_present("fail-fast")
@@ -489,6 +510,9 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf {
bypass_ignore_backends: matches.opt_present("bypass-ignore-backends"),
jobs,
parallel_frontend_threads,
iteration_count,
}
}
+28 -16
View File
@@ -272,22 +272,26 @@ fn run_revision(&self) {
{
self.fatal("cannot use should-ice in a test that is not cfail");
}
match self.config.mode {
TestMode::Pretty => self.run_pretty_test(),
TestMode::DebugInfo => self.run_debuginfo_test(),
TestMode::Codegen => self.run_codegen_test(),
TestMode::RustdocHtml => self.run_rustdoc_html_test(),
TestMode::RustdocJson => self.run_rustdoc_json_test(),
TestMode::CodegenUnits => self.run_codegen_units_test(),
TestMode::Incremental => self.run_incremental_test(),
TestMode::RunMake => self.run_rmake_test(),
TestMode::Ui => self.run_ui_test(),
TestMode::MirOpt => self.run_mir_opt_test(),
TestMode::Assembly => self.run_assembly_test(),
TestMode::RustdocJs => self.run_rustdoc_js_test(),
TestMode::CoverageMap => self.run_coverage_map_test(), // see self::coverage
TestMode::CoverageRun => self.run_coverage_run_test(), // see self::coverage
TestMode::Crashes => self.run_crash_test(),
// Run the test multiple times if requested.
// This is useful for catching flaky tests under the parallel frontend.
for _ in 0..self.config.iteration_count {
match self.config.mode {
TestMode::Pretty => self.run_pretty_test(),
TestMode::DebugInfo => self.run_debuginfo_test(),
TestMode::Codegen => self.run_codegen_test(),
TestMode::RustdocHtml => self.run_rustdoc_html_test(),
TestMode::RustdocJson => self.run_rustdoc_json_test(),
TestMode::CodegenUnits => self.run_codegen_units_test(),
TestMode::Incremental => self.run_incremental_test(),
TestMode::RunMake => self.run_rmake_test(),
TestMode::Ui => self.run_ui_test(),
TestMode::MirOpt => self.run_mir_opt_test(),
TestMode::Assembly => self.run_assembly_test(),
TestMode::RustdocJs => self.run_rustdoc_js_test(),
TestMode::CoverageMap => self.run_coverage_map_test(), // see self::coverage
TestMode::CoverageRun => self.run_coverage_run_test(), // see self::coverage
TestMode::Crashes => self.run_crash_test(),
}
}
}
@@ -1752,6 +1756,14 @@ fn make_compile_args(
compiler.arg("-Zwrite-long-types-to-disk=no");
// FIXME: use this for other modes too, for perf?
compiler.arg("-Cstrip=debuginfo");
if self.config.parallel_frontend_enabled() {
// Currently, we only use multiple threads for the UI test suite,
// because UI tests can effectively verify the parallel frontend and
// require minimal modification. The option will later be extended to
// other test suites.
compiler.arg(&format!("-Zthreads={}", self.config.parallel_frontend_threads));
}
}
TestMode::MirOpt => {
// We check passes under test to minimize the mir-opt test dump
@@ -140,5 +140,7 @@ fn incomplete_config_for_rustdoc_gui_test() -> Config {
override_codegen_backend: None,
bypass_ignore_backends: Default::default(),
jobs: Default::default(),
parallel_frontend_threads: Config::DEFAULT_PARALLEL_FRONTEND_THREADS,
iteration_count: Config::DEFAULT_ITERATION_COUNT,
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
//@ only-x86_64
//@ build-fail
//@ compile-flags: -C target-feature=-avx
//@ ignore-parallel-frontend post-monomorphization errors
#![feature(portable_simd)]
#![feature(simd_ffi)]
#![allow(improper_ctypes_definitions)]
@@ -1,7 +1,7 @@
//@ edition:2018
// Test that impl trait does not allow creating recursive types that are
// otherwise forbidden when using `async` and `await`.
//@ ignore-parallel-frontend query cycle
async fn rec_1() { //~ ERROR recursion in an async fn
rec_2().await;
}
@@ -1,5 +1,5 @@
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend different alloc ids
#![allow(incomplete_features)]
#![feature(adt_const_params, unsized_const_params)]
@@ -1,6 +1,6 @@
//@ stderr-per-bitwidth
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend different alloc ids
use std::mem::transmute;
fn get_flag<const FlagSet: bool, const ShortName: char>() -> Option<char> {
+1 -1
View File
@@ -1,7 +1,7 @@
// Strip out raw byte dumps to make comparison platform-independent:
//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
//@ ignore-parallel-frontend different alloc ids
#![feature(
slice_from_ptr_range,
const_slice_from_ptr_range,
+1 -1
View File
@@ -1,6 +1,6 @@
fn main() {
use std::ptr;
//@ ignore-parallel-frontend different alloc ids
const DATA: [u32; 1] = [42];
const PAST_END_PTR: *const u32 = unsafe { DATA.as_ptr().add(1) };
@@ -1,5 +1,5 @@
//@ run-pass
//@ ignore-parallel-frontend queries overflow the depth limit
// https://github.com/rust-lang/rust/issues/34997
pub const CST_1: u32 = 0;
+1 -1
View File
@@ -1,5 +1,5 @@
//@ check-fail
//@ ignore-parallel-frontend different alloc ids
#![feature(core_intrinsics, const_cmp)]
use std::intrinsics::compare_bytes;
use std::mem::MaybeUninit;
@@ -1,5 +1,5 @@
//@ stderr-per-bitwidth
//@ ignore-parallel-frontend different alloc ids
#[derive(Copy, Clone)]
union Foo {
a: isize,
@@ -1,5 +1,5 @@
//@ build-fail
//@ ignore-parallel-frontend different alloc ids
#![feature(c_variadic)]
#![feature(const_c_variadic)]
#![feature(const_trait_impl)]
@@ -1,7 +1,7 @@
//@ only-x86_64
//@ stderr-per-bitwidth
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend different alloc ids
#[repr(C)]
union Nonsense {
u: usize,
@@ -3,7 +3,7 @@
#![feature(core_intrinsics)]
#![feature(const_heap)]
use std::intrinsics;
//@ ignore-parallel-frontend different alloc ids
const BAR: &i32 = unsafe { //~ ERROR: uninitialized memory
// Make the pointer immutable to avoid errors related to mutable pointers in constants.
&*(intrinsics::const_make_global(intrinsics::const_allocate(4, 4)) as *const i32)
@@ -1,6 +1,6 @@
#![feature(core_intrinsics)]
#![feature(const_heap)]
//@ ignore-parallel-frontend different alloc ids
// Strip out raw byte dumps to make comparison platform-independent:
//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
@@ -1,6 +1,6 @@
#![feature(core_intrinsics)]
#![feature(const_heap)]
//@ ignore-parallel-frontend different alloc ids
use std::intrinsics;
const _X: () = unsafe {
@@ -1,6 +1,6 @@
#![feature(core_intrinsics)]
#![feature(const_heap)]
//@ ignore-parallel-frontend different alloc ids
use std::intrinsics;
const _X: () = unsafe {
@@ -1,5 +1,5 @@
// Ensure that we can't call `const_make_global` on dangling pointers.
//@ ignore-parallel-frontend different alloc ids
#![feature(core_intrinsics)]
#![feature(const_heap)]
@@ -1,5 +1,5 @@
// Ensure that we can't call `const_make_global` on pointers not in the current interpreter.
//@ ignore-parallel-frontend different alloc ids
#![feature(core_intrinsics)]
#![feature(const_heap)]
@@ -1,5 +1,5 @@
// Ensure that we can't call `const_make_global` twice.
//@ ignore-parallel-frontend different alloc ids
#![feature(core_intrinsics)]
#![feature(const_heap)]
@@ -2,7 +2,7 @@
#![feature(core_intrinsics)]
#![feature(const_heap)]
use std::intrinsics;
//@ ignore-parallel-frontend different alloc ids
const A: &u8 = unsafe {
let ptr = intrinsics::const_allocate(1, 1);
*ptr = 1;
@@ -1,5 +1,5 @@
//@ build-fail
//@ ignore-parallel-frontend post-monomorphization errors
// Regression test for #66975
#![warn(unconditional_panic)]
#![feature(never_type)]
+1 -1
View File
@@ -1,5 +1,5 @@
// issue-49296: Unsafe shenigans in constants can result in missing errors
//@ ignore-parallel-frontend different alloc ids
use std::mem::transmute;
const fn wat(x: u64) -> &'static u64 {
+1 -1
View File
@@ -2,7 +2,7 @@
//@ revisions: normal mir-opt
//@ [mir-opt]compile-flags: -Zmir-opt-level=4
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend post-monomorphization errors
trait C {
const BOO: usize;
}
+1 -1
View File
@@ -1,6 +1,6 @@
//@ build-fail
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend post-monomorphization errors
trait Unsigned {
const MAX: u8;
}
@@ -1,6 +1,6 @@
//! This mixes fragments from different pointers, in a way that we should not accept.
//! See <https://github.com/rust-lang/rust/issues/146291>.
//@ ignore-parallel-frontend different alloc ids
static A: u8 = 123;
static B: u8 = 123;
+1 -1
View File
@@ -3,7 +3,7 @@
// ignore-tidy-linelength
//@ normalize-stderr: "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼" -> "╾ALLOC_ID$1╼"
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend different alloc ids
#![allow(invalid_value, unnecessary_transmutes)]
#![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)]
+1 -1
View File
@@ -4,7 +4,7 @@
let _val = *ptr; //~NOTE: failed here
//~^ERROR: based on pointer with alignment 1, but alignment 4 is required
};
//@ ignore-parallel-frontend different alloc ids
const MISALIGNED_STORE: () = unsafe {
let mut mem = [0u32; 8];
let ptr = mem.as_mut_ptr().byte_add(1);
@@ -1,5 +1,5 @@
//! Ensure we error when trying to load from a pointer whose provenance has been messed with.
//@ ignore-parallel-frontend different alloc ids
const PARTIAL_OVERWRITE: () = {
let mut p = &42;
// Overwrite one byte with a no-provenance value.
@@ -2,7 +2,7 @@ enum E {
A(u8),
B,
}
//@ ignore-parallel-frontend different alloc ids
const _: u8 = {
let mut e = E::A(1);
let p = if let E::A(x) = &mut e { x as *mut u8 } else { unreachable!() };
+1 -1
View File
@@ -4,7 +4,7 @@
//@ normalize-stderr: "0x0+" -> "0x0"
//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1"
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend different alloc ids
#![feature(never_type)]
#![allow(invalid_value, unnecessary_transmutes)]
@@ -12,7 +12,7 @@
//@ stderr-per-bitwidth
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend different alloc ids
trait Trait {}
const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
+1 -1
View File
@@ -2,7 +2,7 @@
//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP"
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend different alloc ids
#![allow(invalid_value)] // make sure we cannot allow away the errors tested here
#![feature(rustc_attrs, ptr_metadata)]
+1 -1
View File
@@ -6,7 +6,7 @@
//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1"
#![feature(rustc_attrs)]
#![allow(invalid_value)]
//@ ignore-parallel-frontend different alloc ids
use std::mem;
#[repr(C)]
+1 -1
View File
@@ -1,7 +1,7 @@
//@ edition:2015..2021
//@ stderr-per-bitwidth
#![allow(invalid_value)] // make sure we cannot allow away the errors tested here
//@ ignore-parallel-frontend different alloc ids
use std::mem;
const BAD_UPVAR: &dyn FnOnce() = &{ //~ ERROR null reference
+1 -1
View File
@@ -3,7 +3,7 @@
#![feature(ptr_metadata)]
use std::{ptr, mem};
//@ ignore-parallel-frontend different alloc ids
// Strip out raw byte dumps to make comparison platform-independent:
//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
//@ normalize-stderr: "([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
@@ -1,7 +1,7 @@
//@ dont-require-annotations: NOTE
//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
//@ normalize-stderr: "([[:xdigit:]]{2}\s){4}(__\s){4}\s+│\s+([?|\.]){4}\W{4}" -> "HEX_DUMP"
//@ ignore-parallel-frontend different alloc ids
type Field1 = i32;
type Field2 = f32;
type Field3 = i64;
+1 -1
View File
@@ -1,5 +1,5 @@
//@ only-x86_64
//@ ignore-parallel-frontend different alloc ids
type Field1 = i32;
type Field3 = i64;
+1 -1
View File
@@ -1,6 +1,6 @@
//@ stderr-per-bitwidth
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend different alloc ids
#[repr(C)]
union DummyUnion {
unit: (),
@@ -8,7 +8,7 @@ macro_rules! suite {
)*
}
}
//@ ignore-parallel-frontend different infer type: bool
suite! {
len;
is_empty;
+1 -1
View File
@@ -1,6 +1,6 @@
// ignore-tidy-linelength
#![feature(core_intrinsics)]
//@ ignore-parallel-frontend different alloc ids
use std::intrinsics::{copy, copy_nonoverlapping};
use std::mem;
@@ -3,7 +3,7 @@
//
//@ build-fail
//@ stderr-per-bitwidth
//@ ignore-parallel-frontend different alloc ids
use std::cell::Cell;
use std::mem::ManuallyDrop;
+1 -1
View File
@@ -1,6 +1,6 @@
// Regression test for #63952, shouldn't hang.
//@ stderr-per-bitwidth
//@ ignore-parallel-frontend different alloc ids
#[repr(C)]
#[derive(Copy, Clone)]
struct SliceRepr {
+1 -1
View File
@@ -1,7 +1,7 @@
//@ ignore-32bit
// This test gives a different error on 32-bit architectures.
//@ stderr-per-bitwidth
//@ ignore-parallel-frontend different alloc ids
union Transmute<T: Copy, U: Copy> {
t: T,
u: U,
@@ -1,6 +1,6 @@
//@ stderr-per-bitwidth
//@ compile-flags: -Zunleash-the-miri-inside-of-you
//@ ignore-parallel-frontend different alloc ids
// All "inner" allocations that come with a `static` are interned immutably. This means it is
// crucial that we do not accept any form of (interior) mutability there.
use std::sync::atomic::*;
+1 -1
View File
@@ -1,7 +1,7 @@
//! Check what happens when the error occurs inside a std function that we can't print the span of.
//@ ignore-backends: gcc
//@ compile-flags: -Z ui-testing=no --diagnostic-width=80
//@ ignore-parallel-frontend different alloc ids
use std::{
mem::{self, MaybeUninit},
ptr,
@@ -1,5 +1,5 @@
//@ build-fail
//@ ignore-parallel-frontend post-monomorphization errors
struct Bar<const BITS: usize>;
impl<const BITS: usize> Bar<BITS> {
+1 -1
View File
@@ -1,5 +1,5 @@
use std::ptr;
//@ ignore-parallel-frontend different alloc ids
//@ normalize-stderr: "0xf+" -> "0xf..f"
//@ normalize-stderr: "0x7f+" -> "0x7f..f"
//@ normalize-stderr: "\d+ bytes" -> "$$BYTES bytes"
+1 -1
View File
@@ -1,6 +1,6 @@
//@ revisions: default unleash
//@[unleash]compile-flags: -Zunleash-the-miri-inside-of-you
//@ ignore-parallel-frontend query cycle
// This test ensures that we do not allow ZST statics to initialize themselves without ever
// actually creating a value of that type. This is important, as the ZST may have private fields
// that users can reasonably expect to only get initialized by their own code. Thus unsafe code
@@ -4,7 +4,7 @@
//@[opt] compile-flags: -O
//! Make sure we detect erroneous constants post-monomorphization even when they are unused. This is
//! crucial, people rely on it for soundness. (https://github.com/rust-lang/rust/issues/112090)
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -4,7 +4,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -4,7 +4,7 @@
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
#![feature(type_alias_impl_trait)]
//@ ignore-parallel-frontend post-monomorphization errors
mod m {
struct Fail<T>(T);
impl<T> Fail<T> {
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Late<T>(T);
impl<T> Late<T> {
const FAIL: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This passes without optimizations, so it can (and should) also pass with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!();
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! This fails without optimizations, so it should also fail with optimizations.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -3,7 +3,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! Make sure we error on erroneous consts even if they get promoted.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR evaluation panicked: explicit panic
@@ -2,7 +2,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! Make sure we error on erroneous consts even if they are unused.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR explicit panic
@@ -2,7 +2,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//@ dont-require-annotations: NOTE
//@ ignore-parallel-frontend post-monomorphization errors
//! Make sure we evaluate const fn calls even if they get promoted and their result ignored.
const unsafe fn ub() {
@@ -2,7 +2,7 @@
//@[noopt] compile-flags: -Copt-level=0
//@[opt] compile-flags: -O
//! Make sure we error on erroneous consts even if they are unused.
//@ ignore-parallel-frontend post-monomorphization errors
struct Fail<T>(T);
impl<T> Fail<T> {
const C: () = panic!(); //~ERROR explicit panic
@@ -1,6 +1,6 @@
// Test a supertrait cycle where the first trait we find (`A`) is not
// a direct participant in the cycle.
//@ ignore-parallel-frontend query cycle
trait A: B {
}
+1 -1
View File
@@ -1,7 +1,7 @@
trait T1 : T2 {
//~^ ERROR cycle detected
}
//@ ignore-parallel-frontend query cycle
trait T2 : T1 {
}
+1 -1
View File
@@ -2,7 +2,7 @@
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-fail
//@ ignore-parallel-frontend query cycle
// Next solver revision included because of trait-system-refactor-initiative#234.
// If we end up in a query cycle, it should be okay as long as results are the same.
@@ -1,6 +1,6 @@
// Test that when a trait impl changes, fns whose body uses that trait
// must also be recompiled.
//@ ignore-parallel-frontend dep graph
//@ incremental
//@ compile-flags: -Z query-dep-graph
@@ -3,7 +3,7 @@
//@ incremental
//@ compile-flags: -Z query-dep-graph
//@ ignore-parallel-frontend dep graph
#![feature(rustc_attrs)]
#![allow(dead_code)]
@@ -1,6 +1,6 @@
// Test cases where a changing struct appears in the signature of fns
// and methods.
//@ ignore-parallel-frontend dep graph
//@ incremental
//@ compile-flags: -Z query-dep-graph
@@ -1,6 +1,6 @@
// Test that adding an impl to a trait `Foo` DOES affect functions
// that only use `Bar` if they have methods in common.
//@ ignore-parallel-frontend dep graph
//@ incremental
//@ compile-flags: -Z query-dep-graph
+1 -1
View File
@@ -1,6 +1,6 @@
// Test that when a trait impl changes, fns whose body uses that trait
// must also be recompiled.
//@ ignore-parallel-frontend dep graph
//@ incremental
//@ compile-flags: -Z query-dep-graph
+1 -1
View File
@@ -1,5 +1,5 @@
// Test that changing what a `type` points to does not go unnoticed.
//@ ignore-parallel-frontend dep graph
//@ incremental
//@ compile-flags: -Z query-dep-graph
@@ -1,6 +1,6 @@
// Test that changing what a `type` points to does not go unnoticed
// by the variance analysis.
//@ ignore-parallel-frontend dep graph
//@ incremental
//@ compile-flags: -Z query-dep-graph
@@ -56,3 +56,4 @@ fn bay() -> Vec<(bool, HashSet<u8>)> {
.collect()
}
fn main() {}
//@ ignore-parallel-frontend invalid svg(multiple threads trying to write to the same file)
@@ -4,7 +4,7 @@ trait Foo {
where
Self: 'c;
}
//@ ignore-parallel-frontend query cycle
impl Foo for Box<dyn Foo> {}
fn main() {}
@@ -1,6 +1,6 @@
use std::cell::Cell;
use std::rc::Rc;
//@ ignore-parallel-frontend query cycle
fn send<T: Send>(_: T) {}
fn main() {}
@@ -1,5 +1,5 @@
#![feature(trait_alias)]
//@ ignore-parallel-frontend query cycle
trait T1 = T2;
//~^ ERROR cycle detected when computing the implied predicates of `T1`
@@ -1,5 +1,5 @@
//@ revisions: feature gated
//@ ignore-parallel-frontend query cycle
#![cfg_attr(feature, feature(lazy_type_alias))]
#![allow(incomplete_features)]
+1 -1
View File
@@ -1,6 +1,6 @@
//@ build-fail
//@ compile-flags: -Zmir-opt-level=3
//@ ignore-parallel-frontend post-monomorphization errors
fn foo<T>() {
if false {
const { panic!() } //~ ERROR E0080
@@ -1,6 +1,6 @@
//@ normalize-stderr: "[[:xdigit:]]{2} __ ([[:xdigit:]]{2}\s){2}" -> "HEX_DUMP"
#![feature(core_intrinsics)]
//@ ignore-parallel-frontend different alloc ids
const RAW_EQ_PADDING: bool = unsafe {
std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
//~^ ERROR requires initialized memory
+1 -1
View File
@@ -1,5 +1,5 @@
const FOO: usize = FOO; //~ ERROR E0391
//@ ignore-parallel-frontend query cycle
fn main() {
let _x: [u8; FOO]; // caused stack overflow prior to fix
let _y: usize = 1 + {
+1 -1
View File
@@ -1,5 +1,5 @@
#![allow(warnings)]
//@ ignore-parallel-frontend query cycle
trait Trait<T> {
fn foo(_: T) {}
}
@@ -3,7 +3,7 @@
#![move_size_limit = "1000"]
//@ build-fail
//@ only-64bit
//@ ignore-parallel-frontend post-monomorphization errors
//@ edition:2018
//@ compile-flags: -Zmir-opt-level=1
@@ -1,5 +1,5 @@
//@ build-fail
//@ ignore-parallel-frontend post-monomorphization errors
#![feature(large_assignments)]
#![move_size_limit = "1000"]
#![deny(large_assignments)]
@@ -13,7 +13,7 @@
//! ```
//!
//! We want the diagnostics to point to the relevant user code.
//@ ignore-parallel-frontend post-monomorphization errors
//@ build-fail
//@ compile-flags: -Zmir-opt-level=1 -Zinline-mir
@@ -5,7 +5,7 @@
//@ only-64bit
//@ revisions: attribute option
//@ [option]compile-flags: -Zmove-size-limit=1000
//@ ignore-parallel-frontend post-monomorphization errors
//@ edition:2018
//@ compile-flags: -Zmir-opt-level=0
@@ -1,5 +1,5 @@
//@ build-fail
//@ ignore-parallel-frontend post-monomorphization errors
#![feature(large_assignments)]
#![move_size_limit = "1000"]
#![deny(large_assignments)]
@@ -1,7 +1,7 @@
#![warn(unused)]
#![allow(dead_code)]
#![deny(non_snake_case)]
//@ ignore-parallel-frontend `note`s on different source lines
mod foo {
pub enum Foo { Foo }
}
@@ -2,7 +2,7 @@
//@ compile-flags: --force-warn unused_variables
//@ compile-flags: --force-warn unused_mut
//@ check-pass
//@ ignore-parallel-frontend `note`s on different source lines
fn expect_early_pass_lint() {
#[expect(while_true)]
while true {
+1 -1
View File
@@ -3,7 +3,7 @@
#![deny(unused_assignments)]
#![allow(dead_code, non_camel_case_types, trivial_numeric_casts, dropping_copy_types)]
#![feature(intrinsics)]
//@ ignore-parallel-frontend `note`s on different source lines
use std::ops::AddAssign;
fn f1(x: isize) {
@@ -1,5 +1,5 @@
//@ edition:2021
//@ ignore-parallel-frontend query cycle
struct AnyOption<T>(T);
impl<T> AnyOption<T> {
const NONE: Option<T> = None;

Some files were not shown because too many files have changed in this diff Show More