From a197752e88d99e449caf695f9d2101ceeded24a7 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 24 Feb 2026 11:10:51 +0000 Subject: [PATCH 01/15] Add kernel-hwaddress sanitizer Signed-off-by: Alice Ryhl --- .../src/attributes/codegen_attrs.rs | 6 ++- compiler/rustc_codegen_llvm/src/attributes.rs | 3 +- compiler/rustc_codegen_llvm/src/back/write.rs | 4 ++ compiler/rustc_codegen_llvm/src/base.rs | 8 +++- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 + compiler/rustc_codegen_ssa/src/back/link.rs | 1 + compiler/rustc_feature/src/builtin_attrs.rs | 2 +- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 10 +++-- compiler/rustc_session/src/config/cfg.rs | 4 ++ compiler/rustc_session/src/options.rs | 4 +- compiler/rustc_session/src/session.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/spec/mod.rs | 17 +++++++-- .../aarch64_be_unknown_none_softfloat.rs | 4 +- .../src/spec/targets/aarch64_unknown_none.rs | 4 +- .../targets/aarch64_unknown_none_softfloat.rs | 4 +- .../src/spec/targets/aarch64_unknown_nuttx.rs | 4 +- .../spec/targets/aarch64v8r_unknown_none.rs | 4 +- .../aarch64v8r_unknown_none_softfloat.rs | 4 +- src/tools/compiletest/src/common.rs | 1 + .../src/directives/directive_names.rs | 1 + src/tools/compiletest/src/directives/needs.rs | 7 ++++ .../sanitizer/hwasan-vs-khwasan.rs | 29 ++++++++++++++ .../sanitizer/hwasan-vs-khwasan.rs | 27 +++++++++++++ tests/codegen-llvm/sanitizer/kasan-recover.rs | 33 ++++++++++++++++ .../sanitizer/khwasan-lifetime-markers.rs | 21 ++++++++++ .../codegen-llvm/sanitizer/khwasan-recover.rs | 37 ++++++++++++++++++ .../sanitizer/sanitize-off-hwasan-khwasan.rs | 38 +++++++++++++++++++ .../sanitizer/sanitize-off-khwasan-hwasan.rs | 31 +++++++++++++++ .../sanitizer/sanitizer-recover.rs | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- .../ui/sanitize-attr/invalid-sanitize.stderr | 2 +- tests/ui/sanitizer/cfg-khwasan.rs | 22 +++++++++++ tests/ui/sanitizer/incompatible-khwasan.rs | 9 +++++ .../ui/sanitizer/incompatible-khwasan.stderr | 4 ++ .../sanitizer/unsupported-target-khwasan.rs | 9 +++++ .../unsupported-target-khwasan.stderr | 4 ++ 37 files changed, 345 insertions(+), 22 deletions(-) create mode 100644 tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs create mode 100644 tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs create mode 100644 tests/codegen-llvm/sanitizer/kasan-recover.rs create mode 100644 tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs create mode 100644 tests/codegen-llvm/sanitizer/khwasan-recover.rs create mode 100644 tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs create mode 100644 tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs create mode 100644 tests/ui/sanitizer/cfg-khwasan.rs create mode 100644 tests/ui/sanitizer/incompatible-khwasan.rs create mode 100644 tests/ui/sanitizer/incompatible-khwasan.stderr create mode 100644 tests/ui/sanitizer/unsupported-target-khwasan.rs create mode 100644 tests/ui/sanitizer/unsupported-target-khwasan.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index a8db114129ffd..33fb19089ba55 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -587,6 +587,7 @@ impl SingleAttributeParser for SanitizeParser { r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, + r#"kernel_hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, @@ -654,7 +655,9 @@ impl SingleAttributeParser for SanitizeParser { Some(sym::memtag) => apply(SanitizerSet::MEMTAG), Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK), Some(sym::thread) => apply(SanitizerSet::THREAD), - Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS), + Some(sym::hwaddress) | Some(sym::kernel_hwaddress) => { + apply(SanitizerSet::HWADDRESS | SanitizerSet::KERNELHWADDRESS) + } Some(sym::realtime) => match value.value_as_str() { Some(sym::nonblocking) => rtsan = Some(RtsanSetting::Nonblocking), Some(sym::blocking) => rtsan = Some(RtsanSetting::Blocking), @@ -679,6 +682,7 @@ impl SingleAttributeParser for SanitizeParser { sym::shadow_call_stack, sym::thread, sym::hwaddress, + sym::kernel_hwaddress, sym::realtime, ], ); diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index d51adb6e13b07..f300ee5d4c991 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -120,7 +120,8 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>( if enabled.contains(SanitizerSet::THREAD) { attrs.push(llvm::AttributeKind::SanitizeThread.create_attr(cx.llcx)); } - if enabled.contains(SanitizerSet::HWADDRESS) { + if enabled.contains(SanitizerSet::HWADDRESS) || enabled.contains(SanitizerSet::KERNELHWADDRESS) + { attrs.push(llvm::AttributeKind::SanitizeHWAddress.create_attr(cx.llcx)); } if enabled.contains(SanitizerSet::SHADOWCALLSTACK) { diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index efd4e55d5a856..2125cf6383bf3 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -652,6 +652,10 @@ pub(crate) unsafe fn llvm_optimize( sanitize_kernel_address_recover: config .sanitizer_recover .contains(SanitizerSet::KERNELADDRESS), + sanitize_kernel_hwaddress: config.sanitizer.contains(SanitizerSet::KERNELHWADDRESS), + sanitize_kernel_hwaddress_recover: config + .sanitizer_recover + .contains(SanitizerSet::KERNELHWADDRESS), }) } else { None diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index d00e70638b45a..2276809477121 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -210,10 +210,14 @@ pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { } pub(crate) fn set_variable_sanitizer_attrs(llval: &Value, attrs: &CodegenFnAttrs) { - if attrs.sanitizers.disabled.contains(SanitizerSet::ADDRESS) { + if attrs.sanitizers.disabled.contains(SanitizerSet::ADDRESS) + || attrs.sanitizers.disabled.contains(SanitizerSet::KERNELADDRESS) + { unsafe { llvm::LLVMRustSetNoSanitizeAddress(llval) }; } - if attrs.sanitizers.disabled.contains(SanitizerSet::HWADDRESS) { + if attrs.sanitizers.disabled.contains(SanitizerSet::HWADDRESS) + || attrs.sanitizers.disabled.contains(SanitizerSet::KERNELHWADDRESS) + { unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(llval) }; } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 77438472644fc..7355d11367920 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -464,6 +464,8 @@ pub(crate) struct SanitizerOptions { pub sanitize_hwaddress_recover: bool, pub sanitize_kernel_address: bool, pub sanitize_kernel_address_recover: bool, + pub sanitize_kernel_hwaddress: bool, + pub sanitize_kernel_hwaddress_recover: bool, } /// LLVMRustRelocModel diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7a3d5a6bb2248..be7da2e81add8 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1341,6 +1341,7 @@ fn add_sanitizer_libraries( if sanitizer.contains(SanitizerSet::LEAK) && !sanitizer.contains(SanitizerSet::ADDRESS) && !sanitizer.contains(SanitizerSet::HWADDRESS) + && !sanitizer.contains(SanitizerSet::KERNELHWADDRESS) { link_sanitizer_runtime(sess, flavor, linker, "lsan"); } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 3a2f548902d11..3187876626f3e 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -773,7 +773,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ DuplicatesOk, EncodeCrossCrate::No, effective_target_features, experimental!(force_target_feature) ), gated!( - sanitize, Normal, template!(List: &[r#"address = "on|off""#, r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, r#"thread = "on|off""#]), ErrorPreceding, + sanitize, Normal, template!(List: &[r#"address = "on|off""#, r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, r#"kernel_hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, r#"thread = "on|off""#]), ErrorPreceding, EncodeCrossCrate::No, sanitize, experimental!(sanitize), ), gated!( diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 00d03f023924a..b4f6bb4583c10 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -540,6 +540,8 @@ struct LLVMRustSanitizerOptions { bool SanitizeHWAddressRecover; bool SanitizeKernelAddress; bool SanitizeKernelAddressRecover; + bool SanitizeKernelHWAddress; + bool SanitizeKernelHWAddressRecover; }; extern "C" typedef void (*registerEnzymeAndPassPipelineFn)( @@ -767,13 +769,15 @@ extern "C" LLVMRustResult LLVMRustOptimize( !TM->getTargetTriple().isOSWindows())); }); } - if (SanitizerOptions->SanitizeHWAddress) { + if (SanitizerOptions->SanitizeHWAddress || + SanitizerOptions->SanitizeKernelHWAddress) { OptimizerLastEPCallbacks.push_back( [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level, ThinOrFullLTOPhase phase) { HWAddressSanitizerOptions opts( - /*CompileKernel=*/false, - SanitizerOptions->SanitizeHWAddressRecover, + SanitizerOptions->SanitizeKernelHWAddress, + SanitizerOptions->SanitizeHWAddressRecover || + SanitizerOptions->SanitizeKernelHWAddressRecover, /*DisableOptimization=*/false); MPM.addPass(HWAddressSanitizerPass(opts)); }); diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index ebbbe36878daa..17fdba37b4bc7 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -229,6 +229,10 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { if s == SanitizerSet::KERNELADDRESS { s = SanitizerSet::ADDRESS; } + // KHWASAN is still HWASAN under the hood, so it uses the same attribute. + if s == SanitizerSet::KERNELHWADDRESS { + s = SanitizerSet::HWADDRESS; + } ins_str!(sym::sanitize, &s.to_string()); } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0bc432a0ff06c..d370f00d21987 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -106,6 +106,7 @@ mod target_modifier_consistency_check { | SanitizerSet::SHADOWCALLSTACK | SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS + | SanitizerSet::KERNELHWADDRESS | SanitizerSet::SAFESTACK | SanitizerSet::DATAFLOW; @@ -810,7 +811,7 @@ mod desc { pub(crate) const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)"; pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy; pub(crate) const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; - pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`, or 'realtime'"; + pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `kernel-hwaddress`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`, or 'realtime'"; pub(crate) const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; pub(crate) const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; @@ -1252,6 +1253,7 @@ pub mod parse { "dataflow" => SanitizerSet::DATAFLOW, "kcfi" => SanitizerSet::KCFI, "kernel-address" => SanitizerSet::KERNELADDRESS, + "kernel-hwaddress" => SanitizerSet::KERNELHWADDRESS, "leak" => SanitizerSet::LEAK, "memory" => SanitizerSet::MEMORY, "memtag" => SanitizerSet::MEMTAG, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 0548380331bef..3da2d891e19db 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -529,7 +529,7 @@ impl Session { // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs. // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables. // HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future. - || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) + || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS | SanitizerSet::KERNELHWADDRESS) } pub fn diagnostic_width(&self) -> usize { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 286fea7d90505..6da8974cba641 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1115,6 +1115,7 @@ symbols! { iterator_collect_fn, kcfi, kernel_address, + kernel_hwaddress, keylocker_x86, keyword, kind, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8683e4f51279e..2b5cbd6703084 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1175,9 +1175,10 @@ bitflags::bitflags! { const SHADOWCALLSTACK = 1 << 7; const KCFI = 1 << 8; const KERNELADDRESS = 1 << 9; - const SAFESTACK = 1 << 10; - const DATAFLOW = 1 << 11; - const REALTIME = 1 << 12; + const KERNELHWADDRESS = 1 << 10; + const SAFESTACK = 1 << 11; + const DATAFLOW = 1 << 12; + const REALTIME = 1 << 13; } } rustc_data_structures::external_bitflags_debug! { SanitizerSet } @@ -1191,24 +1192,32 @@ impl SanitizerSet { (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS), (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG), (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS), + (SanitizerSet::ADDRESS, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK), (SanitizerSet::LEAK, SanitizerSet::MEMORY), (SanitizerSet::LEAK, SanitizerSet::THREAD), (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS), + (SanitizerSet::LEAK, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::LEAK, SanitizerSet::SAFESTACK), (SanitizerSet::MEMORY, SanitizerSet::THREAD), (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS), (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS), + (SanitizerSet::MEMORY, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK), (SanitizerSet::THREAD, SanitizerSet::HWADDRESS), (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS), + (SanitizerSet::THREAD, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::THREAD, SanitizerSet::SAFESTACK), (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG), (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS), + (SanitizerSet::HWADDRESS, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK), (SanitizerSet::CFI, SanitizerSet::KCFI), (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS), + (SanitizerSet::MEMTAG, SanitizerSet::KERNELHWADDRESS), + (SanitizerSet::KERNELADDRESS, SanitizerSet::KERNELHWADDRESS), (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK), + (SanitizerSet::KERNELHWADDRESS, SanitizerSet::SAFESTACK), ]; /// Return sanitizer's name @@ -1221,6 +1230,7 @@ impl SanitizerSet { SanitizerSet::DATAFLOW => "dataflow", SanitizerSet::KCFI => "kcfi", SanitizerSet::KERNELADDRESS => "kernel-address", + SanitizerSet::KERNELHWADDRESS => "kernel-hwaddress", SanitizerSet::LEAK => "leak", SanitizerSet::MEMORY => "memory", SanitizerSet::MEMTAG => "memtag", @@ -1266,6 +1276,7 @@ impl FromStr for SanitizerSet { "dataflow" => SanitizerSet::DATAFLOW, "kcfi" => SanitizerSet::KCFI, "kernel-address" => SanitizerSet::KERNELADDRESS, + "kernel-hwaddress" => SanitizerSet::KERNELHWADDRESS, "leak" => SanitizerSet::LEAK, "memory" => SanitizerSet::MEMORY, "memtag" => SanitizerSet::MEMTAG, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs index e204c6466e297..aae7af82d5536 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs @@ -22,7 +22,9 @@ pub(crate) fn target() -> Target { relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::KERNELHWADDRESS, stack_probes: StackProbeType::Inline, panic_strategy: PanicStrategy::Abort, endian: Endian::Big, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs index 1c166030d5e5d..13d3b77588a0e 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs @@ -21,7 +21,9 @@ pub(crate) fn target() -> Target { &["--fix-cortex-a53-843419"], ), features: "+v8a,+strict-align,+neon".into(), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::KERNELHWADDRESS, relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs index ed2e2fb6ab70b..2e972f2fa2acf 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs @@ -21,7 +21,9 @@ pub(crate) fn target() -> Target { relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::KERNELHWADDRESS, stack_probes: StackProbeType::Inline, panic_strategy: PanicStrategy::Abort, default_uwtable: true, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs index 19b7ebe036747..1e06d3abb723b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs @@ -21,7 +21,9 @@ pub(crate) fn target() -> Target { &["--fix-cortex-a53-843419"], ), features: "+v8a,+strict-align,+neon".into(), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::KERNELHWADDRESS, relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs index 8f8bbb4a41caf..680d89653db82 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs @@ -8,7 +8,9 @@ pub(crate) fn target() -> Target { // based off the aarch64-unknown-none target at time of addition linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::KERNELHWADDRESS, relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), diff --git a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs index 6f11f97e3d1df..731b61d6731f8 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs @@ -12,7 +12,9 @@ pub(crate) fn target() -> Target { relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), - supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::KERNELHWADDRESS, stack_probes: StackProbeType::Inline, panic_strategy: PanicStrategy::Abort, default_uwtable: true, diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index bc94a81ba3b52..7cac7f5c04940 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -168,6 +168,7 @@ pub enum Sanitizer { Dataflow, Kcfi, KernelAddress, + KernelHwaddress, Leak, Memory, Memtag, diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 9af881b5c2f58..eaa1a39a9eeef 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -179,6 +179,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-hwaddress", "needs-sanitizer-kasan", "needs-sanitizer-kcfi", + "needs-sanitizer-khwasan", "needs-sanitizer-leak", "needs-sanitizer-memory", "needs-sanitizer-memtag", diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs index 168d5e9eb649b..e9f3d6c28d6ef 100644 --- a/src/tools/compiletest/src/directives/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -46,6 +46,11 @@ pub(super) fn handle_needs( condition: cache.sanitizer_kasan, ignore_reason: "ignored on targets without kernel address sanitizer", }, + Need { + name: "needs-sanitizer-khwasan", + condition: cache.sanitizer_khwasan, + ignore_reason: "ignored on targets without kernel hardware-assisted address sanitizer", + }, Need { name: "needs-sanitizer-leak", condition: cache.sanitizer_leak, @@ -332,6 +337,7 @@ pub(super) struct CachedNeedsConditions { sanitizer_dataflow: bool, sanitizer_kcfi: bool, sanitizer_kasan: bool, + sanitizer_khwasan: bool, sanitizer_leak: bool, sanitizer_memory: bool, sanitizer_thread: bool, @@ -359,6 +365,7 @@ impl CachedNeedsConditions { sanitizer_dataflow: sanitizers.contains(&Sanitizer::Dataflow), sanitizer_kcfi: sanitizers.contains(&Sanitizer::Kcfi), sanitizer_kasan: sanitizers.contains(&Sanitizer::KernelAddress), + sanitizer_khwasan: sanitizers.contains(&Sanitizer::KernelHwaddress), sanitizer_leak: sanitizers.contains(&Sanitizer::Leak), sanitizer_memory: sanitizers.contains(&Sanitizer::Memory), sanitizer_thread: sanitizers.contains(&Sanitizer::Thread), diff --git a/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs b/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs new file mode 100644 index 0000000000000..bcb2fbc613dff --- /dev/null +++ b/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs @@ -0,0 +1,29 @@ +// Verifies that HWASAN and KHWASAN emit different assembly instrumentation on AArch64. +// +//@ add-minicore +//@ assembly-output: emit-asm +//@ revisions: hwasan khwasan +//@[hwasan] compile-flags: --target aarch64-unknown-linux-gnu -Zsanitizer=hwaddress +//@[khwasan] compile-flags: --target aarch64-unknown-none -Zsanitizer=kernel-hwaddress +//@ compile-flags: -Copt-level=1 + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +extern crate minicore; + +// hwasan-LABEL: test: +// hwasan: adrp x{{[0-9]+}}, :gottprel:__hwasan_tls +// hwasan: mrs x{{[0-9]+}}, TPIDR_EL0 +// hwasan: bl __hwasan_check_x0_0_short_v2 + +// khwasan-LABEL: test: +// khwasan-NOT: __hwasan_tls +// khwasan: orr x{{[0-9]+}}, x0, #0xff00000000000000 +// khwasan: bl __hwasan_check_x0_67043328_fixed_0_short_v2 + +#[no_mangle] +pub fn test(b: &mut u8) -> u8 { + *b +} diff --git a/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs new file mode 100644 index 0000000000000..fd3aacee5af2c --- /dev/null +++ b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs @@ -0,0 +1,27 @@ +// Verifies that HWASAN and KHWASAN emit different instrumentation. +// +//@ add-minicore +//@ revisions: hwasan khwasan +//@[hwasan] compile-flags: --target aarch64-unknown-linux-gnu -Zsanitizer=hwaddress +//@[khwasan] compile-flags: --target aarch64-unknown-none -Zsanitizer=kernel-hwaddress +//@ compile-flags: -Copt-level=0 + +#![crate_type = "lib"] +#![feature(no_core, lang_items, sanitize)] +#![no_core] + +extern crate minicore; + +// hwasan-LABEL: define {{.*}} @test +// hwasan: @__hwasan_tls +// hwasan: call void @llvm.hwasan.check.memaccess.shortgranules +// hwasan: declare void @__hwasan_init() + +// khwasan-LABEL: define {{.*}} @test +// khwasan-NOT: @__hwasan_init +// khwasan: @__hwasan_tls +// khwasan: call void @llvm.hwasan.check.memaccess.shortgranules +#[no_mangle] +pub fn test(b: &mut u8) -> u8 { + *b +} diff --git a/tests/codegen-llvm/sanitizer/kasan-recover.rs b/tests/codegen-llvm/sanitizer/kasan-recover.rs new file mode 100644 index 0000000000000..8f0e6eb3a605d --- /dev/null +++ b/tests/codegen-llvm/sanitizer/kasan-recover.rs @@ -0,0 +1,33 @@ +// Verifies that KernelAddressSanitizer recovery mode can be enabled +// with -Zsanitizer-recover=kernel-address. +// +//@ add-minicore +//@ revisions: KASAN KASAN-RECOVER +//@ compile-flags: -Copt-level=0 +//@[KASAN] compile-flags: -Zsanitizer=kernel-address --target x86_64-unknown-none +//@[KASAN] needs-llvm-components: x86 +//@[KASAN-RECOVER] compile-flags: -Zsanitizer=kernel-address +//@[KASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-address --target x86_64-unknown-none +//@[KASAN-RECOVER] needs-llvm-components: x86 + +#![feature(no_core, sanitize, lang_items)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +// KASAN-LABEL: define{{.*}}@penguin( +// KASAN: call void @__asan_report_load4( +// KASAN: unreachable +// KASAN: } + +// KASAN-RECOVER-LABEL: define{{.*}}@penguin( +// KASAN-RECOVER: call void @__asan_report_load4_noabort( +// KASAN-RECOVER-NOT: unreachable +// KASAN-RECOVER: } + +#[no_mangle] +pub unsafe fn penguin(p: *mut i32) -> i32 { + *p +} diff --git a/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs b/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs new file mode 100644 index 0000000000000..01b129cb69207 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs @@ -0,0 +1,21 @@ +// Verifies that `-Zsanitizer=kernel-hwaddress` enables lifetime markers. + +//@ add-minicore +//@ compile-flags: -Zsanitizer=kernel-hwaddress -Copt-level=0 +//@ revisions: aarch64 +//@[aarch64] compile-flags: --target aarch64-unknown-none +//@[aarch64] needs-llvm-components: aarch64 + +#![crate_type = "rlib"] +#![feature(no_core, lang_items)] +#![no_core] + +extern crate minicore; +use minicore::*; + +// CHECK-LABEL: ; khwasan_lifetime_markers::test +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @llvm.lifetime.end +pub fn test() { + let _x = [0u8; 10]; +} diff --git a/tests/codegen-llvm/sanitizer/khwasan-recover.rs b/tests/codegen-llvm/sanitizer/khwasan-recover.rs new file mode 100644 index 0000000000000..957b867a61ad9 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/khwasan-recover.rs @@ -0,0 +1,37 @@ +// Verifies that KernelHWAddressSanitizer recovery mode can be enabled +// with -Zsanitizer-recover=kernel-hwaddress. +// +//@ add-minicore +//@[KHWASAN] needs-llvm-components: aarch64 +//@[KHWASAN-RECOVER] needs-llvm-components: aarch64 +//@ revisions: KHWASAN KHWASAN-RECOVER +//@ no-prefer-dynamic +//@ compile-flags: -Copt-level=0 +//@[KHWASAN] compile-flags: -Zsanitizer=kernel-hwaddress --target aarch64-unknown-none +//@[KHWASAN-RECOVER] compile-flags: -Zsanitizer=kernel-hwaddress +//@[KHWASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-hwaddress +//@[KHWASAN-RECOVER] compile-flags: --target aarch64-unknown-none + +#![feature(no_core, sanitize, lang_items)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +// KHWASAN-LABEL: define{{.*}}@penguin( +// KHWASAN: call void @llvm.hwasan.check.memaccess +// KHWASAN: ret i32 +// KHWASAN: } +// KHWASAN: declare void @__hwasan_load4(i64) + +// KHWASAN-RECOVER-LABEL: define{{.*}}@penguin( +// KHWASAN-RECOVER: call void asm sideeffect "brk #2338", "{x0}"(i64 %{{[0-9]+}}) +// KHWASAN-RECOVER-NOT: unreachable +// KHWASAN-RECOVER: } +// KHWASAN-RECOVER: declare void @__hwasan_load4_noabort(i64) + +#[no_mangle] +pub unsafe fn penguin(p: *mut i32) -> i32 { + *p +} diff --git a/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs b/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs new file mode 100644 index 0000000000000..c0e23f5f596ba --- /dev/null +++ b/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs @@ -0,0 +1,38 @@ +// Verifies that the `#[sanitize(hwaddress = "off")]` attribute also turns off +// the kernel hardware-assisted address sanitizer. +// +//@ add-minicore +//@ compile-flags: -Zsanitizer=kernel-hwaddress -Ctarget-feature=-crt-static -Copt-level=0 +//@ revisions: aarch64 aarch64v8r +//@[aarch64] compile-flags: --target aarch64-unknown-none +//@[aarch64] needs-llvm-components: aarch64 +//@[aarch64v8r] compile-flags: --target aarch64v8r-unknown-none +//@[aarch64v8r] needs-llvm-components: aarch64 + +#![crate_type = "rlib"] +#![feature(no_core, sanitize, lang_items)] +#![no_core] + +extern crate minicore; +use minicore::*; + +// CHECK-NOT: sanitize_hwaddress +// CHECK-LABEL: define {{.*}} @unsanitized +// CHECK: start: +// CHECK-NOT: call void @llvm.hwasan.check.memaccess +// CHECK: } +#[sanitize(hwaddress = "off")] +#[no_mangle] +pub fn unsanitized(b: &mut u8) -> u8 { + *b +} + +// CHECK: sanitize_hwaddress +// CHECK-LABEL: define {{.*}} @sanitized +// CHECK: start: +// CHECK: call void @llvm.hwasan.check.memaccess +// CHECK: } +#[no_mangle] +pub fn sanitized(b: &mut u8) -> u8 { + *b +} diff --git a/tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs b/tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs new file mode 100644 index 0000000000000..a4491eb9f785d --- /dev/null +++ b/tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs @@ -0,0 +1,31 @@ +// Verifies that the `#[sanitize(kernel_hwaddress = "off")]` attribute also turns off +// the hardware-assisted address sanitizer. +// +//@ needs-sanitizer-hwaddress +//@ compile-flags: -Cunsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -Ctarget-feature=-crt-static +//@ compile-flags: -Zsanitizer=hwaddress -Copt-level=0 + +#![crate_type = "lib"] +#![feature(sanitize)] + +// CHECK-NOT: sanitize_hwaddress +// CHECK-LABEL: define {{.*}} @unsanitized +// CHECK: start: +// CHECK-NOT: call void @llvm.hwasan.check.memaccess +// CHECK: } +#[sanitize(kernel_hwaddress = "off")] +#[no_mangle] +pub fn unsanitized(b: &mut u8) -> u8 { + *b +} + +// CHECK: sanitize_hwaddress +// CHECK-LABEL: define {{.*}} @sanitized +// CHECK: start: +// CHECK: call void @llvm.hwasan.check.memaccess +// CHECK: } +#[no_mangle] +pub fn sanitized(b: &mut u8) -> u8 { + *b +} diff --git a/tests/codegen-llvm/sanitizer/sanitizer-recover.rs b/tests/codegen-llvm/sanitizer/sanitizer-recover.rs index b8a24e31c30bb..5e05b92f3b100 100644 --- a/tests/codegen-llvm/sanitizer/sanitizer-recover.rs +++ b/tests/codegen-llvm/sanitizer/sanitizer-recover.rs @@ -5,7 +5,7 @@ //@ needs-sanitizer-memory //@ revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER MSAN-RECOVER-LTO //@ no-prefer-dynamic -//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -Cunsafe-allow-abi-mismatch=sanitizer //@ compile-flags: -Ctarget-feature=-crt-static //@[ASAN] compile-flags: -Zsanitizer=address -Copt-level=0 //@[ASAN-RECOVER] compile-flags: -Zsanitizer=address -Zsanitizer-recover=address -Copt-level=0 diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index efa0a7f4af9ac..0ba2f0b0f2096 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -120,7 +120,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | sanitize = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `realtime`, `safestack`, `shadow-call-stack`, and `thread` + = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `kernel-hwaddress`, `leak`, `memory`, `memtag`, `realtime`, `safestack`, `shadow-call-stack`, and `thread` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr index 00bb7746d05f3..b35c2f9976f0e 100644 --- a/tests/ui/sanitize-attr/invalid-sanitize.stderr +++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr @@ -4,7 +4,7 @@ error[E0539]: malformed `sanitize` attribute input LL | #[sanitize(brontosaurus = "off")] | ^^^^^^^^^^^------------^^^^^^^^^^ | | - | valid arguments are "address", "kernel_address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress" or "realtime" + | valid arguments are "address", "kernel_address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress", "kernel_hwaddress" or "realtime" error: multiple `sanitize` attributes --> $DIR/invalid-sanitize.rs:7:1 diff --git a/tests/ui/sanitizer/cfg-khwasan.rs b/tests/ui/sanitizer/cfg-khwasan.rs new file mode 100644 index 0000000000000..c2b0505a34c26 --- /dev/null +++ b/tests/ui/sanitizer/cfg-khwasan.rs @@ -0,0 +1,22 @@ +// Verifies that when compiling with -Zsanitizer=kernel-hwaddress, +// the `#[cfg(sanitize = "hwaddress")]` attribute is configured. + +//@ add-minicore +//@ check-pass +//@ compile-flags: -Zsanitizer=kernel-hwaddress +//@ revisions: aarch64 +//@[aarch64] compile-flags: --target aarch64-unknown-none +//@[aarch64] needs-llvm-components: aarch64 +//@ ignore-backends: gcc + +#![crate_type = "rlib"] +#![feature(cfg_sanitize, no_core)] +#![no_core] + +extern crate minicore; +use minicore::*; + +const _: fn() -> () = main; + +#[cfg(sanitize = "hwaddress")] +fn main() {} diff --git a/tests/ui/sanitizer/incompatible-khwasan.rs b/tests/ui/sanitizer/incompatible-khwasan.rs new file mode 100644 index 0000000000000..eb6a5d33a472b --- /dev/null +++ b/tests/ui/sanitizer/incompatible-khwasan.rs @@ -0,0 +1,9 @@ +//@ compile-flags: -Z sanitizer=kernel-hwaddress -Z sanitizer=kernel-address --target aarch64-unknown-none +//@ needs-llvm-components: aarch64 +//@ ignore-backends: gcc + +#![feature(no_core)] +#![no_core] +#![no_main] + +//~? ERROR `-Zsanitizer=kernel-address` is incompatible with `-Zsanitizer=kernel-hwaddress` diff --git a/tests/ui/sanitizer/incompatible-khwasan.stderr b/tests/ui/sanitizer/incompatible-khwasan.stderr new file mode 100644 index 0000000000000..35246fb266230 --- /dev/null +++ b/tests/ui/sanitizer/incompatible-khwasan.stderr @@ -0,0 +1,4 @@ +error: `-Zsanitizer=kernel-address` is incompatible with `-Zsanitizer=kernel-hwaddress` + +error: aborting due to 1 previous error + diff --git a/tests/ui/sanitizer/unsupported-target-khwasan.rs b/tests/ui/sanitizer/unsupported-target-khwasan.rs new file mode 100644 index 0000000000000..bef6d95e57b21 --- /dev/null +++ b/tests/ui/sanitizer/unsupported-target-khwasan.rs @@ -0,0 +1,9 @@ +//@ compile-flags: -Z sanitizer=kernel-hwaddress --target x86_64-unknown-none +//@ needs-llvm-components: x86 +//@ ignore-backends: gcc + +#![feature(no_core)] +#![no_core] +#![no_main] + +//~? ERROR kernel-hwaddress sanitizer is not supported for this target diff --git a/tests/ui/sanitizer/unsupported-target-khwasan.stderr b/tests/ui/sanitizer/unsupported-target-khwasan.stderr new file mode 100644 index 0000000000000..8b122a610ee40 --- /dev/null +++ b/tests/ui/sanitizer/unsupported-target-khwasan.stderr @@ -0,0 +1,4 @@ +error: kernel-hwaddress sanitizer is not supported for this target + +error: aborting due to 1 previous error + From e41bbfaaa6b4bfde2130add801ec3bf392d74539 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Fri, 6 Mar 2026 17:07:14 +0000 Subject: [PATCH 02/15] Explain why __hwasan_tls is present in LLVM codegen --- tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs index fd3aacee5af2c..b059f6bbefb4a 100644 --- a/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs +++ b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs @@ -17,9 +17,19 @@ extern crate minicore; // hwasan: call void @llvm.hwasan.check.memaccess.shortgranules // hwasan: declare void @__hwasan_init() +// The `__hwasan_tls` symbol is unconditionally declared by LLVM's `HWAddressSanitizer` pass. +// However, in kernel mode KHWASAN does not actually use it (because shadow mapping is fixed +// and the stack frame ring buffer is disabled). It remains an unused declaration in the LLVM IR +// and is optimized out before the final assembly/object file is generated, so it does not end +// up in the final binary. Thus, assert that it appears in the output, but not inside `test`. +// +// khwasan: @__hwasan_tls // khwasan-LABEL: define {{.*}} @test +// khwasan-NOT: @__hwasan_tls +// +// Also test a few other things appear under the LABEL. +// // khwasan-NOT: @__hwasan_init -// khwasan: @__hwasan_tls // khwasan: call void @llvm.hwasan.check.memaccess.shortgranules #[no_mangle] pub fn test(b: &mut u8) -> u8 { From ec03f4ef294d3a75ed12b36662d1a40441b0a726 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 16 Mar 2026 14:23:24 +0000 Subject: [PATCH 03/15] Adjust lifetime markers comment --- compiler/rustc_session/src/session.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 3da2d891e19db..96f54481350db 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -527,8 +527,11 @@ impl Session { pub fn emit_lifetime_markers(&self) -> bool { self.opts.optimize != config::OptLevel::No // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs. + // // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables. - // HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future. + // + // HWAddressSanitizer and KernelHWAddressSanitizer will use lifetimes to detect use after + // scope bugs in the future. || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS | SanitizerSet::KERNELHWADDRESS) } From c679e3daf2166e2bcd56e8acc2cacfe6dc9757a8 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 17 Mar 2026 07:49:28 +0000 Subject: [PATCH 04/15] Simplify tests and fix test tidy issue --- tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs | 2 ++ tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs | 2 ++ tests/codegen-llvm/sanitizer/kasan-recover.rs | 8 +++----- tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs | 5 ++--- tests/codegen-llvm/sanitizer/khwasan-recover.rs | 9 +++------ .../sanitizer/sanitize-off-hwasan-khwasan.rs | 9 +++------ tests/ui/sanitizer/cfg-khwasan.rs | 6 ++---- 7 files changed, 17 insertions(+), 24 deletions(-) diff --git a/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs b/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs index bcb2fbc613dff..a4362b3621326 100644 --- a/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs +++ b/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs @@ -4,7 +4,9 @@ //@ assembly-output: emit-asm //@ revisions: hwasan khwasan //@[hwasan] compile-flags: --target aarch64-unknown-linux-gnu -Zsanitizer=hwaddress +//@[hwasan] needs-llvm-components: aarch64 //@[khwasan] compile-flags: --target aarch64-unknown-none -Zsanitizer=kernel-hwaddress +//@[khwasan] needs-llvm-components: aarch64 //@ compile-flags: -Copt-level=1 #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs index b059f6bbefb4a..93932d86582fa 100644 --- a/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs +++ b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs @@ -3,7 +3,9 @@ //@ add-minicore //@ revisions: hwasan khwasan //@[hwasan] compile-flags: --target aarch64-unknown-linux-gnu -Zsanitizer=hwaddress +//@[hwasan] needs-llvm-components: aarch64 //@[khwasan] compile-flags: --target aarch64-unknown-none -Zsanitizer=kernel-hwaddress +//@[khwasan] needs-llvm-components: aarch64 //@ compile-flags: -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/kasan-recover.rs b/tests/codegen-llvm/sanitizer/kasan-recover.rs index 8f0e6eb3a605d..f0f9180ae595e 100644 --- a/tests/codegen-llvm/sanitizer/kasan-recover.rs +++ b/tests/codegen-llvm/sanitizer/kasan-recover.rs @@ -4,11 +4,9 @@ //@ add-minicore //@ revisions: KASAN KASAN-RECOVER //@ compile-flags: -Copt-level=0 -//@[KASAN] compile-flags: -Zsanitizer=kernel-address --target x86_64-unknown-none -//@[KASAN] needs-llvm-components: x86 -//@[KASAN-RECOVER] compile-flags: -Zsanitizer=kernel-address -//@[KASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-address --target x86_64-unknown-none -//@[KASAN-RECOVER] needs-llvm-components: x86 +//@ needs-llvm-components: x86 +//@ compile-flags: -Zsanitizer=kernel-address --target x86_64-unknown-none +//@[KASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-address #![feature(no_core, sanitize, lang_items)] #![no_core] diff --git a/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs b/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs index 01b129cb69207..26dc7983d7314 100644 --- a/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs +++ b/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs @@ -2,9 +2,8 @@ //@ add-minicore //@ compile-flags: -Zsanitizer=kernel-hwaddress -Copt-level=0 -//@ revisions: aarch64 -//@[aarch64] compile-flags: --target aarch64-unknown-none -//@[aarch64] needs-llvm-components: aarch64 +//@ compile-flags: --target aarch64-unknown-none +//@ needs-llvm-components: aarch64 #![crate_type = "rlib"] #![feature(no_core, lang_items)] diff --git a/tests/codegen-llvm/sanitizer/khwasan-recover.rs b/tests/codegen-llvm/sanitizer/khwasan-recover.rs index 957b867a61ad9..452a0f579fc72 100644 --- a/tests/codegen-llvm/sanitizer/khwasan-recover.rs +++ b/tests/codegen-llvm/sanitizer/khwasan-recover.rs @@ -2,15 +2,12 @@ // with -Zsanitizer-recover=kernel-hwaddress. // //@ add-minicore -//@[KHWASAN] needs-llvm-components: aarch64 -//@[KHWASAN-RECOVER] needs-llvm-components: aarch64 +//@ needs-llvm-components: aarch64 //@ revisions: KHWASAN KHWASAN-RECOVER //@ no-prefer-dynamic //@ compile-flags: -Copt-level=0 -//@[KHWASAN] compile-flags: -Zsanitizer=kernel-hwaddress --target aarch64-unknown-none -//@[KHWASAN-RECOVER] compile-flags: -Zsanitizer=kernel-hwaddress -//@[KHWASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-hwaddress -//@[KHWASAN-RECOVER] compile-flags: --target aarch64-unknown-none +//@ compile-flags: -Zsanitizer=kernel-hwaddress --target aarch64-unknown-none +//@[KHWASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-hwaddress #![feature(no_core, sanitize, lang_items)] #![no_core] diff --git a/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs b/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs index c0e23f5f596ba..313f48031e4ab 100644 --- a/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs +++ b/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs @@ -2,12 +2,9 @@ // the kernel hardware-assisted address sanitizer. // //@ add-minicore -//@ compile-flags: -Zsanitizer=kernel-hwaddress -Ctarget-feature=-crt-static -Copt-level=0 -//@ revisions: aarch64 aarch64v8r -//@[aarch64] compile-flags: --target aarch64-unknown-none -//@[aarch64] needs-llvm-components: aarch64 -//@[aarch64v8r] compile-flags: --target aarch64v8r-unknown-none -//@[aarch64v8r] needs-llvm-components: aarch64 +//@ compile-flags: -Zsanitizer=kernel-hwaddress --target aarch64-unknown-none +//@ compile-flags: -Ctarget-feature=-crt-static -Copt-level=0 +//@ needs-llvm-components: aarch64 #![crate_type = "rlib"] #![feature(no_core, sanitize, lang_items)] diff --git a/tests/ui/sanitizer/cfg-khwasan.rs b/tests/ui/sanitizer/cfg-khwasan.rs index c2b0505a34c26..27a2f6030d0ba 100644 --- a/tests/ui/sanitizer/cfg-khwasan.rs +++ b/tests/ui/sanitizer/cfg-khwasan.rs @@ -3,10 +3,8 @@ //@ add-minicore //@ check-pass -//@ compile-flags: -Zsanitizer=kernel-hwaddress -//@ revisions: aarch64 -//@[aarch64] compile-flags: --target aarch64-unknown-none -//@[aarch64] needs-llvm-components: aarch64 +//@ compile-flags: -Zsanitizer=kernel-hwaddress --target aarch64-unknown-none +//@ needs-llvm-components: aarch64 //@ ignore-backends: gcc #![crate_type = "rlib"] From adacd90f29c381c2e3876f356dda7575a96ffef5 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 19 Mar 2026 14:37:13 +0000 Subject: [PATCH 05/15] move many `ui/macros` tests from `run-` to `check-pass` --- tests/ui/macros/issue-2804.rs | 2 +- tests/ui/macros/issue-33185.rs | 2 +- tests/ui/macros/issue-40469.rs | 2 +- tests/ui/macros/issue-40770.rs | 2 +- tests/ui/macros/macro-attribute-expansion.rs | 2 +- tests/ui/macros/macro-attributes.rs | 2 +- tests/ui/macros/macro-delimiter-significance.rs | 2 +- tests/ui/macros/macro-doc-comments.rs | 2 +- tests/ui/macros/macro-doc-escapes.rs | 2 +- tests/ui/macros/macro-follow-rpass.rs | 2 +- tests/ui/macros/macro-followed-by-seq.rs | 2 +- tests/ui/macros/macro-in-fn.rs | 2 +- .../macros/macro-invocation-in-count-expr-fixed-array-type.rs | 2 +- tests/ui/macros/macro-multiple-items.rs | 2 +- tests/ui/macros/macro-named-default.rs | 2 +- tests/ui/macros/macro-nt-list.rs | 2 +- tests/ui/macros/macro-pat-follow-2018.rs | 2 +- tests/ui/macros/macro-pub-matcher.rs | 2 +- tests/ui/macros/macro-seq-followed-by-seq.rs | 2 +- tests/ui/macros/macro-use-all-and-none.rs | 2 +- tests/ui/macros/macro-use-all.rs | 2 +- tests/ui/macros/macro-use-both.rs | 2 +- tests/ui/macros/macro-use-one.rs | 2 +- tests/ui/macros/parse-complex-macro-invoc-op.rs | 2 +- tests/ui/macros/pub-item-inside-macro.rs | 2 +- tests/ui/macros/pub-method-inside-macro.rs | 2 +- tests/ui/macros/semi-after-macro-ty.rs | 2 +- tests/ui/macros/two-macro-use.rs | 2 +- tests/ui/macros/type-macros-simple.rs | 2 +- tests/ui/macros/use-macro-self.rs | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/ui/macros/issue-2804.rs b/tests/ui/macros/issue-2804.rs index 0b6f9487ece2a..9f45df4a3178a 100644 --- a/tests/ui/macros/issue-2804.rs +++ b/tests/ui/macros/issue-2804.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(non_camel_case_types)] #![allow(dead_code)] diff --git a/tests/ui/macros/issue-33185.rs b/tests/ui/macros/issue-33185.rs index 8d7e305f1e359..5771b40809dc3 100644 --- a/tests/ui/macros/issue-33185.rs +++ b/tests/ui/macros/issue-33185.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] #[macro_export] diff --git a/tests/ui/macros/issue-40469.rs b/tests/ui/macros/issue-40469.rs index faa4c6581af7f..4529e44e267de 100644 --- a/tests/ui/macros/issue-40469.rs +++ b/tests/ui/macros/issue-40469.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] diff --git a/tests/ui/macros/issue-40770.rs b/tests/ui/macros/issue-40770.rs index d90294acd2510..028bd48b1be74 100644 --- a/tests/ui/macros/issue-40770.rs +++ b/tests/ui/macros/issue-40770.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(unused_macros)] macro_rules! m { ($e:expr) => { diff --git a/tests/ui/macros/macro-attribute-expansion.rs b/tests/ui/macros/macro-attribute-expansion.rs index be682b38865d3..255400e2679e0 100644 --- a/tests/ui/macros/macro-attribute-expansion.rs +++ b/tests/ui/macros/macro-attribute-expansion.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass macro_rules! descriptions { ($name:ident is $desc:expr) => { // Check that we will correctly expand attributes diff --git a/tests/ui/macros/macro-attributes.rs b/tests/ui/macros/macro-attributes.rs index 976d2cbcccdbb..a25ed2ba7ef6a 100644 --- a/tests/ui/macros/macro-attributes.rs +++ b/tests/ui/macros/macro-attributes.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass macro_rules! compiles_fine { (#[$at:meta]) => { diff --git a/tests/ui/macros/macro-delimiter-significance.rs b/tests/ui/macros/macro-delimiter-significance.rs index 8b532e19196b3..1947ecf9b22ea 100644 --- a/tests/ui/macros/macro-delimiter-significance.rs +++ b/tests/ui/macros/macro-delimiter-significance.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass fn main() { vec![1_usize, 2, 3].len(); } diff --git a/tests/ui/macros/macro-doc-comments.rs b/tests/ui/macros/macro-doc-comments.rs index 47740e26fb6fa..4622c3710e93e 100644 --- a/tests/ui/macros/macro-doc-comments.rs +++ b/tests/ui/macros/macro-doc-comments.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(non_snake_case)] macro_rules! doc { diff --git a/tests/ui/macros/macro-doc-escapes.rs b/tests/ui/macros/macro-doc-escapes.rs index 81c8d3383b579..77d9a5c048fa1 100644 --- a/tests/ui/macros/macro-doc-escapes.rs +++ b/tests/ui/macros/macro-doc-escapes.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass // When expanding a macro, documentation attributes (including documentation comments) must be // passed "as is" without being parsed. Otherwise, some text will be incorrectly interpreted as // escape sequences, leading to an ICE. diff --git a/tests/ui/macros/macro-follow-rpass.rs b/tests/ui/macros/macro-follow-rpass.rs index 8551b1887708e..dfaacefc528ae 100644 --- a/tests/ui/macros/macro-follow-rpass.rs +++ b/tests/ui/macros/macro-follow-rpass.rs @@ -1,5 +1,5 @@ //@ edition:2015..2021 -//@ run-pass +//@ check-pass #![allow(unused_macros)] // Check the macro follow sets (see corresponding cfail test). diff --git a/tests/ui/macros/macro-followed-by-seq.rs b/tests/ui/macros/macro-followed-by-seq.rs index f4756d42088ad..3643836fa031f 100644 --- a/tests/ui/macros/macro-followed-by-seq.rs +++ b/tests/ui/macros/macro-followed-by-seq.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(unused_macros)] // Regression test for issue #25436: check that things which can be // followed by any token also permit X* to come afterwards. diff --git a/tests/ui/macros/macro-in-fn.rs b/tests/ui/macros/macro-in-fn.rs index 2ffa6b2e4572e..48085b8b221ba 100644 --- a/tests/ui/macros/macro-in-fn.rs +++ b/tests/ui/macros/macro-in-fn.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![feature(decl_macro)] pub fn moo() { diff --git a/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs b/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs index e80c712b03dc5..ed8974c23e714 100644 --- a/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs +++ b/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass macro_rules! four { () => (4) diff --git a/tests/ui/macros/macro-multiple-items.rs b/tests/ui/macros/macro-multiple-items.rs index c746d1bc51881..46b561af4467e 100644 --- a/tests/ui/macros/macro-multiple-items.rs +++ b/tests/ui/macros/macro-multiple-items.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass macro_rules! make_foo { () => ( struct Foo; diff --git a/tests/ui/macros/macro-named-default.rs b/tests/ui/macros/macro-named-default.rs index bca0e005083d2..c7eac831cffb8 100644 --- a/tests/ui/macros/macro-named-default.rs +++ b/tests/ui/macros/macro-named-default.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass macro_rules! default { ($($x:tt)*) => { $($x)* } } diff --git a/tests/ui/macros/macro-nt-list.rs b/tests/ui/macros/macro-nt-list.rs index b7b260c5398cb..56ea917c3be99 100644 --- a/tests/ui/macros/macro-nt-list.rs +++ b/tests/ui/macros/macro-nt-list.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass macro_rules! list { ( ($($id:ident),*) ) => (()); diff --git a/tests/ui/macros/macro-pat-follow-2018.rs b/tests/ui/macros/macro-pat-follow-2018.rs index 6dcb841fec15f..b2a556fce6f9e 100644 --- a/tests/ui/macros/macro-pat-follow-2018.rs +++ b/tests/ui/macros/macro-pat-follow-2018.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass //@ edition:2018 macro_rules! pat_bar { diff --git a/tests/ui/macros/macro-pub-matcher.rs b/tests/ui/macros/macro-pub-matcher.rs index e0b03dbbeb1b3..20cacab390d5a 100644 --- a/tests/ui/macros/macro-pub-matcher.rs +++ b/tests/ui/macros/macro-pub-matcher.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code, unused_imports, unused_macro_rules)] /** diff --git a/tests/ui/macros/macro-seq-followed-by-seq.rs b/tests/ui/macros/macro-seq-followed-by-seq.rs index 3661744284eef..cf5a1c1170313 100644 --- a/tests/ui/macros/macro-seq-followed-by-seq.rs +++ b/tests/ui/macros/macro-seq-followed-by-seq.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass // Test of allowing two sequences repetitions in a row, // functionality added as byproduct of RFC amendment #1384 // https://github.com/rust-lang/rfcs/pull/1384 diff --git a/tests/ui/macros/macro-use-all-and-none.rs b/tests/ui/macros/macro-use-all-and-none.rs index f1acff4840382..53d450ed8d581 100644 --- a/tests/ui/macros/macro-use-all-and-none.rs +++ b/tests/ui/macros/macro-use-all-and-none.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass //@ aux-build:two_macros-rpass.rs #![warn(unused_attributes)] diff --git a/tests/ui/macros/macro-use-all.rs b/tests/ui/macros/macro-use-all.rs index a7fd3dfa5ce60..06b96da7f8b17 100644 --- a/tests/ui/macros/macro-use-all.rs +++ b/tests/ui/macros/macro-use-all.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass //@ aux-build:two_macros.rs #[macro_use] diff --git a/tests/ui/macros/macro-use-both.rs b/tests/ui/macros/macro-use-both.rs index e49f346c8e3e8..c41797513f6a3 100644 --- a/tests/ui/macros/macro-use-both.rs +++ b/tests/ui/macros/macro-use-both.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass //@ aux-build:two_macros.rs #[macro_use(macro_one, macro_two)] diff --git a/tests/ui/macros/macro-use-one.rs b/tests/ui/macros/macro-use-one.rs index 2b048651ccccf..93f7c212e0012 100644 --- a/tests/ui/macros/macro-use-one.rs +++ b/tests/ui/macros/macro-use-one.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass //@ aux-build:two_macros.rs #[macro_use(macro_two)] diff --git a/tests/ui/macros/parse-complex-macro-invoc-op.rs b/tests/ui/macros/parse-complex-macro-invoc-op.rs index 2c384bdb42efe..bbb01facc6242 100644 --- a/tests/ui/macros/parse-complex-macro-invoc-op.rs +++ b/tests/ui/macros/parse-complex-macro-invoc-op.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(unused_must_use)] #![allow(dead_code)] #![allow(unused_assignments)] diff --git a/tests/ui/macros/pub-item-inside-macro.rs b/tests/ui/macros/pub-item-inside-macro.rs index c37945a2d672a..679987ac1f4a3 100644 --- a/tests/ui/macros/pub-item-inside-macro.rs +++ b/tests/ui/macros/pub-item-inside-macro.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass // Issue #14660 diff --git a/tests/ui/macros/pub-method-inside-macro.rs b/tests/ui/macros/pub-method-inside-macro.rs index dd4e6fda8be9b..23d8c454d6973 100644 --- a/tests/ui/macros/pub-method-inside-macro.rs +++ b/tests/ui/macros/pub-method-inside-macro.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass // Issue #17436 diff --git a/tests/ui/macros/semi-after-macro-ty.rs b/tests/ui/macros/semi-after-macro-ty.rs index 60afc3b445061..ff026c53b1d70 100644 --- a/tests/ui/macros/semi-after-macro-ty.rs +++ b/tests/ui/macros/semi-after-macro-ty.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass macro_rules! foo { ($t:ty; $p:path;) => {} } diff --git a/tests/ui/macros/two-macro-use.rs b/tests/ui/macros/two-macro-use.rs index 8bb3c9da30512..733853f8d2347 100644 --- a/tests/ui/macros/two-macro-use.rs +++ b/tests/ui/macros/two-macro-use.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass //@ aux-build:two_macros.rs #[macro_use(macro_one)] diff --git a/tests/ui/macros/type-macros-simple.rs b/tests/ui/macros/type-macros-simple.rs index d189b881f7dda..800a796491be9 100644 --- a/tests/ui/macros/type-macros-simple.rs +++ b/tests/ui/macros/type-macros-simple.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] #![allow(unused_variables)] #![allow(non_local_definitions)] diff --git a/tests/ui/macros/use-macro-self.rs b/tests/ui/macros/use-macro-self.rs index 1d15b8386af96..cf5a410c6edfc 100644 --- a/tests/ui/macros/use-macro-self.rs +++ b/tests/ui/macros/use-macro-self.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(unused_imports)] //@ aux-build:use-macro-self.rs From 9ce6863063006951d678d0ec8a9e037731478609 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 19 Mar 2026 14:40:33 +0000 Subject: [PATCH 06/15] merge `die-macro` tests into `panic-macro-basic.rs` --- tests/ui/macros/die-macro-2.rs | 7 ------- tests/ui/macros/die-macro-pure.rs | 11 ----------- tests/ui/macros/die-macro.rs | 16 ---------------- .../{die-macro-expr.rs => panic-macro-basic.rs} | 9 ++++++++- 4 files changed, 8 insertions(+), 35 deletions(-) delete mode 100644 tests/ui/macros/die-macro-2.rs delete mode 100644 tests/ui/macros/die-macro-pure.rs delete mode 100644 tests/ui/macros/die-macro.rs rename tests/ui/macros/{die-macro-expr.rs => panic-macro-basic.rs} (53%) diff --git a/tests/ui/macros/die-macro-2.rs b/tests/ui/macros/die-macro-2.rs deleted file mode 100644 index d802f189ce1af..0000000000000 --- a/tests/ui/macros/die-macro-2.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-fail -//@ error-pattern:test -//@ needs-subprocess - -fn main() { - panic!("test"); -} diff --git a/tests/ui/macros/die-macro-pure.rs b/tests/ui/macros/die-macro-pure.rs deleted file mode 100644 index d84787705a1aa..0000000000000 --- a/tests/ui/macros/die-macro-pure.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-fail -//@ error-pattern:test -//@ needs-subprocess - -fn f() { - panic!("test"); -} - -fn main() { - f(); -} diff --git a/tests/ui/macros/die-macro.rs b/tests/ui/macros/die-macro.rs deleted file mode 100644 index b717eed3fb438..0000000000000 --- a/tests/ui/macros/die-macro.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -// Just testing that panic!() type checks in statement or expr - - -#![allow(unreachable_code)] - -fn f() { - panic!(); - - let _x: isize = panic!(); -} - -pub fn main() { - -} diff --git a/tests/ui/macros/die-macro-expr.rs b/tests/ui/macros/panic-macro-basic.rs similarity index 53% rename from tests/ui/macros/die-macro-expr.rs rename to tests/ui/macros/panic-macro-basic.rs index f4fefb0ca37dd..96ed4265ef6eb 100644 --- a/tests/ui/macros/die-macro-expr.rs +++ b/tests/ui/macros/panic-macro-basic.rs @@ -1,7 +1,14 @@ //@ run-fail //@ error-pattern:test //@ needs-subprocess +// Just testing that panic!() type checks in statement or expr -fn main() { +fn f() { let __isize: isize = panic!("test"); + + panic!(); +} + +fn main() { + f(); } From ad79aa764b28a1d8b57a431326f00a7061cc760f Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 20 Mar 2026 09:04:03 +0000 Subject: [PATCH 07/15] merge many repetitive `classes-*` tests --- tests/ui/structs-enums/auxiliary/cci_class.rs | 14 --- .../ui/structs-enums/auxiliary/cci_class_2.rs | 19 --- .../ui/structs-enums/auxiliary/cci_class_3.rs | 19 --- .../ui/structs-enums/auxiliary/cci_class_4.rs | 21 ++++ .../structs-enums/auxiliary/cci_class_cast.rs | 50 -------- .../auxiliary/cci_class_trait.rs | 5 - .../class-cast-to-trait-cross-crate-2.rs | 17 --- .../class-cast-to-trait-multiple-types.rs | 94 --------------- tests/ui/structs-enums/class-cast-to-trait.rs | 60 ---------- tests/ui/structs-enums/class-exports.rs | 31 ----- .../class-implement-trait-cross-crate.rs | 59 ---------- .../structs-enums/class-implement-traits.rs | 64 ---------- .../structs-enums/class-method-cross-crate.rs | 13 --- .../class-methods-cross-crate.rs | 14 --- tests/ui/structs-enums/class-methods.rs | 30 ----- tests/ui/structs-enums/class-separate-impl.rs | 63 ---------- tests/ui/structs-enums/class-str-field.rs | 20 ---- tests/ui/structs-enums/classes-cross-crate.rs | 109 +++++++++++++++++- .../classes-simple-cross-crate.rs | 12 -- .../ui/structs-enums/classes-simple-method.rs | 28 ----- tests/ui/structs-enums/classes-simple.rs | 23 ---- tests/ui/structs-enums/classes.rs | 51 -------- 22 files changed, 128 insertions(+), 688 deletions(-) delete mode 100644 tests/ui/structs-enums/auxiliary/cci_class.rs delete mode 100644 tests/ui/structs-enums/auxiliary/cci_class_2.rs delete mode 100644 tests/ui/structs-enums/auxiliary/cci_class_3.rs delete mode 100644 tests/ui/structs-enums/auxiliary/cci_class_cast.rs delete mode 100644 tests/ui/structs-enums/auxiliary/cci_class_trait.rs delete mode 100644 tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs delete mode 100644 tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs delete mode 100644 tests/ui/structs-enums/class-cast-to-trait.rs delete mode 100644 tests/ui/structs-enums/class-exports.rs delete mode 100644 tests/ui/structs-enums/class-implement-trait-cross-crate.rs delete mode 100644 tests/ui/structs-enums/class-implement-traits.rs delete mode 100644 tests/ui/structs-enums/class-method-cross-crate.rs delete mode 100644 tests/ui/structs-enums/class-methods-cross-crate.rs delete mode 100644 tests/ui/structs-enums/class-methods.rs delete mode 100644 tests/ui/structs-enums/class-separate-impl.rs delete mode 100644 tests/ui/structs-enums/class-str-field.rs delete mode 100644 tests/ui/structs-enums/classes-simple-cross-crate.rs delete mode 100644 tests/ui/structs-enums/classes-simple-method.rs delete mode 100644 tests/ui/structs-enums/classes-simple.rs delete mode 100644 tests/ui/structs-enums/classes.rs diff --git a/tests/ui/structs-enums/auxiliary/cci_class.rs b/tests/ui/structs-enums/auxiliary/cci_class.rs deleted file mode 100644 index de2945d746045..0000000000000 --- a/tests/ui/structs-enums/auxiliary/cci_class.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub mod kitties { - pub struct cat { - meows : usize, - - pub how_hungry : isize, - } - - pub fn cat(in_x : usize, in_y : isize) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } - } -} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_2.rs b/tests/ui/structs-enums/auxiliary/cci_class_2.rs deleted file mode 100644 index c3de3150e6978..0000000000000 --- a/tests/ui/structs-enums/auxiliary/cci_class_2.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub mod kitties { - pub struct cat { - meows : usize, - - pub how_hungry : isize, - - } - - impl cat { - pub fn speak(&self) {} - } - - pub fn cat(in_x : usize, in_y : isize) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } - } -} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_3.rs b/tests/ui/structs-enums/auxiliary/cci_class_3.rs deleted file mode 100644 index fb7fad0b5a2e7..0000000000000 --- a/tests/ui/structs-enums/auxiliary/cci_class_3.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub mod kitties { - pub struct cat { - meows : usize, - - pub how_hungry : isize, - } - - impl cat { - pub fn speak(&mut self) { self.meows += 1; } - pub fn meow_count(&mut self) -> usize { self.meows } - } - - pub fn cat(in_x : usize, in_y : isize) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } - } -} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_4.rs b/tests/ui/structs-enums/auxiliary/cci_class_4.rs index 85aa3bc8c0df9..f8c243c9f3955 100644 --- a/tests/ui/structs-enums/auxiliary/cci_class_4.rs +++ b/tests/ui/structs-enums/auxiliary/cci_class_4.rs @@ -1,4 +1,6 @@ pub mod kitties { + use std::fmt; + #[derive(Clone)] pub struct cat { meows : usize, @@ -19,6 +21,8 @@ pub mod kitties { return false; } } + + pub fn noop(&self) {} } impl cat { @@ -29,6 +33,9 @@ pub mod kitties { self.how_hungry += 1; } } + pub fn meow_count(&self) -> usize { + self.meows + } } pub fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { @@ -38,4 +45,18 @@ pub mod kitties { name: in_name } } + pub fn cat_unnamed(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: String::new(), + } + } + + impl fmt::Display for cat { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.name) + } + } + } diff --git a/tests/ui/structs-enums/auxiliary/cci_class_cast.rs b/tests/ui/structs-enums/auxiliary/cci_class_cast.rs deleted file mode 100644 index dfc3c56ddee70..0000000000000 --- a/tests/ui/structs-enums/auxiliary/cci_class_cast.rs +++ /dev/null @@ -1,50 +0,0 @@ -pub mod kitty { - use std::fmt; - - pub struct cat { - meows : usize, - pub how_hungry : isize, - pub name : String, - } - - impl fmt::Display for cat { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.name) - } - } - - impl cat { - fn meow(&mut self) { - println!("Meow"); - self.meows += 1; - if self.meows % 5 == 0 { - self.how_hungry += 1; - } - } - - } - - impl cat { - pub fn speak(&mut self) { self.meow(); } - - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - println!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } - else { - println!("Not hungry!"); - return false; - } - } - } - - pub fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } - } -} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_trait.rs b/tests/ui/structs-enums/auxiliary/cci_class_trait.rs deleted file mode 100644 index 2d02b591c5559..0000000000000 --- a/tests/ui/structs-enums/auxiliary/cci_class_trait.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod animals { - pub trait noisy { - fn speak(&mut self); - } -} diff --git a/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs b/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs deleted file mode 100644 index d4caa19135e8a..0000000000000 --- a/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ run-pass -//@ aux-build:cci_class_cast.rs - -extern crate cci_class_cast; - -use cci_class_cast::kitty::cat; - -fn print_out(thing: Box, expected: String) { - let actual = (*thing).to_string(); - println!("{}", actual); - assert_eq!(actual.to_string(), expected); -} - -pub fn main() { - let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; - print_out(nyan, "nyan".to_string()); -} diff --git a/tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs b/tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs deleted file mode 100644 index 658e9d2117dc3..0000000000000 --- a/tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs +++ /dev/null @@ -1,94 +0,0 @@ -//@ run-pass -#![allow(non_camel_case_types)] -#![allow(dead_code)] - -trait noisy { - fn speak(&mut self) -> isize; -} - -struct dog { - barks: usize, - - volume: isize, -} - -impl dog { - fn bark(&mut self) -> isize { - println!("Woof {} {}", self.barks, self.volume); - self.barks += 1_usize; - if self.barks % 3_usize == 0_usize { - self.volume += 1; - } - if self.barks % 10_usize == 0_usize { - self.volume -= 2; - } - println!("Grrr {} {}", self.barks, self.volume); - self.volume - } -} - -impl noisy for dog { - fn speak(&mut self) -> isize { - self.bark() - } -} - -fn dog() -> dog { - dog { - volume: 0, - barks: 0_usize - } -} - -#[derive(Clone)] -struct cat { - meows: usize, - - how_hungry: isize, - name: String, -} - -impl noisy for cat { - fn speak(&mut self) -> isize { - self.meow() as isize - } -} - -impl cat { - pub fn meow_count(&self) -> usize { - self.meows - } -} - -impl cat { - fn meow(&mut self) -> usize { - println!("Meow"); - self.meows += 1_usize; - if self.meows % 5_usize == 0_usize { - self.how_hungry += 1; - } - self.meows - } -} - -fn cat(in_x: usize, in_y: isize, in_name: String) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} - - -fn annoy_neighbors(critter: &mut dyn noisy) { - for _i in 0_usize..10 { critter.speak(); } -} - -pub fn main() { - let mut nyan: cat = cat(0_usize, 2, "nyan".to_string()); - let mut whitefang: dog = dog(); - annoy_neighbors(&mut nyan); - annoy_neighbors(&mut whitefang); - assert_eq!(nyan.meow_count(), 10_usize); - assert_eq!(whitefang.volume, 1); -} diff --git a/tests/ui/structs-enums/class-cast-to-trait.rs b/tests/ui/structs-enums/class-cast-to-trait.rs deleted file mode 100644 index bbbde34ec096c..0000000000000 --- a/tests/ui/structs-enums/class-cast-to-trait.rs +++ /dev/null @@ -1,60 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(unused_mut)] -#![allow(non_camel_case_types)] - -//@ ignore-freebsd FIXME fails on BSD - - -trait noisy { - fn speak(&mut self); -} - -struct cat { - meows: usize, - how_hungry: isize, - name: String, -} - -impl noisy for cat { - fn speak(&mut self) { self.meow(); } -} - -impl cat { - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - println!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } - else { - println!("Not hungry!"); - return false; - } - } -} - -impl cat { - fn meow(&mut self) { - println!("Meow"); - self.meows += 1; - if self.meows % 5 == 0 { - self.how_hungry += 1; - } - } -} - -fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} - - -pub fn main() { - let mut nyan = cat(0, 2, "nyan".to_string()); - let mut nyan: &mut dyn noisy = &mut nyan; - nyan.speak(); -} diff --git a/tests/ui/structs-enums/class-exports.rs b/tests/ui/structs-enums/class-exports.rs deleted file mode 100644 index 53d0e3db6f5f4..0000000000000 --- a/tests/ui/structs-enums/class-exports.rs +++ /dev/null @@ -1,31 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - -/* Test that exporting a class also exports its - public fields and methods */ - -use kitty::cat; - -mod kitty { - pub struct cat { - meows: usize, - name: String, - } - - impl cat { - pub fn get_name(&self) -> String { self.name.clone() } - } - - pub fn cat(in_name: String) -> cat { - cat { - name: in_name, - meows: 0 - } - } -} - -pub fn main() { - assert_eq!(cat("Spreckles".to_string()).get_name(), - "Spreckles".to_string()); -} diff --git a/tests/ui/structs-enums/class-implement-trait-cross-crate.rs b/tests/ui/structs-enums/class-implement-trait-cross-crate.rs deleted file mode 100644 index 781ac6ad10d2c..0000000000000 --- a/tests/ui/structs-enums/class-implement-trait-cross-crate.rs +++ /dev/null @@ -1,59 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - -//@ aux-build:cci_class_trait.rs -extern crate cci_class_trait; -use cci_class_trait::animals::noisy; - -struct cat { - meows: usize, - - how_hungry : isize, - name : String, -} - -impl cat { - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - println!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } - else { - println!("Not hungry!"); - return false; - } - } -} - -impl noisy for cat { - fn speak(&mut self) { self.meow(); } -} - -impl cat { - fn meow(&mut self) { - println!("Meow"); - self.meows += 1_usize; - if self.meows % 5_usize == 0_usize { - self.how_hungry += 1; - } - } -} - -fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} - - -pub fn main() { - let mut nyan = cat(0_usize, 2, "nyan".to_string()); - nyan.eat(); - assert!(!nyan.eat()); - for _ in 1_usize..10_usize { nyan.speak(); }; - assert!(nyan.eat()); -} diff --git a/tests/ui/structs-enums/class-implement-traits.rs b/tests/ui/structs-enums/class-implement-traits.rs deleted file mode 100644 index 3a514ff9d7581..0000000000000 --- a/tests/ui/structs-enums/class-implement-traits.rs +++ /dev/null @@ -1,64 +0,0 @@ -//@ run-pass -#![allow(non_camel_case_types)] -#![allow(dead_code)] - -trait noisy { - fn speak(&mut self); -} - -#[derive(Clone)] -struct cat { - meows : usize, - - how_hungry : isize, - name : String, -} - -impl cat { - fn meow(&mut self) { - println!("Meow"); - self.meows += 1_usize; - if self.meows % 5_usize == 0_usize { - self.how_hungry += 1; - } - } -} - -impl cat { - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - println!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } else { - println!("Not hungry!"); - return false; - } - } -} - -impl noisy for cat { - fn speak(&mut self) { self.meow(); } -} - -fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name.clone() - } -} - - -fn make_speak(mut c: C) { - c.speak(); -} - -pub fn main() { - let mut nyan = cat(0_usize, 2, "nyan".to_string()); - nyan.eat(); - assert!(!nyan.eat()); - for _ in 1_usize..10_usize { - make_speak(nyan.clone()); - } -} diff --git a/tests/ui/structs-enums/class-method-cross-crate.rs b/tests/ui/structs-enums/class-method-cross-crate.rs deleted file mode 100644 index f73999a24501f..0000000000000 --- a/tests/ui/structs-enums/class-method-cross-crate.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ run-pass -//@ aux-build:cci_class_2.rs - -extern crate cci_class_2; -use cci_class_2::kitties::cat; - -pub fn main() { - let nyan : cat = cat(52, 99); - let kitty = cat(1000, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(); -} diff --git a/tests/ui/structs-enums/class-methods-cross-crate.rs b/tests/ui/structs-enums/class-methods-cross-crate.rs deleted file mode 100644 index b2c48248a6712..0000000000000 --- a/tests/ui/structs-enums/class-methods-cross-crate.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ run-pass -//@ aux-build:cci_class_3.rs - -extern crate cci_class_3; -use cci_class_3::kitties::cat; - -pub fn main() { - let mut nyan : cat = cat(52, 99); - let kitty = cat(1000, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(); - assert_eq!(nyan.meow_count(), 53); -} diff --git a/tests/ui/structs-enums/class-methods.rs b/tests/ui/structs-enums/class-methods.rs deleted file mode 100644 index b0dbbbec5224f..0000000000000 --- a/tests/ui/structs-enums/class-methods.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ run-pass -#![allow(non_camel_case_types)] - - -struct cat { - meows : usize, - - how_hungry : isize, -} - -impl cat { - pub fn speak(&mut self) { self.meows += 1; } - pub fn meow_count(&mut self) -> usize { self.meows } -} - -fn cat(in_x: usize, in_y: isize) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } -} - -pub fn main() { - let mut nyan: cat = cat(52, 99); - let kitty = cat(1000, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(); - assert_eq!(nyan.meow_count(), 53); -} diff --git a/tests/ui/structs-enums/class-separate-impl.rs b/tests/ui/structs-enums/class-separate-impl.rs deleted file mode 100644 index 2768e284c1736..0000000000000 --- a/tests/ui/structs-enums/class-separate-impl.rs +++ /dev/null @@ -1,63 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - -use std::fmt; - -struct cat { - meows : usize, - - how_hungry : isize, - name : String, -} - -impl cat { - pub fn speak(&mut self) { self.meow(); } - - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - println!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } - else { - println!("Not hungry!"); - return false; - } - } -} - -impl cat { - fn meow(&mut self) { - println!("Meow"); - self.meows += 1; - if self.meows % 5 == 0 { - self.how_hungry += 1; - } - } -} - -fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} - -impl fmt::Display for cat { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.name) - } -} - -fn print_out(thing: Box, expected: String) { - let actual = (*thing).to_string(); - println!("{}", actual); - assert_eq!(actual.to_string(), expected); -} - -pub fn main() { - let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; - print_out(nyan, "nyan".to_string()); -} diff --git a/tests/ui/structs-enums/class-str-field.rs b/tests/ui/structs-enums/class-str-field.rs deleted file mode 100644 index 24f648afc90b1..0000000000000 --- a/tests/ui/structs-enums/class-str-field.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - - -struct cat { - - name : String, - -} - -fn cat(in_name: String) -> cat { - cat { - name: in_name - } -} - -pub fn main() { - let _nyan = cat("nyan".to_string()); -} diff --git a/tests/ui/structs-enums/classes-cross-crate.rs b/tests/ui/structs-enums/classes-cross-crate.rs index 6fb5f2e3cc9d7..d859cbdc76dae 100644 --- a/tests/ui/structs-enums/classes-cross-crate.rs +++ b/tests/ui/structs-enums/classes-cross-crate.rs @@ -1,13 +1,118 @@ //@ run-pass //@ aux-build:cci_class_4.rs +#![allow(non_camel_case_types)] extern crate cci_class_4; -use cci_class_4::kitties::cat; +use cci_class_4::kitties::{cat, cat_unnamed}; -pub fn main() { +fn simple_cross_crate() { + let nyan : cat = cat_unnamed(52, 99); + let kitty = cat_unnamed(1000, 2); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); + nyan.noop(); +} + +fn cross_crate() { let mut nyan = cat(0_usize, 2, "nyan".to_string()); nyan.eat(); assert!(!nyan.eat()); for _ in 1_usize..10_usize { nyan.speak(); }; assert!(nyan.eat()); } + + +fn print_out(thing: Box, expected: String) { + let actual = (*thing).to_string(); + println!("{}", actual); + assert_eq!(actual.to_string(), expected); +} + +fn separate_impl() { + let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; + print_out(nyan, "nyan".to_string()); +} + +trait noisy { + fn speak(&mut self) -> isize; +} + +impl noisy for cat { + fn speak(&mut self) -> isize { self.meow(); 0 } +} + +fn make_speak(mut c: C) { + c.speak(); +} + +fn implement_traits() { + let mut nyan = cat(0_usize, 2, "nyan".to_string()); + nyan.eat(); + assert!(!nyan.eat()); + for _ in 1_usize..10_usize { + make_speak(nyan.clone()); + } +} + + +struct dog { + barks: usize, + + volume: isize, +} + +impl dog { + fn bark(&mut self) -> isize { + println!("Woof {} {}", self.barks, self.volume); + self.barks += 1_usize; + if self.barks % 3_usize == 0_usize { + self.volume += 1; + } + if self.barks % 10_usize == 0_usize { + self.volume -= 2; + } + println!("Grrr {} {}", self.barks, self.volume); + self.volume + } +} + +impl noisy for dog { + fn speak(&mut self) -> isize { + self.bark() + } +} + +fn dog() -> dog { + dog { + volume: 0, + barks: 0_usize + } +} + +fn annoy_neighbors(critter: &mut dyn noisy) { + for _i in 0_usize..10 { critter.speak(); } +} + +fn multiple_types() { + let mut nyan: cat = cat(0_usize, 2, "nyan".to_string()); + let mut whitefang: dog = dog(); + annoy_neighbors(&mut nyan); + annoy_neighbors(&mut whitefang); + assert_eq!(nyan.meow_count(), 10_usize); + assert_eq!(whitefang.volume, 1); +} + +fn cast_to_trait() { + let mut nyan = cat(0, 2, "nyan".to_string()); + let nyan: &mut dyn noisy = &mut nyan; + nyan.speak(); +} + +fn main() { + simple_cross_crate(); + cross_crate(); + separate_impl(); + implement_traits(); + multiple_types(); + cast_to_trait(); +} diff --git a/tests/ui/structs-enums/classes-simple-cross-crate.rs b/tests/ui/structs-enums/classes-simple-cross-crate.rs deleted file mode 100644 index 1548f768b6f3c..0000000000000 --- a/tests/ui/structs-enums/classes-simple-cross-crate.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ run-pass -//@ aux-build:cci_class.rs - -extern crate cci_class; -use cci_class::kitties::cat; - -pub fn main() { - let nyan : cat = cat(52, 99); - let kitty = cat(1000, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); -} diff --git a/tests/ui/structs-enums/classes-simple-method.rs b/tests/ui/structs-enums/classes-simple-method.rs deleted file mode 100644 index 562fd5909815c..0000000000000 --- a/tests/ui/structs-enums/classes-simple-method.rs +++ /dev/null @@ -1,28 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - -struct cat { - meows : usize, - - how_hungry : isize, -} - -impl cat { - pub fn speak(&mut self) {} -} - -fn cat(in_x : usize, in_y : isize) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } -} - -pub fn main() { - let mut nyan : cat = cat(52, 99); - let kitty = cat(1000, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.speak(); -} diff --git a/tests/ui/structs-enums/classes-simple.rs b/tests/ui/structs-enums/classes-simple.rs deleted file mode 100644 index d870a3101f1ae..0000000000000 --- a/tests/ui/structs-enums/classes-simple.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - -struct cat { - meows : usize, - - how_hungry : isize, -} - -fn cat(in_x : usize, in_y : isize) -> cat { - cat { - meows: in_x, - how_hungry: in_y - } -} - -pub fn main() { - let nyan : cat = cat(52, 99); - let kitty = cat(1000, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); -} diff --git a/tests/ui/structs-enums/classes.rs b/tests/ui/structs-enums/classes.rs deleted file mode 100644 index 05976f6a759af..0000000000000 --- a/tests/ui/structs-enums/classes.rs +++ /dev/null @@ -1,51 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - -struct cat { - meows : usize, - - how_hungry : isize, - name : String, -} - -impl cat { - pub fn speak(&mut self) { self.meow(); } - - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - println!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } else { - println!("Not hungry!"); - return false; - } - } -} - -impl cat { - fn meow(&mut self) { - println!("Meow"); - self.meows += 1_usize; - if self.meows % 5_usize == 0_usize { - self.how_hungry += 1; - } - } -} - -fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} - -pub fn main() { - let mut nyan = cat(0_usize, 2, "nyan".to_string()); - nyan.eat(); - assert!(!nyan.eat()); - for _ in 1_usize..10_usize { nyan.speak(); }; - assert!(nyan.eat()); -} From 0941e187ef276a707025f01ce513cf594611e834 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 20 Mar 2026 09:17:48 +0000 Subject: [PATCH 08/15] reformat merged files --- .../ui/structs-enums/auxiliary/cci_class_4.rs | 90 +++++++++---------- tests/ui/structs-enums/classes-cross-crate.rs | 89 +++++++++--------- 2 files changed, 86 insertions(+), 93 deletions(-) diff --git a/tests/ui/structs-enums/auxiliary/cci_class_4.rs b/tests/ui/structs-enums/auxiliary/cci_class_4.rs index f8c243c9f3955..fff7b7809571a 100644 --- a/tests/ui/structs-enums/auxiliary/cci_class_4.rs +++ b/tests/ui/structs-enums/auxiliary/cci_class_4.rs @@ -1,62 +1,54 @@ -pub mod kitties { - use std::fmt; - #[derive(Clone)] - pub struct cat { - meows : usize, - - pub how_hungry : isize, - pub name : String, - } +use std::fmt; - impl cat { - pub fn speak(&mut self) { self.meow(); } - - pub fn eat(&mut self) -> bool { - if self.how_hungry > 0 { - println!("OM NOM NOM"); - self.how_hungry -= 2; - return true; - } else { - println!("Not hungry!"); - return false; - } - } +#[derive(Clone)] +pub struct Cat { + meows: usize, + + pub how_hungry: isize, + pub name: String, +} - pub fn noop(&self) {} +impl Cat { + pub fn speak(&mut self) { + self.meow(); } - impl cat { - pub fn meow(&mut self) { - println!("Meow"); - self.meows += 1; - if self.meows % 5 == 0 { - self.how_hungry += 1; - } - } - pub fn meow_count(&self) -> usize { - self.meows + pub fn eat(&mut self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } else { + println!("Not hungry!"); + return false; } } - pub fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name + pub fn noop(&self) {} +} + +impl Cat { + pub fn meow(&mut self) { + println!("Meow"); + self.meows += 1; + if self.meows % 5 == 0 { + self.how_hungry += 1; } } - pub fn cat_unnamed(in_x : usize, in_y : isize) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: String::new(), - } + pub fn meow_count(&self) -> usize { + self.meows } +} - impl fmt::Display for cat { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.name) - } - } +pub fn cat(in_x: usize, in_y: isize, in_name: String) -> Cat { + Cat { meows: in_x, how_hungry: in_y, name: in_name } +} +pub fn cat_unnamed(in_x: usize, in_y: isize) -> Cat { + Cat { meows: in_x, how_hungry: in_y, name: String::new() } +} +impl fmt::Display for Cat { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.name) + } } diff --git a/tests/ui/structs-enums/classes-cross-crate.rs b/tests/ui/structs-enums/classes-cross-crate.rs index d859cbdc76dae..85454bb15a7bb 100644 --- a/tests/ui/structs-enums/classes-cross-crate.rs +++ b/tests/ui/structs-enums/classes-cross-crate.rs @@ -1,47 +1,50 @@ //@ run-pass //@ aux-build:cci_class_4.rs -#![allow(non_camel_case_types)] extern crate cci_class_4; -use cci_class_4::kitties::{cat, cat_unnamed}; +use cci_class_4::*; fn simple_cross_crate() { - let nyan : cat = cat_unnamed(52, 99); - let kitty = cat_unnamed(1000, 2); - assert_eq!(nyan.how_hungry, 99); - assert_eq!(kitty.how_hungry, 2); - nyan.noop(); + let nyan: Cat = cat_unnamed(52, 99); + let kitty = cat_unnamed(1000, 2); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); + nyan.noop(); } fn cross_crate() { let mut nyan = cat(0_usize, 2, "nyan".to_string()); nyan.eat(); assert!(!nyan.eat()); - for _ in 1_usize..10_usize { nyan.speak(); }; + for _ in 1_usize..10_usize { + nyan.speak(); + } assert!(nyan.eat()); } - fn print_out(thing: Box, expected: String) { - let actual = (*thing).to_string(); - println!("{}", actual); - assert_eq!(actual.to_string(), expected); + let actual = (*thing).to_string(); + println!("{}", actual); + assert_eq!(actual.to_string(), expected); } fn separate_impl() { - let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; - print_out(nyan, "nyan".to_string()); + let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; + print_out(nyan, "nyan".to_string()); } -trait noisy { +trait Noisy { fn speak(&mut self) -> isize; } -impl noisy for cat { - fn speak(&mut self) -> isize { self.meow(); 0 } +impl Noisy for Cat { + fn speak(&mut self) -> isize { + self.meow(); + 0 + } } -fn make_speak(mut c: C) { +fn make_speak(mut c: C) { c.speak(); } @@ -54,48 +57,46 @@ fn implement_traits() { } } +struct Dog { + barks: usize, -struct dog { - barks: usize, - - volume: isize, + volume: isize, } -impl dog { +impl Dog { fn bark(&mut self) -> isize { - println!("Woof {} {}", self.barks, self.volume); - self.barks += 1_usize; - if self.barks % 3_usize == 0_usize { - self.volume += 1; - } - if self.barks % 10_usize == 0_usize { - self.volume -= 2; - } - println!("Grrr {} {}", self.barks, self.volume); - self.volume + println!("Woof {} {}", self.barks, self.volume); + self.barks += 1_usize; + if self.barks % 3_usize == 0_usize { + self.volume += 1; + } + if self.barks % 10_usize == 0_usize { + self.volume -= 2; + } + println!("Grrr {} {}", self.barks, self.volume); + self.volume } } -impl noisy for dog { +impl Noisy for Dog { fn speak(&mut self) -> isize { self.bark() } } -fn dog() -> dog { - dog { - volume: 0, - barks: 0_usize - } +fn dog() -> Dog { + Dog { volume: 0, barks: 0_usize } } -fn annoy_neighbors(critter: &mut dyn noisy) { - for _i in 0_usize..10 { critter.speak(); } +fn annoy_neighbors(critter: &mut dyn Noisy) { + for _i in 0_usize..10 { + critter.speak(); + } } fn multiple_types() { - let mut nyan: cat = cat(0_usize, 2, "nyan".to_string()); - let mut whitefang: dog = dog(); + let mut nyan: Cat = cat(0_usize, 2, "nyan".to_string()); + let mut whitefang: Dog = dog(); annoy_neighbors(&mut nyan); annoy_neighbors(&mut whitefang); assert_eq!(nyan.meow_count(), 10_usize); @@ -104,7 +105,7 @@ fn multiple_types() { fn cast_to_trait() { let mut nyan = cat(0, 2, "nyan".to_string()); - let nyan: &mut dyn noisy = &mut nyan; + let nyan: &mut dyn Noisy = &mut nyan; nyan.speak(); } From 0486281b303d838694f97d8b35531a20ed0ee1c9 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 20 Mar 2026 09:48:54 +0000 Subject: [PATCH 09/15] delete some tests that lost their meaning --- tests/ui/structs-enums/export-abstract-tag.rs | 14 -------------- tests/ui/structs-enums/export-tag-variant.rs | 8 -------- tests/ui/structs-enums/rec-auto.rs | 14 -------------- .../tag-variant-disr-type-mismatch.rs | 11 ----------- tests/ui/structs-enums/tuple-struct-trivial.rs | 7 ------- 5 files changed, 54 deletions(-) delete mode 100644 tests/ui/structs-enums/export-abstract-tag.rs delete mode 100644 tests/ui/structs-enums/export-tag-variant.rs delete mode 100644 tests/ui/structs-enums/rec-auto.rs delete mode 100644 tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs delete mode 100644 tests/ui/structs-enums/tuple-struct-trivial.rs diff --git a/tests/ui/structs-enums/export-abstract-tag.rs b/tests/ui/structs-enums/export-abstract-tag.rs deleted file mode 100644 index e6d359803856d..0000000000000 --- a/tests/ui/structs-enums/export-abstract-tag.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ run-pass -#![allow(non_camel_case_types)] - -// We can export tags without exporting the variants to create a simple -// sort of ADT. - - -mod foo { - pub enum t { t1, } - - pub fn f() -> t { return t::t1; } -} - -pub fn main() { let _v: foo::t = foo::f(); } diff --git a/tests/ui/structs-enums/export-tag-variant.rs b/tests/ui/structs-enums/export-tag-variant.rs deleted file mode 100644 index c6216d1b567b3..0000000000000 --- a/tests/ui/structs-enums/export-tag-variant.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ run-pass -#![allow(non_camel_case_types)] - -mod foo { - pub enum t { t1, } -} - -pub fn main() { let _v = foo::t::t1; } diff --git a/tests/ui/structs-enums/rec-auto.rs b/tests/ui/structs-enums/rec-auto.rs deleted file mode 100644 index bf2e37a189bc8..0000000000000 --- a/tests/ui/structs-enums/rec-auto.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ run-pass - - - - -// Issue #50. - -struct X { foo: String, bar: String } - -pub fn main() { - let x = X {foo: "hello".to_string(), bar: "world".to_string()}; - println!("{}", x.foo.clone()); - println!("{}", x.bar.clone()); -} diff --git a/tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs b/tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs deleted file mode 100644 index f4c202d91a7c1..0000000000000 --- a/tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - - -enum color { - red = 1, - blue = 2, -} - -pub fn main() {} diff --git a/tests/ui/structs-enums/tuple-struct-trivial.rs b/tests/ui/structs-enums/tuple-struct-trivial.rs deleted file mode 100644 index e2395036551e4..0000000000000 --- a/tests/ui/structs-enums/tuple-struct-trivial.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -#![allow(dead_code)] - -struct Foo(isize, isize, isize); - -pub fn main() { -} From 98a14412777fc337178fc4ee6d4b4bb7c9acd85d Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 20 Mar 2026 09:55:22 +0000 Subject: [PATCH 10/15] merge several `tuple-struct-*` tests --- tests/ui/structs-enums/tuple-struct-construct.rs | 9 --------- .../ui/structs-enums/tuple-struct-destructuring.rs | 13 +++++++++++++ tests/ui/structs-enums/tuple-struct-matching.rs | 13 ------------- 3 files changed, 13 insertions(+), 22 deletions(-) delete mode 100644 tests/ui/structs-enums/tuple-struct-construct.rs delete mode 100644 tests/ui/structs-enums/tuple-struct-matching.rs diff --git a/tests/ui/structs-enums/tuple-struct-construct.rs b/tests/ui/structs-enums/tuple-struct-construct.rs deleted file mode 100644 index 4243bccb4eb7a..0000000000000 --- a/tests/ui/structs-enums/tuple-struct-construct.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-pass -#[allow(dead_code)] -#[derive(Debug)] -struct Foo(isize, isize); - -pub fn main() { - let x = Foo(1, 2); - println!("{:?}", x); -} diff --git a/tests/ui/structs-enums/tuple-struct-destructuring.rs b/tests/ui/structs-enums/tuple-struct-destructuring.rs index 5213052dd7a40..36a36605ba80f 100644 --- a/tests/ui/structs-enums/tuple-struct-destructuring.rs +++ b/tests/ui/structs-enums/tuple-struct-destructuring.rs @@ -1,4 +1,5 @@ //@ run-pass +#[derive(Debug)] struct Foo(isize, isize); pub fn main() { @@ -7,4 +8,16 @@ pub fn main() { println!("{} {}", y, z); assert_eq!(y, 1); assert_eq!(z, 2); + + let x = Foo(1, 2); + match x { + Foo(a, b) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + println!("{} {}", a, b); + } + } + + let x = Foo(1, 2); + assert_eq!(format!("{x:?}"), "Foo(1, 2)"); } diff --git a/tests/ui/structs-enums/tuple-struct-matching.rs b/tests/ui/structs-enums/tuple-struct-matching.rs deleted file mode 100644 index a5436624c658a..0000000000000 --- a/tests/ui/structs-enums/tuple-struct-matching.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ run-pass -struct Foo(isize, isize); - -pub fn main() { - let x = Foo(1, 2); - match x { - Foo(a, b) => { - assert_eq!(a, 1); - assert_eq!(b, 2); - println!("{} {}", a, b); - } - } -} From ff524fdb979cdc916136ed4c98605218cb56cc82 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 20 Mar 2026 09:59:26 +0000 Subject: [PATCH 11/15] move many tests from `run-pass` to `check-pass` --- tests/ui/structs-enums/class-dtor.rs | 2 +- tests/ui/structs-enums/classes-self-referential.rs | 2 +- tests/ui/structs-enums/enum-discrim-range-overflow.rs | 2 +- tests/ui/structs-enums/foreign-struct.rs | 2 +- tests/ui/structs-enums/namespaced-enum-emulate-flat.rs | 2 +- tests/ui/structs-enums/namespaced-enum-glob-import.rs | 2 +- tests/ui/structs-enums/namespaced-enums.rs | 2 +- tests/ui/structs-enums/nested-enum-same-names.rs | 2 +- tests/ui/structs-enums/newtype-struct-with-dtor.rs | 2 +- tests/ui/structs-enums/simple-generic-tag.rs | 2 +- tests/ui/structs-enums/struct-variant-field-visibility.rs | 2 +- tests/ui/structs-enums/tag-in-block.rs | 2 +- tests/ui/structs-enums/uninstantiable-struct.rs | 2 +- tests/ui/structs-enums/variant-structs-trivial.rs | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/ui/structs-enums/class-dtor.rs b/tests/ui/structs-enums/class-dtor.rs index a08f0f0b0a47f..b7911823ef1b9 100644 --- a/tests/ui/structs-enums/class-dtor.rs +++ b/tests/ui/structs-enums/class-dtor.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] #![allow(non_camel_case_types)] diff --git a/tests/ui/structs-enums/classes-self-referential.rs b/tests/ui/structs-enums/classes-self-referential.rs index f819e558aa2ee..40c51a1573cd5 100644 --- a/tests/ui/structs-enums/classes-self-referential.rs +++ b/tests/ui/structs-enums/classes-self-referential.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] #![allow(non_camel_case_types)] diff --git a/tests/ui/structs-enums/enum-discrim-range-overflow.rs b/tests/ui/structs-enums/enum-discrim-range-overflow.rs index 91be8014ebdaa..641e5566bee3d 100644 --- a/tests/ui/structs-enums/enum-discrim-range-overflow.rs +++ b/tests/ui/structs-enums/enum-discrim-range-overflow.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(overflowing_literals)] diff --git a/tests/ui/structs-enums/foreign-struct.rs b/tests/ui/structs-enums/foreign-struct.rs index f339c191ae806..b710d83350abf 100644 --- a/tests/ui/structs-enums/foreign-struct.rs +++ b/tests/ui/structs-enums/foreign-struct.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] #![allow(non_camel_case_types)] diff --git a/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs b/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs index 774cfa1a38089..2bc23d94b4d92 100644 --- a/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs +++ b/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] pub use Foo::*; diff --git a/tests/ui/structs-enums/namespaced-enum-glob-import.rs b/tests/ui/structs-enums/namespaced-enum-glob-import.rs index 82742a934c413..52bfa9d4ab723 100644 --- a/tests/ui/structs-enums/namespaced-enum-glob-import.rs +++ b/tests/ui/structs-enums/namespaced-enum-glob-import.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] mod m2 { diff --git a/tests/ui/structs-enums/namespaced-enums.rs b/tests/ui/structs-enums/namespaced-enums.rs index 3e2e0b5ffa8fd..f3f1a3bd44e50 100644 --- a/tests/ui/structs-enums/namespaced-enums.rs +++ b/tests/ui/structs-enums/namespaced-enums.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] enum Foo { diff --git a/tests/ui/structs-enums/nested-enum-same-names.rs b/tests/ui/structs-enums/nested-enum-same-names.rs index 5ff730aff4415..1d3fab4e722c3 100644 --- a/tests/ui/structs-enums/nested-enum-same-names.rs +++ b/tests/ui/structs-enums/nested-enum-same-names.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] /* diff --git a/tests/ui/structs-enums/newtype-struct-with-dtor.rs b/tests/ui/structs-enums/newtype-struct-with-dtor.rs index 35476c5ed2d6b..c0d04932c4642 100644 --- a/tests/ui/structs-enums/newtype-struct-with-dtor.rs +++ b/tests/ui/structs-enums/newtype-struct-with-dtor.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(unused_unsafe)] #![allow(unused_variables)] diff --git a/tests/ui/structs-enums/simple-generic-tag.rs b/tests/ui/structs-enums/simple-generic-tag.rs index b78505edd1f2b..dbb5d707b52f5 100644 --- a/tests/ui/structs-enums/simple-generic-tag.rs +++ b/tests/ui/structs-enums/simple-generic-tag.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] #![allow(non_camel_case_types)] diff --git a/tests/ui/structs-enums/struct-variant-field-visibility.rs b/tests/ui/structs-enums/struct-variant-field-visibility.rs index a6528f9a2b17e..40acea956aeab 100644 --- a/tests/ui/structs-enums/struct-variant-field-visibility.rs +++ b/tests/ui/structs-enums/struct-variant-field-visibility.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] mod foo { diff --git a/tests/ui/structs-enums/tag-in-block.rs b/tests/ui/structs-enums/tag-in-block.rs index 27b48aae51f60..75691f02dd824 100644 --- a/tests/ui/structs-enums/tag-in-block.rs +++ b/tests/ui/structs-enums/tag-in-block.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] #![allow(non_camel_case_types)] diff --git a/tests/ui/structs-enums/uninstantiable-struct.rs b/tests/ui/structs-enums/uninstantiable-struct.rs index 97bc7d8414e7f..def0fa00e17c2 100644 --- a/tests/ui/structs-enums/uninstantiable-struct.rs +++ b/tests/ui/structs-enums/uninstantiable-struct.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass pub struct Z(#[allow(dead_code)] &'static Z); pub fn main() {} diff --git a/tests/ui/structs-enums/variant-structs-trivial.rs b/tests/ui/structs-enums/variant-structs-trivial.rs index a7b0575118437..c1403b79c8aab 100644 --- a/tests/ui/structs-enums/variant-structs-trivial.rs +++ b/tests/ui/structs-enums/variant-structs-trivial.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] enum Foo { From 5f680443579ae914c005cc40485a1c029cbe4cdc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 23 Mar 2026 18:37:52 +0100 Subject: [PATCH 12/15] miri recursive checking: only check one layer deep --- .../rustc_const_eval/src/interpret/validity.rs | 14 +++++++++++--- src/tools/miri/README.md | 5 +++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 62ee653000dca..9310cda8450b6 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1512,6 +1512,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, } impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { + /// The internal core entry point for all validation operations. fn validate_operand_internal( &mut self, val: &PlaceTy<'tcx, M::Provenance>, @@ -1519,6 +1520,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ref_tracking: Option<&mut RefTracking, Vec>>, ctfe_mode: Option, reset_provenance_and_padding: bool, + start_in_may_dangle: bool, ) -> InterpResult<'tcx> { trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty); @@ -1536,7 +1538,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ecx, reset_provenance_and_padding, data_bytes: reset_padding.then_some(RangeSet(Vec::new())), - may_dangle: false, + may_dangle: start_in_may_dangle, }; v.visit_value(val)?; v.reset_padding(val)?; @@ -1579,6 +1581,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Some(ref_tracking), Some(ctfe_mode), /*reset_provenance*/ false, + /*start_in_may_dangle*/ false, ) } @@ -1610,6 +1613,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { None, None, reset_provenance_and_padding, + /*start_in_may_dangle*/ false, ); } // Do a recursive check. @@ -1620,15 +1624,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Some(&mut ref_tracking), None, reset_provenance_and_padding, + /*start_in_may_dangle*/ false, )?; while let Some((mplace, path)) = ref_tracking.todo.pop() { - // Things behind reference do *not* have the provenance reset. + // Things behind reference do *not* have the provenance reset. In fact + // we treat the entire thing as being inside MaybeDangling, i.e., references + // do not have to be dereferenceable. self.validate_operand_internal( &mplace.into(), path, - Some(&mut ref_tracking), + None, // no further recursion None, /*reset_provenance_and_padding*/ false, + /*start_in_may_dangle*/ true, )?; } interp_ok(()) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 97f385ad755bc..f51cd96486b4f 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -476,8 +476,9 @@ to Miri failing to detect cases of undefined behavior in a program. but reports to the program that it did actually write. This is useful when you are not interested in the actual program's output, but only want to see Miri's errors and warnings. -* `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking - recurse below references. +* `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking recurse + *one level* below references. The in-memory value is treated as-if it was inside a + `MaybeDangling`, i.e., nested references do not even have to be dereferenceable. * `-Zmiri-preemption-rate` configures the probability that at the end of a basic block, the active thread will be preempted. The default is `0.01` (i.e., 1%). Setting this to `0` disables preemption. Note that even without preemption, the schedule is still non-deterministic: From 422906d57e99eaf8a27c0aa2696cac3286c2594f Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 24 Mar 2026 17:39:46 +0000 Subject: [PATCH 13/15] Do not check for LEAK & KERNELHWADDRESS because they are incompatible --- compiler/rustc_codegen_ssa/src/back/link.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index be7da2e81add8..7a3d5a6bb2248 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1341,7 +1341,6 @@ fn add_sanitizer_libraries( if sanitizer.contains(SanitizerSet::LEAK) && !sanitizer.contains(SanitizerSet::ADDRESS) && !sanitizer.contains(SanitizerSet::HWADDRESS) - && !sanitizer.contains(SanitizerSet::KERNELHWADDRESS) { link_sanitizer_runtime(sess, flavor, linker, "lsan"); } From 4d86840bf153fa62e92db3065e7b02b117823a52 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 24 Mar 2026 17:46:20 +0000 Subject: [PATCH 14/15] Document kernel-hwaddress in Unstable Book --- .../unstable-book/src/compiler-flags/sanitizer.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 1771d1382f073..eb070c22dc288 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -22,6 +22,8 @@ This feature allows for use of one of following sanitizers: * [AddressSanitizer](#addresssanitizer) a fast memory error detector. * [HWAddressSanitizer](#hwaddresssanitizer) a memory error detector similar to AddressSanitizer, but based on partial hardware assistance. + * [KernelHWAddressSanitizer](#kernelhwaddresssanitizer) variant of + HWAddressSanitizer that is designed for bare metal environments. * [LeakSanitizer](#leaksanitizer) a run-time memory leak detector. * [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads. * [RealtimeSanitizer](#realtimesanitizer) a detector of calls to function with @@ -622,6 +624,16 @@ Registers where the failure occurred (pc 0xaaaae0ae4a98): SUMMARY: HWAddressSanitizer: tag-mismatch (/.../main+0x54a94) ``` +# KernelHWAddressSanitizer + +KernelHWAddressSanitizer is the kernel version of [HWAddressSanitizer](#hwaddresssanitizer), +which achieves the same purpose but is designed for bare-metal environments. + +HWAddressSanitizer is supported on the `aarch64*-unknown-none` and +`aarch64*-unknown-none-softfloat` targets. + +See the [Clang HWAddressSanitizer documentation][clang-hwasan] for more details. + # KernelControlFlowIntegrity The LLVM Kernel Control Flow Integrity (CFI) support to the Rust compiler From 62ba3c1022f2070125f070dadeb6d6dae694b3a0 Mon Sep 17 00:00:00 2001 From: kyleecodes Date: Wed, 25 Mar 2026 00:35:04 +0000 Subject: [PATCH 15/15] Move ui/issues tests to relevant subdirectories * tests(ui): migrate issues/issue-17546 to ui/resolve * tests(ui): add gh issue link * tests(ui/issues): move tests to variants dir --- .../variant-result-noresult-used-as-type.rs} | 1 + .../variant-result-noresult-used-as-type.stderr} | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) rename tests/ui/{issues/issue-17546.rs => variants/variant-result-noresult-used-as-type.rs} (94%) rename tests/ui/{issues/issue-17546.stderr => variants/variant-result-noresult-used-as-type.stderr} (89%) diff --git a/tests/ui/issues/issue-17546.rs b/tests/ui/variants/variant-result-noresult-used-as-type.rs similarity index 94% rename from tests/ui/issues/issue-17546.rs rename to tests/ui/variants/variant-result-noresult-used-as-type.rs index 1f0afc368a2eb..14433c1460ebb 100644 --- a/tests/ui/issues/issue-17546.rs +++ b/tests/ui/variants/variant-result-noresult-used-as-type.rs @@ -1,5 +1,6 @@ //@ edition:2015 //@ ignore-sgx std::os::fortanix_sgx::usercalls::raw::Result changes compiler suggestions +// https://github.com/rust-lang/rust/issues/17546 use foo::MyEnum::Result; use foo::NoResult; // Through a re-export diff --git a/tests/ui/issues/issue-17546.stderr b/tests/ui/variants/variant-result-noresult-used-as-type.stderr similarity index 89% rename from tests/ui/issues/issue-17546.stderr rename to tests/ui/variants/variant-result-noresult-used-as-type.stderr index d4aa354491fe1..511cb3562f947 100644 --- a/tests/ui/issues/issue-17546.stderr +++ b/tests/ui/variants/variant-result-noresult-used-as-type.stderr @@ -1,5 +1,5 @@ error[E0573]: expected type, found variant `NoResult` - --> $DIR/issue-17546.rs:15:17 + --> $DIR/variant-result-noresult-used-as-type.rs:16:17 | LL | fn new() -> NoResult { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL + fn new() -> Result { | error[E0573]: expected type, found variant `Result` - --> $DIR/issue-17546.rs:25:17 + --> $DIR/variant-result-noresult-used-as-type.rs:26:17 | LL | fn new() -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type @@ -36,7 +36,7 @@ LL + use std::thread::Result; | error[E0573]: expected type, found variant `Result` - --> $DIR/issue-17546.rs:31:13 + --> $DIR/variant-result-noresult-used-as-type.rs:32:13 | LL | fn new() -> Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type @@ -53,7 +53,7 @@ LL + use std::thread::Result; | error[E0573]: expected type, found variant `NoResult` - --> $DIR/issue-17546.rs:36:15 + --> $DIR/variant-result-noresult-used-as-type.rs:37:15 | LL | fn newer() -> NoResult { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^