From de351814b37907ccadf3cb503218b340698e394d Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Tue, 17 Feb 2026 13:53:43 +0000 Subject: [PATCH 1/6] Create x86_64-unknown-linux-gnu{m,t}san target which enables {M,T}SAN by default Similar like we've done it for `x86_64-unknown-linux-gnuasan`, in order to distribute sanitizer instrumented standard libraries without introducing new rustc flags, this adds a new dedicated target. With the target, we can distribute the instrumented standard libraries through a separate rustup component. --- compiler/rustc_target/src/spec/mod.rs | 2 + .../targets/x86_64_unknown_linux_gnumsan.rs | 16 ++++++ .../targets/x86_64_unknown_linux_gnutsan.rs | 16 ++++++ src/bootstrap/src/core/build_steps/llvm.rs | 2 + src/bootstrap/src/core/sanity.rs | 2 + .../host-x86_64/dist-various-2/Dockerfile | 2 + src/doc/rustc/src/SUMMARY.md | 2 + src/doc/rustc/src/platform-support.md | 2 + .../x86_64-unknown-linux-gnumsan.md | 56 +++++++++++++++++++ .../x86_64-unknown-linux-gnutsan.md | 56 +++++++++++++++++++ tests/assembly-llvm/targets/targets-elf.rs | 6 ++ 11 files changed, 162 insertions(+) create mode 100644 compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnumsan.rs create mode 100644 compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnutsan.rs create mode 100644 src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnumsan.md create mode 100644 src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnutsan.md diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 77cc6dd1036c8..6682361a92feb 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1815,6 +1815,8 @@ supported_targets! { ("x86_64-pc-cygwin", x86_64_pc_cygwin), ("x86_64-unknown-linux-gnuasan", x86_64_unknown_linux_gnuasan), + ("x86_64-unknown-linux-gnumsan", x86_64_unknown_linux_gnumsan), + ("x86_64-unknown-linux-gnutsan", x86_64_unknown_linux_gnutsan), } /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]> diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnumsan.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnumsan.rs new file mode 100644 index 0000000000000..377aae8bf0732 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnumsan.rs @@ -0,0 +1,16 @@ +use crate::spec::{SanitizerSet, Target, TargetMetadata}; + +pub(crate) fn target() -> Target { + let mut base = super::x86_64_unknown_linux_gnu::target(); + base.metadata = TargetMetadata { + description: Some( + "64-bit Linux (kernel 3.2+, glibc 2.17+) with MSAN enabled by default".into(), + ), + tier: Some(2), + host_tools: Some(false), + std: Some(true), + }; + base.supported_sanitizers = SanitizerSet::MEMORY; + base.default_sanitizers = SanitizerSet::MEMORY; + base +} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnutsan.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnutsan.rs new file mode 100644 index 0000000000000..bbe377ca74a68 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnutsan.rs @@ -0,0 +1,16 @@ +use crate::spec::{SanitizerSet, Target, TargetMetadata}; + +pub(crate) fn target() -> Target { + let mut base = super::x86_64_unknown_linux_gnu::target(); + base.metadata = TargetMetadata { + description: Some( + "64-bit Linux (kernel 3.2+, glibc 2.17+) with TSAN enabled by default".into(), + ), + tier: Some(2), + host_tools: Some(false), + std: Some(true), + }; + base.supported_sanitizers = SanitizerSet::THREAD; + base.default_sanitizers = SanitizerSet::THREAD; + base +} diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 0c607cb6ba6f3..d7480fe08e464 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1552,6 +1552,8 @@ fn supported_sanitizers( &["asan", "dfsan", "lsan", "msan", "safestack", "tsan", "rtsan"], ), "x86_64-unknown-linux-gnuasan" => common_libs("linux", "x86_64", &["asan"]), + "x86_64-unknown-linux-gnumsan" => common_libs("linux", "x86_64", &["msan"]), + "x86_64-unknown-linux-gnutsan" => common_libs("linux", "x86_64", &["tsan"]), "x86_64-unknown-linux-musl" => { common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index ca8af279b92bc..c4a6b68aedee8 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -37,6 +37,8 @@ pub struct Finder { /// when the newly-bumped stage 0 compiler now knows about the formerly-missing targets. const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined + "x86_64-unknown-linux-gnumsan", + "x86_64-unknown-linux-gnutsan", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index dacf3c0db2026..b655fe78bf8c4 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -126,6 +126,8 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-musl ENV TARGETS_SANITIZERS=x86_64-unknown-linux-gnuasan +ENV TARGETS_SANITIZERS=$TARGETS_SANITIZERS,x86_64-unknown-linux-gnumsan +ENV TARGETS_SANITIZERS=$TARGETS_SANITIZERS,x86_64-unknown-linux-gnutsan # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 # we need asm in the search path for gcc-9 (for gnux32) but not in the search path of the diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 9049828c8b121..cc10f476780c5 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -155,5 +155,7 @@ - [x86_64-unknown-linux-none](platform-support/x86_64-unknown-linux-none.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) - [x86_64-unknown-linux-gnuasan](platform-support/x86_64-unknown-linux-gnuasan.md) + - [x86_64-unknown-linux-gnumsan](platform-support/x86_64-unknown-linux-gnumsan.md) + - [x86_64-unknown-linux-gnutsan](platform-support/x86_64-unknown-linux-gnutsan.md) - [xtensa-\*-none-elf](platform-support/xtensa.md) - [\*-nuttx-\*](platform-support/nuttx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index a8b2111a901e4..26dd6b31b8991 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -216,6 +216,8 @@ target | std | notes [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android [`x86_64-unknown-linux-gnuasan`](platform-support/x86_64-unknown-linux-gnuasan.md) | ✓ | 64-bit Linux (kernel 3.2+, glibc 2.17+) with ASAN enabled by default +[`x86_64-unknown-linux-gnumsan`](platform-support/x86_64-unknown-linux-gnumsan.md) | ✓ | 64-bit Linux (kernel 3.2+, glibc 2.17+) with MSAN enabled by default +[`x86_64-unknown-linux-gnutsan`](platform-support/x86_64-unknown-linux-gnutsan.md) | ✓ | 64-bit Linux (kernel 3.2+, glibc 2.17+) with TSAN enabled by default [`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15+, glibc 2.27) [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat diff --git a/src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnumsan.md b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnumsan.md new file mode 100644 index 0000000000000..3b56436d0a1c5 --- /dev/null +++ b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnumsan.md @@ -0,0 +1,56 @@ +# `x86_64-unknown-linux-gnumsan` + +**Tier: 2** + +Target mirroring `x86_64-unknown-linux-gnu` with MemorySanitizer enabled by +default. +The goal of this target is to allow shipping MSAN-instrumented standard +libraries through rustup, enabling a fully instrumented binary without requiring +nightly features (build-std). +Once build-std stabilizes, this target is no longer needed and will be removed. + +## Target maintainers + +- [@jakos-sec](https://github.com/jakos-sec) +- [@1c3t3a](https://github.com/1c3t3a) +- [@rust-lang/project-exploit-mitigations][project-exploit-mitigations] + +## Requirements + +The target is for cross-compilation only. Host tools are not supported, since +there is no need to have the host tools instrumented with MSAN. std is fully +supported. + +In all other aspects the target is equivalent to `x86_64-unknown-linux-gnu`. + +## Building the target + +The target can be built by enabling it for a rustc build: + +```toml +[build] +target = ["x86_64-unknown-linux-gnumsan"] +``` + +## Building Rust programs + +Rust programs can be compiled by adding this target via rustup: + +```sh +$ rustup target add x86_64-unknown-linux-gnumsan +``` + +and then compiling with the target: + +```sh +$ rustc foo.rs --target x86_64-unknown-linux-gnumsan +``` + +## Testing + +Created binaries will run on Linux without any external requirements. + +## Cross-compilation toolchains and C code + +The target supports C code and should use the same toolchain target as +`x86_64-unknown-linux-gnu`. diff --git a/src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnutsan.md b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnutsan.md new file mode 100644 index 0000000000000..71488f476cd5a --- /dev/null +++ b/src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnutsan.md @@ -0,0 +1,56 @@ +# `x86_64-unknown-linux-gnutsan` + +**Tier: 2** + +Target mirroring `x86_64-unknown-linux-gnu` with ThreadSanitizer enabled by +default. +The goal of this target is to allow shipping TSAN-instrumented standard +libraries through rustup, enabling a fully instrumented binary without requiring +nightly features (build-std). +Once build-std stabilizes, this target is no longer needed and will be removed. + +## Target maintainers + +- [@jakos-sec](https://github.com/jakos-sec) +- [@1c3t3a](https://github.com/1c3t3a) +- [@rust-lang/project-exploit-mitigations][project-exploit-mitigations] + +## Requirements + +The target is for cross-compilation only. Host tools are not supported, since +there is no need to have the host tools instrumented with TSAN. std is fully +supported. + +In all other aspects the target is equivalent to `x86_64-unknown-linux-gnu`. + +## Building the target + +The target can be built by enabling it for a rustc build: + +```toml +[build] +target = ["x86_64-unknown-linux-gnutsan"] +``` + +## Building Rust programs + +Rust programs can be compiled by adding this target via rustup: + +```sh +$ rustup target add x86_64-unknown-linux-gnutsan +``` + +and then compiling with the target: + +```sh +$ rustc foo.rs --target x86_64-unknown-linux-gnutsan +``` + +## Testing + +Created binaries will run on Linux without any external requirements. + +## Cross-compilation toolchains and C code + +The target supports C code and should use the same toolchain target as +`x86_64-unknown-linux-gnu`. diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index b7deb6686cfe1..ce6629b4f27ce 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -709,6 +709,12 @@ //@ revisions: x86_64_unknown_linux_gnuasan //@ [x86_64_unknown_linux_gnuasan] compile-flags: --target x86_64-unknown-linux-gnuasan //@ [x86_64_unknown_linux_gnuasan] needs-llvm-components: x86 +//@ revisions: x86_64_unknown_linux_gnumsan +//@ [x86_64_unknown_linux_gnumsan] compile-flags: --target x86_64-unknown-linux-gnumsan +//@ [x86_64_unknown_linux_gnumsan] needs-llvm-components: x86 +//@ revisions: x86_64_unknown_linux_gnutsan +//@ [x86_64_unknown_linux_gnutsan] compile-flags: --target x86_64-unknown-linux-gnutsan +//@ [x86_64_unknown_linux_gnutsan] needs-llvm-components: x86 //@ revisions: x86_64_unknown_linux_musl //@ [x86_64_unknown_linux_musl] compile-flags: --target x86_64-unknown-linux-musl //@ [x86_64_unknown_linux_musl] needs-llvm-components: x86 From 9975d4760d1888a7cbd4bd9acfd26101792a3bcf Mon Sep 17 00:00:00 2001 From: "Andrew V. Teylu" Date: Thu, 19 Mar 2026 10:27:36 +0000 Subject: [PATCH 2/6] Reorder inline asm operands in pretty printer to satisfy grammar constraints After macro expansion, named `asm!` operands are converted to positional operands and the template string uses numeric indices. However, the pretty printer previously emitted operands in their original AST order, which could place positional (formerly named) register-class operands after explicit register operands. This violates the `asm!` grammar rule that positional arguments cannot follow explicit register arguments, causing the expanded output from `rustc -Zunpretty=expanded` to fail to reparse. When reordering is needed, the fix partitions operands into non-explicit and explicit register groups, emits non-explicit operands first, then explicit register operands, and remaps template placeholder indices (`{N}`) to match the new positions. When operands are already correctly ordered, the original code path is used unchanged. Signed-off-by: Andrew V. Teylu --- compiler/rustc_ast_pretty/src/pprust/state.rs | 82 ++++++++++++++++++- tests/pretty/asm-operand-order.pp | 18 ++++ tests/pretty/asm-operand-order.rs | 13 +++ 3 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 tests/pretty/asm-operand-order.pp create mode 100644 tests/pretty/asm-operand-order.rs diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 4ba5dc541342a..92767f97c28ee 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1620,8 +1620,86 @@ impl<'a> State<'a> { Options(InlineAsmOptions), } - let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&asm.template))]; - args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o))); + // After macro expansion, named operands become positional. The grammar + // requires positional operands to precede explicit register operands, + // so we must reorder when any non-explicit operand follows an explicit + // one. When no reordering is needed, we use the original template + // string and operand order to avoid duplicating the Display logic in + // InlineAsmTemplatePiece. + let is_explicit_reg = |op: &InlineAsmOperand| -> bool { + match op { + InlineAsmOperand::In { reg, .. } + | InlineAsmOperand::Out { reg, .. } + | InlineAsmOperand::InOut { reg, .. } + | InlineAsmOperand::SplitInOut { reg, .. } => { + matches!(reg, InlineAsmRegOrRegClass::Reg(_)) + } + InlineAsmOperand::Const { .. } + | InlineAsmOperand::Sym { .. } + | InlineAsmOperand::Label { .. } => false, + } + }; + + // Check whether any non-explicit operand follows an explicit one. + let needs_reorder = { + let mut seen_explicit = false; + asm.operands.iter().any(|(op, _)| { + if is_explicit_reg(op) { + seen_explicit = true; + false + } else { + seen_explicit + } + }) + }; + + let mut args = if needs_reorder { + let mut non_explicit: Vec = Vec::new(); + let mut explicit: Vec = Vec::new(); + for (i, (op, _)) in asm.operands.iter().enumerate() { + if is_explicit_reg(op) { + explicit.push(i); + } else { + non_explicit.push(i); + } + } + + // Build old-index → new-index mapping for template renumbering. + let mut old_to_new = vec![0usize; asm.operands.len()]; + for (new_idx, &old_idx) in non_explicit.iter().chain(explicit.iter()).enumerate() { + old_to_new[old_idx] = new_idx; + } + + // Remap template placeholder indices and reuse the existing + // Display impl to build the template string. + let remapped: Vec<_> = asm + .template + .iter() + .map(|piece| match piece { + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => { + InlineAsmTemplatePiece::Placeholder { + operand_idx: old_to_new[*operand_idx], + modifier: *modifier, + span: *span, + } + } + other => other.clone(), + }) + .collect(); + + let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&remapped))]; + for &idx in &non_explicit { + args.push(AsmArg::Operand(&asm.operands[idx].0)); + } + for &idx in &explicit { + args.push(AsmArg::Operand(&asm.operands[idx].0)); + } + args + } else { + let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&asm.template))]; + args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o))); + args + }; for (abi, _) in &asm.clobber_abis { args.push(AsmArg::ClobberAbi(*abi)); } diff --git a/tests/pretty/asm-operand-order.pp b/tests/pretty/asm-operand-order.pp new file mode 100644 index 0000000000000..723191412d0f2 --- /dev/null +++ b/tests/pretty/asm-operand-order.pp @@ -0,0 +1,18 @@ +#![feature(prelude_import)] +#![no_std] +extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; +//@ pretty-mode:expanded +//@ pp-exact:asm-operand-order.pp +//@ only-x86_64 + +use std::arch::asm; + +pub fn main() { + unsafe { + asm!("{0}", in(reg) 4, out("rax") _); + asm!("{0}", in(reg) 4, out("rax") _, options(nostack)); + asm!("{0} {1}", in(reg) 4, in(reg) 5, out("rax") _); + } +} diff --git a/tests/pretty/asm-operand-order.rs b/tests/pretty/asm-operand-order.rs new file mode 100644 index 0000000000000..05a994e385441 --- /dev/null +++ b/tests/pretty/asm-operand-order.rs @@ -0,0 +1,13 @@ +//@ pretty-mode:expanded +//@ pp-exact:asm-operand-order.pp +//@ only-x86_64 + +use std::arch::asm; + +pub fn main() { + unsafe { + asm!("{val}", out("rax") _, val = in(reg) 4); + asm!("{val}", out("rax") _, val = in(reg) 4, options(nostack)); + asm!("{a} {b}", out("rax") _, a = in(reg) 4, b = in(reg) 5); + } +} From 23411ce1661a5496821419e3c685e3abd4493e1f Mon Sep 17 00:00:00 2001 From: "Andrew V. Teylu" Date: Mon, 23 Mar 2026 08:47:54 +0000 Subject: [PATCH 3/6] Refactor asm pretty-print operand reordering and broaden regression coverage Extract the inline asm operand reorder/remap logic into a dedicated helper so `print_inline_asm` stays focused on assembling the printed argument list. This keeps the reordered-template logic local to the AST pretty printer while making the main printing path easier to read. Also extend the pretty regression test with a `const` operand case. That checks that non-register operands other than `in(reg)` are also moved ahead of explicit register operands and that the remapped template indices still match the new operand order. Signed-off-by: Andrew V. Teylu --- compiler/rustc_ast_pretty/src/pprust/state.rs | 120 +++++++++--------- tests/pretty/asm-operand-order.pp | 1 + tests/pretty/asm-operand-order.rs | 1 + 3 files changed, 63 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 92767f97c28ee..4823189f7be3f 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1612,21 +1612,10 @@ impl<'a> State<'a> { ); } - fn print_inline_asm(&mut self, asm: &ast::InlineAsm) { - enum AsmArg<'a> { - Template(String), - Operand(&'a InlineAsmOperand), - ClobberAbi(Symbol), - Options(InlineAsmOptions), - } - - // After macro expansion, named operands become positional. The grammar - // requires positional operands to precede explicit register operands, - // so we must reorder when any non-explicit operand follows an explicit - // one. When no reordering is needed, we use the original template - // string and operand order to avoid duplicating the Display logic in - // InlineAsmTemplatePiece. - let is_explicit_reg = |op: &InlineAsmOperand| -> bool { + fn inline_asm_template_and_operands<'asm>( + asm: &'asm ast::InlineAsm, + ) -> (String, Vec<&'asm InlineAsmOperand>) { + fn is_explicit_reg(op: &InlineAsmOperand) -> bool { match op { InlineAsmOperand::In { reg, .. } | InlineAsmOperand::Out { reg, .. } @@ -1638,9 +1627,14 @@ impl<'a> State<'a> { | InlineAsmOperand::Sym { .. } | InlineAsmOperand::Label { .. } => false, } - }; + } - // Check whether any non-explicit operand follows an explicit one. + // After macro expansion, named operands become positional. The grammar + // requires positional operands to precede explicit register operands, + // so we must reorder when any non-explicit operand follows an explicit + // one. When no reordering is needed, we use the original template + // string and operand order to avoid duplicating the Display logic in + // InlineAsmTemplatePiece. let needs_reorder = { let mut seen_explicit = false; asm.operands.iter().any(|(op, _)| { @@ -1653,53 +1647,61 @@ impl<'a> State<'a> { }) }; - let mut args = if needs_reorder { - let mut non_explicit: Vec = Vec::new(); - let mut explicit: Vec = Vec::new(); - for (i, (op, _)) in asm.operands.iter().enumerate() { - if is_explicit_reg(op) { - explicit.push(i); - } else { - non_explicit.push(i); - } - } + if !needs_reorder { + let template = InlineAsmTemplatePiece::to_string(&asm.template); + let operands = asm.operands.iter().map(|(op, _)| op).collect(); + return (template, operands); + } - // Build old-index → new-index mapping for template renumbering. - let mut old_to_new = vec![0usize; asm.operands.len()]; - for (new_idx, &old_idx) in non_explicit.iter().chain(explicit.iter()).enumerate() { - old_to_new[old_idx] = new_idx; + let mut non_explicit = Vec::new(); + let mut explicit = Vec::new(); + for (i, (op, _)) in asm.operands.iter().enumerate() { + if is_explicit_reg(op) { + explicit.push(i); + } else { + non_explicit.push(i); } + } + let order = non_explicit.into_iter().chain(explicit).collect::>(); - // Remap template placeholder indices and reuse the existing - // Display impl to build the template string. - let remapped: Vec<_> = asm - .template - .iter() - .map(|piece| match piece { - InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => { - InlineAsmTemplatePiece::Placeholder { - operand_idx: old_to_new[*operand_idx], - modifier: *modifier, - span: *span, - } + // Build old-index -> new-index mapping for template renumbering. + let mut old_to_new = vec![0usize; asm.operands.len()]; + for (new_idx, old_idx) in order.iter().copied().enumerate() { + old_to_new[old_idx] = new_idx; + } + + // Remap template placeholder indices and reuse the existing Display + // impl to build the template string. + let remapped = asm + .template + .iter() + .map(|piece| match piece { + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => { + InlineAsmTemplatePiece::Placeholder { + operand_idx: old_to_new[*operand_idx], + modifier: *modifier, + span: *span, } - other => other.clone(), - }) - .collect(); + } + other => other.clone(), + }) + .collect::>(); + let template = InlineAsmTemplatePiece::to_string(&remapped); + let operands = order.iter().map(|&idx| &asm.operands[idx].0).collect(); + (template, operands) + } - let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&remapped))]; - for &idx in &non_explicit { - args.push(AsmArg::Operand(&asm.operands[idx].0)); - } - for &idx in &explicit { - args.push(AsmArg::Operand(&asm.operands[idx].0)); - } - args - } else { - let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&asm.template))]; - args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o))); - args - }; + fn print_inline_asm(&mut self, asm: &ast::InlineAsm) { + enum AsmArg<'a> { + Template(String), + Operand(&'a InlineAsmOperand), + ClobberAbi(Symbol), + Options(InlineAsmOptions), + } + + let (template, operands) = Self::inline_asm_template_and_operands(asm); + let mut args = vec![AsmArg::Template(template)]; + args.extend(operands.into_iter().map(AsmArg::Operand)); for (abi, _) in &asm.clobber_abis { args.push(AsmArg::ClobberAbi(*abi)); } diff --git a/tests/pretty/asm-operand-order.pp b/tests/pretty/asm-operand-order.pp index 723191412d0f2..949c18c6723a5 100644 --- a/tests/pretty/asm-operand-order.pp +++ b/tests/pretty/asm-operand-order.pp @@ -14,5 +14,6 @@ asm!("{0}", in(reg) 4, out("rax") _); asm!("{0}", in(reg) 4, out("rax") _, options(nostack)); asm!("{0} {1}", in(reg) 4, in(reg) 5, out("rax") _); + asm!("{0}", const 5, out("rax") _); } } diff --git a/tests/pretty/asm-operand-order.rs b/tests/pretty/asm-operand-order.rs index 05a994e385441..b0bdabd946787 100644 --- a/tests/pretty/asm-operand-order.rs +++ b/tests/pretty/asm-operand-order.rs @@ -9,5 +9,6 @@ pub fn main() { asm!("{val}", out("rax") _, val = in(reg) 4); asm!("{val}", out("rax") _, val = in(reg) 4, options(nostack)); asm!("{a} {b}", out("rax") _, a = in(reg) 4, b = in(reg) 5); + asm!("{val}", out("rax") _, val = const 5); } } From 91e4524bfe66a33d1a572750504cd5ac006d9b5e Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Thu, 26 Mar 2026 11:33:33 +0700 Subject: [PATCH 4/6] Link from `assert_matches` to `debug_assert_matches` This resolves a FIXME which was added in https://github.com/rust-lang/rust/pull/151423. --- library/core/src/macros/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 49e1acd0b90fb..7f35e94d3df30 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -124,8 +124,6 @@ macro_rules! assert_ne { }; } -// FIXME add back debug_assert_matches doc link after bootstrap. - /// Asserts that an expression matches the provided pattern. /// /// This macro is generally preferable to `assert!(matches!(value, pattern))`, because it can print @@ -137,9 +135,11 @@ macro_rules! assert_ne { /// otherwise this macro will panic. /// /// Assertions are always checked in both debug and release builds, and cannot -/// be disabled. See `debug_assert_matches!` for assertions that are disabled in +/// be disabled. See [`debug_assert_matches!`] for assertions that are disabled in /// release builds by default. /// +/// [`debug_assert_matches!`]: crate::debug_assert_matches +/// /// On panic, this macro will print the value of the expression with its debug representation. /// /// Like [`assert!`], this macro has a second form, where a custom panic message can be provided. From 224eda09e6def37e6452e058f0a91ed9a1bcef9b Mon Sep 17 00:00:00 2001 From: ywxt Date: Thu, 26 Mar 2026 16:08:34 +0800 Subject: [PATCH 5/6] Add more tests for the parallel frontend --- .../assert-found_cycle-issue-115223.rs | 31 ++ ...default-trait-shadow-cycle-issue-151358.rs | 12 + ...ult-trait-shadow-cycle-issue-151358.stderr | 9 + ...neric-const-exprs-deadlock-issue-120757.rs | 127 ++++++ ...c-const-exprs-deadlock-issue-120757.stderr | 166 ++++++++ ...neric-const-exprs-deadlock-issue-134978.rs | 20 + ...c-const-exprs-deadlock-issue-134978.stderr | 29 ++ .../infer-unwrap-none-issue-120786.rs | 82 ++++ .../infer-unwrap-none-issue-120786.stderr | 256 ++++++++++++ .../nested-type-alias-cycle-issue-129911.rs | 89 ++++ ...ested-type-alias-cycle-issue-129911.stderr | 391 ++++++++++++++++++ ...ursive-impl-trait-deadlock-issue-129912.rs | 97 +++++ ...ve-impl-trait-deadlock-issue-129912.stderr | 137 ++++++ .../recursive-struct-oncelock-issue-151226.rs | 9 + ...ursive-struct-oncelock-issue-151226.stderr | 14 + .../recursive-trait-fn-sig-issue-142064.rs | 18 + ...recursive-trait-fn-sig-issue-142064.stderr | 114 +++++ ...-type-with-transmutability-issue-120759.rs | 26 ++ ...e-with-transmutability-issue-120759.stderr | 35 ++ 19 files changed, 1662 insertions(+) create mode 100644 tests/ui/parallel-rustc/assert-found_cycle-issue-115223.rs create mode 100644 tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.rs create mode 100644 tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.stderr create mode 100644 tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.rs create mode 100644 tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.stderr create mode 100644 tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-134978.rs create mode 100644 tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-134978.stderr create mode 100644 tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.rs create mode 100644 tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.stderr create mode 100644 tests/ui/parallel-rustc/nested-type-alias-cycle-issue-129911.rs create mode 100644 tests/ui/parallel-rustc/nested-type-alias-cycle-issue-129911.stderr create mode 100644 tests/ui/parallel-rustc/recursive-impl-trait-deadlock-issue-129912.rs create mode 100644 tests/ui/parallel-rustc/recursive-impl-trait-deadlock-issue-129912.stderr create mode 100644 tests/ui/parallel-rustc/recursive-struct-oncelock-issue-151226.rs create mode 100644 tests/ui/parallel-rustc/recursive-struct-oncelock-issue-151226.stderr create mode 100644 tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.rs create mode 100644 tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.stderr create mode 100644 tests/ui/parallel-rustc/recursive-type-with-transmutability-issue-120759.rs create mode 100644 tests/ui/parallel-rustc/recursive-type-with-transmutability-issue-120759.stderr diff --git a/tests/ui/parallel-rustc/assert-found_cycle-issue-115223.rs b/tests/ui/parallel-rustc/assert-found_cycle-issue-115223.rs new file mode 100644 index 0000000000000..96a11720abdff --- /dev/null +++ b/tests/ui/parallel-rustc/assert-found_cycle-issue-115223.rs @@ -0,0 +1,31 @@ +// Test for #115223, which causes a deadlock bug without finding the cycle +//@ build-pass +#![crate_name = "foo"] + +use std::ops; + +pub struct Foo; + +impl Foo { + pub fn foo(&mut self) {} +} + +pub struct Bar { + foo: Foo, +} + +impl ops::Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &self.foo + } +} + +impl ops::DerefMut for Bar { + fn deref_mut(&mut self) -> &mut Foo { + &mut self.foo + } +} + +fn main() {} diff --git a/tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.rs b/tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.rs new file mode 100644 index 0000000000000..8bc11ce31d195 --- /dev/null +++ b/tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.rs @@ -0,0 +1,12 @@ +// Test for #151358, assertion failed: !worker_thread.is_null() +//~^ ERROR cycle detected when looking up span for `Default` +// +//@ compile-flags: -Z threads=2 +//@ compare-output-by-lines + +trait Default {} +use std::num::NonZero; +fn main() { + NonZero(); + todo!(); +} diff --git a/tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.stderr b/tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.stderr new file mode 100644 index 0000000000000..9c1d7b1de33a5 --- /dev/null +++ b/tests/ui/parallel-rustc/default-trait-shadow-cycle-issue-151358.stderr @@ -0,0 +1,9 @@ +error[E0391]: cycle detected when looking up span for `Default` + | + = note: ...which immediately requires looking up span for `Default` again + = note: cycle used when perform lints prior to AST lowering + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.rs b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.rs new file mode 100644 index 0000000000000..ef484c38ccad6 --- /dev/null +++ b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.rs @@ -0,0 +1,127 @@ +// Test for #120757, deadlock due to query cycle + +#![feature(generic_const_exprs)] + +trait TensorDimension { + const DIM: usize; + const ISSCALAR: bool = Self::DIM == 0; + fn is_scalar(&self) -> bool { + Self::ISSCALAR + } +} + +trait TensorSize: TensorDimension { + fn size(&self) -> [usize; Self::DIM]; + fn inbounds(&self, index: [usize; Self::DIM]) -> bool { + index.iter().zip(self.size().iter()).all(|(i, s)| i < s) + } +} + +trait Broadcastable: TensorSize + Sized { + type Element; + fn bget(&self, index: [usize; Self::DIM]) -> Option; + fn lazy_updim( + &self, + size: [usize; NEWDIM], + ) -> LazyUpdim { + assert!( + NEWDIM >= Self::DIM, + "Updimmed tensor cannot have fewer indices than the initial one." + ); + LazyUpdim { size, reference: &self } + } + fn bmap T>(&self, foo: F) -> BMap { + BMap { reference: self, closure: foo } + } +} + +struct LazyUpdim<'a, T: Broadcastable, const OLDDIM: usize, const DIM: usize> { + size: [usize; DIM], + reference: &'a T, +} + +impl<'a, T: Broadcastable, const DIM: usize> TensorDimension for LazyUpdim<'a, T, { T::DIM }, DIM> { + const DIM: usize = DIM; +} +impl<'a, T: Broadcastable, const DIM: usize> TensorSize for LazyUpdim<'a, T, { T::DIM }, DIM> { + fn size(&self) -> [usize; DIM] { + //~^ ERROR method not compatible with trait + self.size + } +} +impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> { + type Element = T::Element; + fn bget(&self, index: [usize; DIM]) -> Option { + //~^ ERROR method not compatible with trait + assert!(DIM >= T::DIM); + if !self.inbounds(index) { + //~^ ERROR unconstrained generic constant + //~| ERROR mismatched types + return None; + } + let size = self.size(); + //~^ ERROR unconstrained generic constant + + let newindex: [usize; T::DIM] = Default::default(); + //~^ ERROR the trait bound `[usize; T::DIM]: Default` is not satisfied + self.reference.bget(newindex) + } +} + +struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> { + reference: &'a T, + closure: F, +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension + for BMap<'a, R, T, F, DIM> +{ + const DIM: usize = DIM; +} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize + for BMap<'a, R, T, F, DIM> +{ + fn size(&self) -> [usize; DIM] { + //~^ ERROR method not compatible with trait + self.reference.size() + //~^ ERROR unconstrained generic constant + //~| ERROR mismatched types + } +} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> Broadcastable + for BMap<'a, R, T, F, DIM> +{ + type Element = R; + fn bget(&self, index: [usize; DIM]) -> Option { + //~^ ERROR method not compatible with trait + self.reference.bget(index).map(ns_window) + //~^ ERROR unconstrained generic constant + //~| ERROR mismatched types + //~| ERROR cannot find value `ns_window` in this scope + } +} + +impl TensorDimension for Vec { + const DIM: usize = 1; +} +impl TensorSize for Vec { + fn size(&self) -> [usize; 1] { + //~^ ERROR method not compatible with trait + [self.len()] + } +} +impl Broadcastable for Vec { + type Element = T; + fn bget(&self, index: [usize; 1]) -> Option { + //~^ ERROR method not compatible with trait + self.get(index[0]).cloned() + } +} + +fn main() { + let v = vec![1, 2, 3]; + let bv = v.lazy_updim([3, 4]); + let bbv = bv.bmap(|x| x * x); + + println!("The size of v is {:?}", bbv.bget([0, 2]).expect("Out of bounds.")); +} diff --git a/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.stderr b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.stderr new file mode 100644 index 0000000000000..4e8cbdb319511 --- /dev/null +++ b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.stderr @@ -0,0 +1,166 @@ +error[E0425]: cannot find value `ns_window` in this scope + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:97:40 + | +LL | self.reference.bget(index).map(ns_window) + | ^^^^^^^^^ not found in this scope + +error[E0308]: method not compatible with trait + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:47:5 + | +LL | fn size(&self) -> [usize; DIM] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` + +error[E0308]: method not compatible with trait + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:54:5 + | +LL | fn bget(&self, index: [usize; DIM]) -> Option { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` + +error[E0308]: method not compatible with trait + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:84:5 + | +LL | fn size(&self) -> [usize; DIM] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` + +error[E0308]: method not compatible with trait + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:95:5 + | +LL | fn bget(&self, index: [usize; DIM]) -> Option { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` + +error[E0308]: method not compatible with trait + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:108:5 + | +LL | fn size(&self) -> [usize; 1] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `1` + | + = note: expected constant `Self::DIM` + found constant `1` + +error[E0308]: method not compatible with trait + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:115:5 + | +LL | fn bget(&self, index: [usize; 1]) -> Option { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `1` + | + = note: expected constant `Self::DIM` + found constant `1` + +error: unconstrained generic constant + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:57:13 + | +LL | if !self.inbounds(index) { + | ^^^^ + | +note: required by a bound in `TensorSize::inbounds` + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:15:39 + | +LL | fn inbounds(&self, index: [usize; Self::DIM]) -> bool { + | ^^^^^^^^^ required by this bound in `TensorSize::inbounds` +help: try adding a `where` bound + | +LL | fn bget(&self, index: [usize; DIM]) -> Option where [(); Self::DIM]: { + | ++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:57:27 + | +LL | if !self.inbounds(index) { + | ^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` + +error: unconstrained generic constant + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:62:25 + | +LL | let size = self.size(); + | ^^^^ + | +note: required by a bound in `TensorSize::size` + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:14:31 + | +LL | fn size(&self) -> [usize; Self::DIM]; + | ^^^^^^^^^ required by this bound in `TensorSize::size` +help: try adding a `where` bound + | +LL | fn bget(&self, index: [usize; DIM]) -> Option where [(); Self::DIM]: { + | ++++++++++++++++++++++ + +error[E0277]: the trait bound `[usize; T::DIM]: Default` is not satisfied + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:65:41 + | +LL | let newindex: [usize; T::DIM] = Default::default(); + | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[usize; T::DIM]` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> where [usize; T::DIM]: Default { + | ++++++++++++++++++++++++++++++ + +error: unconstrained generic constant + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:86:24 + | +LL | self.reference.size() + | ^^^^ + | +note: required by a bound in `TensorSize::size` + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:14:31 + | +LL | fn size(&self) -> [usize; Self::DIM]; + | ^^^^^^^^^ required by this bound in `TensorSize::size` +help: try adding a `where` bound + | +LL | fn size(&self) -> [usize; DIM] where [(); Self::DIM]: { + | ++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:86:9 + | +LL | self.reference.size() + | ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM` + | + = note: expected constant `DIM` + found constant `Self::DIM` + +error: unconstrained generic constant + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:97:9 + | +LL | self.reference.bget(index).map(ns_window) + | ^^^^^^^^^^^^^^ + | +note: required by a bound in `Broadcastable::bget` + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:22:35 + | +LL | fn bget(&self, index: [usize; Self::DIM]) -> Option; + | ^^^^^^^^^ required by this bound in `Broadcastable::bget` +help: try adding a `where` bound + | +LL | fn bget(&self, index: [usize; DIM]) -> Option where [(); Self::DIM]: { + | ++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:97:29 + | +LL | self.reference.bget(index).map(ns_window) + | ^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0277, E0308, E0425. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-134978.rs b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-134978.rs new file mode 100644 index 0000000000000..ccc03a44cf70b --- /dev/null +++ b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-134978.rs @@ -0,0 +1,20 @@ +// Test for #134978, deadlock detected as we're unable to find a query cycle to break + +#![feature(generic_const_exprs)] + +pub struct Struct; + +impl Struct { + pub const OK: usize = 0; +} + +fn main() { + function::<0>(); +} + +fn function() +where + [(); Struct::<{ NUM_CARDS + 0 }>::OK]:, + //~^ ERROR cycle detected when building an abstract representation +{ +} diff --git a/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-134978.stderr b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-134978.stderr new file mode 100644 index 0000000000000..a27c1079bd816 --- /dev/null +++ b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-134978.stderr @@ -0,0 +1,29 @@ +error[E0391]: cycle detected when building an abstract representation for `function::{constant#0}` + --> $DIR/generic-const-exprs-deadlock-issue-134978.rs:17:10 + | +LL | [(); Struct::<{ NUM_CARDS + 0 }>::OK]:, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires building THIR for `function::{constant#0}`... + --> $DIR/generic-const-exprs-deadlock-issue-134978.rs:17:10 + | +LL | [(); Struct::<{ NUM_CARDS + 0 }>::OK]:, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `function::{constant#0}`... + --> $DIR/generic-const-exprs-deadlock-issue-134978.rs:17:10 + | +LL | [(); Struct::<{ NUM_CARDS + 0 }>::OK]:, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires building an abstract representation for `function::{constant#0}`, completing the cycle +note: cycle used when checking that `function` is well-formed + --> $DIR/generic-const-exprs-deadlock-issue-134978.rs:15:1 + | +LL | / fn function() +LL | | where +LL | | [(); Struct::<{ NUM_CARDS + 0 }>::OK]:, + | |___________________________________________^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.rs b/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.rs new file mode 100644 index 0000000000000..f617e20804a2e --- /dev/null +++ b/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.rs @@ -0,0 +1,82 @@ +// Test for #120786, which causes an ice bug: infer: `None` + +fn no_err() { + |x: u32, y| x; + //~^ ERROR type annotations needed + let _ = String::from("x"); +} + +fn err() { + String::from("x".as_ref()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} + +fn arg_pat_closure_err() { + |x| String::from("x".as_ref()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} + +fn local_pat_closure_err() { + let _ = "x".as_ref(); + //~^ ERROR type annotations needed +} + +fn err_first_arg_pat() { + String::from("x".as_ref()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + |x: String| x; +} + +fn err_second_arg_pat() { + |x: String| x; + String::from("x".as_ref()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} + +fn err_mid_arg_pat() { + |x: String| x; + |x: String| x; + |x: String| x; + |x: String| x; + String::from("x".as_ref()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + |x: String| x; + |x: String| x; + |x: String| x; + |x: String| x; +} + +fn err_first_local_pat() { + String::from("x".as_ref()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + let _ = String::from("x"); +} + +fn err_second_local_pat() { + let _ = String::from("x"); + String::from("x".as_ref()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} + +fn err_mid_local_pat() { + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + String::from("x".as_ref()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); +} + +fn main() {} diff --git a/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.stderr b/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.stderr new file mode 100644 index 0000000000000..3be18fc59e737 --- /dev/null +++ b/tests/ui/parallel-rustc/infer-unwrap-none-issue-120786.stderr @@ -0,0 +1,256 @@ +error[E0282]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:4:14 + | +LL | |x: u32, y| x; + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | |x: u32, y: /* Type */| x; + | ++++++++++++ + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:10:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl From<&String> for String; + - impl From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:10:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:16:9 + | +LL | |x| String::from("x".as_ref()); + | ^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl From<&String> for String; + - impl From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:16:26 + | +LL | |x| String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL - |x| String::from("x".as_ref()); +LL + |x| String::from(>::as_ref("x")); + | + +error[E0283]: type annotations needed for `&_` + --> $DIR/infer-unwrap-none-issue-120786.rs:22:9 + | +LL | let _ = "x".as_ref(); + | ^ ------ type must be known at this point + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let _: &T = "x".as_ref(); + | ++++ + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:27:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl From<&String> for String; + - impl From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:27:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:35:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl From<&String> for String; + - impl From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:35:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:45:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl From<&String> for String; + - impl From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:45:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:55:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl From<&String> for String; + - impl From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:55:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:63:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl From<&String> for String; + - impl From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:63:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:73:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl From<&String> for String; + - impl From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/infer-unwrap-none-issue-120786.rs:73:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL - String::from("x".as_ref()); +LL + String::from(>::as_ref("x")); + | + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/parallel-rustc/nested-type-alias-cycle-issue-129911.rs b/tests/ui/parallel-rustc/nested-type-alias-cycle-issue-129911.rs new file mode 100644 index 0000000000000..1fd058db29d4c --- /dev/null +++ b/tests/ui/parallel-rustc/nested-type-alias-cycle-issue-129911.rs @@ -0,0 +1,89 @@ +// Test for #129911, deadlock detected as we're unable to find a query cycle to break + +fn main() { + type KooArc = Frc< + //~^ ERROR cannot find type `Frc` in this scope + { + { + { + {}; + } + type Frc = Frc<{}>::Arc;; + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + } + type Frc = Frc< + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + { + { + { + {}; + } + type Frc = Frc<{}>::Arc;; + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + } + type Frc = Frc< + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + { + { + { + {}; + } + type Frc = Frc<{}>::Arc;; + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + } + type Frc = Frc< + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + { + { + { + {}; + } + type Frc = Frc<{}>::Arc;; + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + } + type Frc = Frc< + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + { + { + { + { + {}; + } + type Frc = Frc<{}>::Arc;; + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + }; + } + type Frc = Frc< + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + { + { + { + {}; + }; + } + type Frc = Frc<{}>::Arc;; + //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cycle detected when expanding type alias + }, + >::Arc;; + }, + >::Arc;; + }, + >::Arc;; + }, + >::Arc;; + }, + >::Arc;; + }, + >::Arc; +} diff --git a/tests/ui/parallel-rustc/nested-type-alias-cycle-issue-129911.stderr b/tests/ui/parallel-rustc/nested-type-alias-cycle-issue-129911.stderr new file mode 100644 index 0000000000000..b1ece17479891 --- /dev/null +++ b/tests/ui/parallel-rustc/nested-type-alias-cycle-issue-129911.stderr @@ -0,0 +1,391 @@ +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:11:28 + | +LL | type Frc = Frc<{}>::Arc;; + | ^^^---- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:11:22 + | +LL | type Frc = Frc<{}>::Arc;; + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:11:28 + | +LL | type Frc = Frc<{}>::Arc;; + | ^^^^^^^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:11:17 + | +LL | type Frc = Frc<{}>::Arc;; + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:15:24 + | +LL | type Frc = Frc< + | ________________________^^^- + | | | + | | expected 0 generic arguments +... | +LL | | }, +LL | | >::Arc;; + | |_____________- help: remove the unnecessary generics + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:15:18 + | +LL | type Frc = Frc< + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:15:24 + | +LL | type Frc = Frc< + | ________________________^ +... | +LL | | }, +LL | | >::Arc;; + | |_____________^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:15:13 + | +LL | type Frc = Frc< + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:23:36 + | +LL | type Frc = Frc<{}>::Arc;; + | ^^^---- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:23:30 + | +LL | type Frc = Frc<{}>::Arc;; + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:23:36 + | +LL | type Frc = Frc<{}>::Arc;; + | ^^^^^^^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:23:25 + | +LL | type Frc = Frc<{}>::Arc;; + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:27:32 + | +LL | type Frc = Frc< + | ________________________________^^^- + | | | + | | expected 0 generic arguments +... | +LL | | }, +LL | | >::Arc;; + | |_____________________- help: remove the unnecessary generics + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:27:26 + | +LL | type Frc = Frc< + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:27:32 + | +LL | type Frc = Frc< + | ________________________________^ +... | +LL | | }, +LL | | >::Arc;; + | |_____________________^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:27:21 + | +LL | type Frc = Frc< + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:35:44 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^---- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:35:38 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:35:44 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^^^^^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:35:33 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:39:40 + | +LL | ... type Frc = Frc< + | __________________________________^^^- + | | | + | | expected 0 generic arguments +... | +LL | | ... }, +LL | | ... >::Arc;; + | |_______________________- help: remove the unnecessary generics + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:39:34 + | +LL | ... type Frc = Frc< + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:39:40 + | +LL | ... type Frc = Frc< + | __________________________________^ +... | +LL | | ... }, +LL | | ... >::Arc;; + | |_______________________^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:39:29 + | +LL | ... type Frc = Frc< + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:47:52 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^---- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:47:46 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:47:52 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^^^^^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:47:41 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:51:48 + | +LL | ... type Frc = Frc< + | __________________________________^^^- + | | | + | | expected 0 generic arguments +... | +LL | | ... }, +LL | | ... >::Arc;; + | |_______________________- help: remove the unnecessary generics + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:51:42 + | +LL | ... type Frc = Frc< + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:51:48 + | +LL | ... type Frc = Frc< + | __________________________________^ +... | +LL | | ... }, +LL | | ... >::Arc;; + | |_______________________^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:51:37 + | +LL | ... type Frc = Frc< + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:60:64 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^---- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:60:58 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:60:64 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^^^^^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:60:53 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:65:56 + | +LL | ... type Frc = Frc< + | __________________________________^^^- + | | | + | | expected 0 generic arguments +... | +LL | | ... }, +LL | | ... >::Arc;; + | |_______________________- help: remove the unnecessary generics + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:65:50 + | +LL | ... type Frc = Frc< + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:65:56 + | +LL | ... type Frc = Frc< + | __________________________________^ +... | +LL | | ... }, +LL | | ... >::Arc;; + | |_______________________^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:65:45 + | +LL | ... type Frc = Frc< + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/nested-type-alias-cycle-issue-129911.rs:74:64 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^---- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/nested-type-alias-cycle-issue-129911.rs:74:58 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^ + +error[E0391]: cycle detected when expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` + --> $DIR/nested-type-alias-cycle-issue-129911.rs:74:64 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^^^^^ + | + = note: ...which immediately requires expanding type alias `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when checking that `main::KooArc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc::{constant#0}::Frc` is well-formed + --> $DIR/nested-type-alias-cycle-issue-129911.rs:74:53 + | +LL | ... type Frc = Frc<{}>::Arc;; + | ^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0433]: cannot find type `Frc` in this scope + --> $DIR/nested-type-alias-cycle-issue-129911.rs:4:19 + | +LL | type KooArc = Frc< + | ^^^ use of undeclared type `Frc` + +error: aborting due to 23 previous errors + +Some errors have detailed explanations: E0107, E0391, E0433. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/parallel-rustc/recursive-impl-trait-deadlock-issue-129912.rs b/tests/ui/parallel-rustc/recursive-impl-trait-deadlock-issue-129912.rs new file mode 100644 index 0000000000000..5b0bd19fff0b0 --- /dev/null +++ b/tests/ui/parallel-rustc/recursive-impl-trait-deadlock-issue-129912.rs @@ -0,0 +1,97 @@ +// Test for #129912, which causes a deadlock bug without finding a cycle + +#![feature(generators)] +//~^ ERROR feature has been removed +#![allow(unconditional_recursion)] + +fn option(i: i32) -> impl Sync { + if generator_sig() < 0 { None } else { Sized((option(i - Sized), i)) } + //~^ ERROR expected value, found trait `Sized` + //~| ERROR expected function, tuple struct or tuple variant, found trait `Sized` +} + +fn tuple() -> impl Sized { + (tuple(),) +} + +fn array() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + [array()] +} + +fn ptr() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + &ptr() as *const impl Sized + //~^ ERROR `impl Trait` is not allowed in cast expression types +} + +fn fn_ptr() -> impl Sized { + fn_ptr as fn() -> _ +} + +fn closure_capture() -> impl Sized { + let x = closure_capture(); + move || { + x; + } +} + +fn closure_ref_capture() -> impl Sized { + let x = closure_ref_capture(); + move || { + &x; + } +} + +fn closure_sig() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + || closure_sig() +} + +fn generator_sig() -> impl Sized { + || i + //~^ ERROR cannot find value `i` in this scope +} + +fn generator_capture() -> impl i32 { + //~^ ERROR expected trait, found builtin type `i32` + let x = 1(); + move || { + yield; + //~^ ERROR yield syntax is experimental + //~| ERROR yield syntax is experimental + //~| ERROR `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + x; + } +} + +fn substs_change() -> impl Sized { + (substs_change::<&T>(),) +} + +fn generator_hold() -> impl generator_capture { + //~^ ERROR expected trait, found function `generator_capture` + move || { + let x = (); + yield; + //~^ ERROR yield syntax is experimental + //~| ERROR yield syntax is experimental + //~| ERROR `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + x virtual ; + //~^ ERROR expected one of + } +} + +fn use_fn_ptr() -> impl Sized { + fn_ptr() +} + +fn mutual_recursion() -> impl Sync { + mutual_recursion_b() +} + +fn mutual_recursion_b() -> impl Sized { + mutual_recursion() +} + +fn main() {} diff --git a/tests/ui/parallel-rustc/recursive-impl-trait-deadlock-issue-129912.stderr b/tests/ui/parallel-rustc/recursive-impl-trait-deadlock-issue-129912.stderr new file mode 100644 index 0000000000000..420fb36d56003 --- /dev/null +++ b/tests/ui/parallel-rustc/recursive-impl-trait-deadlock-issue-129912.stderr @@ -0,0 +1,137 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found reserved keyword `virtual` + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:80:11 + | +LL | x virtual ; + | ^^^^^^^ expected one of 8 possible tokens + +error[E0557]: feature has been removed + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:3:12 + | +LL | #![feature(generators)] + | ^^^^^^^^^^ feature has been removed + | + = note: removed in 1.75.0; see for more information + = note: renamed to `coroutines` + +error[E0423]: expected value, found trait `Sized` + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:8:62 + | +LL | if generator_sig() < 0 { None } else { Sized((option(i - Sized), i)) } + | ^^^^^ not a value + +error[E0425]: cannot find value `i` in this scope + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:52:8 + | +LL | || i + | ^ not found in this scope + +error[E0404]: expected trait, found builtin type `i32` + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:56:32 + | +LL | fn generator_capture() -> impl i32 { + | ^^^ not a trait + +error[E0404]: expected trait, found function `generator_capture` + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:72:29 + | +LL | fn generator_hold() -> impl generator_capture { + | ^^^^^^^^^^^^^^^^^ not a trait + +error[E0658]: yield syntax is experimental + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:60:9 + | +LL | yield; + | ^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(yield_expr)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: yield syntax is experimental + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:76:9 + | +LL | yield; + | ^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(yield_expr)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0562]: `impl Trait` is not allowed in cast expression types + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:24:22 + | +LL | &ptr() as *const impl Sized + | ^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods + +error[E0658]: yield syntax is experimental + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:60:9 + | +LL | yield; + | ^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(yield_expr)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:60:9 + | +LL | yield; + | ^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | #[coroutine] move || { + | ++++++++++++ + +error[E0658]: yield syntax is experimental + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:76:9 + | +LL | yield; + | ^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(yield_expr)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:76:9 + | +LL | yield; + | ^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | #[coroutine] move || { + | ++++++++++++ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:17:15 + | +LL | fn array() -> _ { + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:22:13 + | +LL | fn ptr() -> _ { + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:46:21 + | +LL | fn closure_sig() -> _ { + | ^ not allowed in type signatures + +error[E0423]: expected function, tuple struct or tuple variant, found trait `Sized` + --> $DIR/recursive-impl-trait-deadlock-issue-129912.rs:8:44 + | +LL | if generator_sig() < 0 { None } else { Sized((option(i - Sized), i)) } + | ^^^^^ not a function, tuple struct or tuple variant + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0121, E0404, E0423, E0425, E0557, E0562, E0658. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/parallel-rustc/recursive-struct-oncelock-issue-151226.rs b/tests/ui/parallel-rustc/recursive-struct-oncelock-issue-151226.rs new file mode 100644 index 0000000000000..69cbd578325c5 --- /dev/null +++ b/tests/ui/parallel-rustc/recursive-struct-oncelock-issue-151226.rs @@ -0,0 +1,9 @@ +// Test for #151226, Unable to verify registry association +// +//@ compile-flags: -Z threads=2 +//@ compare-output-by-lines + +struct A(std::sync::OnceLock); +//~^ ERROR recursive type `A` has infinite size +static B: A<()> = todo!(); +fn main() {} diff --git a/tests/ui/parallel-rustc/recursive-struct-oncelock-issue-151226.stderr b/tests/ui/parallel-rustc/recursive-struct-oncelock-issue-151226.stderr new file mode 100644 index 0000000000000..2a51ee930779c --- /dev/null +++ b/tests/ui/parallel-rustc/recursive-struct-oncelock-issue-151226.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `A` has infinite size + --> $DIR/recursive-struct-oncelock-issue-151226.rs:6:1 + | +LL | struct A(std::sync::OnceLock); + | ^^^^^^^^^^^ ------------------------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct A(Box>); + | ++++ + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.rs b/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.rs new file mode 100644 index 0000000000000..5ae2f936333f6 --- /dev/null +++ b/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.rs @@ -0,0 +1,18 @@ +// Test for #142064, internal error: entered unreachable code +// +//@ compile-flags: -Zthreads=2 +//@ compare-output-by-lines + +#![crate_type = "rlib"] +trait A { fn foo() -> A; } +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| ERROR the trait `A` is not dyn compatible +trait B { fn foo() -> A; } +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| ERROR the trait `A` is not dyn compatible diff --git a/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.stderr b/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.stderr new file mode 100644 index 0000000000000..540f70ec1e15d --- /dev/null +++ b/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.stderr @@ -0,0 +1,114 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/recursive-trait-fn-sig-issue-142064.rs:7:23 + | +LL | trait A { fn foo() -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` (part of `#[warn(rust_2021_compatibility)]`) on by default +help: if this is a dyn-compatible trait, use `dyn` + | +LL | trait A { fn foo() -> dyn A; } + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/recursive-trait-fn-sig-issue-142064.rs:13:23 + | +LL | trait B { fn foo() -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: if this is a dyn-compatible trait, use `dyn` + | +LL | trait B { fn foo() -> dyn A; } + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/recursive-trait-fn-sig-issue-142064.rs:7:23 + | +LL | trait A { fn foo() -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: if this is a dyn-compatible trait, use `dyn` + | +LL | trait A { fn foo() -> dyn A; } + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/recursive-trait-fn-sig-issue-142064.rs:13:23 + | +LL | trait B { fn foo() -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: if this is a dyn-compatible trait, use `dyn` + | +LL | trait B { fn foo() -> dyn A; } + | +++ + +error[E0038]: the trait `A` is not dyn compatible + --> $DIR/recursive-trait-fn-sig-issue-142064.rs:7:23 + | +LL | trait A { fn foo() -> A; } + | ^ `A` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/recursive-trait-fn-sig-issue-142064.rs:7:14 + | +LL | trait A { fn foo() -> A; } + | - ^^^ ...because associated function `foo` has no `self` parameter + | | + | this trait is not dyn compatible... +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | trait A { fn foo(&self) -> A; } + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | trait A { fn foo() -> A where Self: Sized; } + | +++++++++++++++++ +help: you might have meant to use `Self` to refer to the implementing type + | +LL - trait A { fn foo() -> A; } +LL + trait A { fn foo() -> Self; } + | + +error[E0038]: the trait `A` is not dyn compatible + --> $DIR/recursive-trait-fn-sig-issue-142064.rs:13:23 + | +LL | trait B { fn foo() -> A; } + | ^ `A` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/recursive-trait-fn-sig-issue-142064.rs:7:14 + | +LL | trait A { fn foo() -> A; } + | - ^^^ ...because associated function `foo` has no `self` parameter + | | + | this trait is not dyn compatible... +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | trait A { fn foo(&self) -> A; } + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | trait A { fn foo() -> A where Self: Sized; } + | +++++++++++++++++ +help: you might have meant to use `Self` to refer to the implementing type + | +LL - trait B { fn foo() -> A; } +LL + trait B { fn foo() -> Self; } + | + +error: aborting due to 2 previous errors; 4 warnings emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/parallel-rustc/recursive-type-with-transmutability-issue-120759.rs b/tests/ui/parallel-rustc/recursive-type-with-transmutability-issue-120759.rs new file mode 100644 index 0000000000000..cee66985dd4a3 --- /dev/null +++ b/tests/ui/parallel-rustc/recursive-type-with-transmutability-issue-120759.rs @@ -0,0 +1,26 @@ +// Test for #120759, deadlock detected without any query + +#![crate_type = "lib"] +#![feature(transmutability)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + //~^ ERROR unresolved import `std::mem::BikeshedIntrinsicFrom` + pub struct Context; + + pub fn is_maybe_transmutable(&self, cpu: &mut CPU) + //~^ ERROR `self` parameter is only allowed in associated functions + //~| ERROR cannot find type `CPU` in this scope + where + Dst: BikeshedIntrinsicFrom, + { + } +} + +fn should_pad_explicitly_packed_field() { + #[repr(C)] + struct ExplicitlyPadded(ExplicitlyPadded); + //~^ ERROR recursive type `ExplicitlyPadded` has infinite size + + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/parallel-rustc/recursive-type-with-transmutability-issue-120759.stderr b/tests/ui/parallel-rustc/recursive-type-with-transmutability-issue-120759.stderr new file mode 100644 index 0000000000000..c21418c041165 --- /dev/null +++ b/tests/ui/parallel-rustc/recursive-type-with-transmutability-issue-120759.stderr @@ -0,0 +1,35 @@ +error: `self` parameter is only allowed in associated functions + --> $DIR/recursive-type-with-transmutability-issue-120759.rs:11:44 + | +LL | pub fn is_maybe_transmutable(&self, cpu: &mut CPU) + | ^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0432]: unresolved import `std::mem::BikeshedIntrinsicFrom` + --> $DIR/recursive-type-with-transmutability-issue-120759.rs:7:28 + | +LL | use std::mem::{Assume, BikeshedIntrinsicFrom}; + | ^^^^^^^^^^^^^^^^^^^^^ no `BikeshedIntrinsicFrom` in `mem` + +error[E0425]: cannot find type `CPU` in this scope + --> $DIR/recursive-type-with-transmutability-issue-120759.rs:11:61 + | +LL | pub fn is_maybe_transmutable(&self, cpu: &mut CPU) + | ^^^ not found in this scope + +error[E0072]: recursive type `ExplicitlyPadded` has infinite size + --> $DIR/recursive-type-with-transmutability-issue-120759.rs:22:5 + | +LL | struct ExplicitlyPadded(ExplicitlyPadded); + | ^^^^^^^^^^^^^^^^^^^^^^^ ---------------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct ExplicitlyPadded(Box); + | ++++ + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0072, E0425, E0432. +For more information about an error, try `rustc --explain E0072`. From f33b5cb590ed4cf520b30dc0c6ea07f9f49299e5 Mon Sep 17 00:00:00 2001 From: Xiangfei Ding Date: Thu, 26 Mar 2026 11:59:51 +0000 Subject: [PATCH 6/6] use extended regex syntax ... and match on optional minor version for python Signed-off-by: Xiangfei Ding --- x | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x b/x index a8acbd4d5ac62..768ed1674641e 100755 --- a/x +++ b/x @@ -46,7 +46,7 @@ for SEARCH_PYTHON in $SEARCH; do fi done -python=$(bash -c "compgen -c python" | grep '^python[2-3]\.[0-9]+$' | head -n1) +python=$(bash -c "compgen -c python" | grep -E '^python[2-3](\.[0-9]+)?$' | head -n1) if ! [ "$python" = "" ]; then exec "$python" "$xpy" "$@" fi