From d9d743eefc22ad5bf26168d435bf0f8a3804413d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 28 Oct 2026 12:10:36 +0100 Subject: [PATCH 1/3] add test showing the problem as shown in issue 165055, an unstable use of the `z` modifier should be rejected. That would make this test fail, but it doesn't yet. --- .../feature-gate-asm_experimental_reg.loongarch.stderr | 8 ++++---- .../ui/feature-gates/feature-gate-asm_experimental_reg.rs | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr index 0f829dd65cb47..80ecc34905df6 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr @@ -1,5 +1,5 @@ error[E0658]: register class `vreg` can only be used as a clobber in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:60:41 + --> $DIR/feature-gate-asm_experimental_reg.rs:67:41 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: register class `vreg` can only be used as a clobber in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:60:54 + --> $DIR/feature-gate-asm_experimental_reg.rs:67:54 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `i8x16` cannot be used with this register class in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:60:51 + --> $DIR/feature-gate-asm_experimental_reg.rs:67:51 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^ @@ -29,7 +29,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `i8x16` cannot be used with this register class in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:60:63 + --> $DIR/feature-gate-asm_experimental_reg.rs:67:63 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^ diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs index c91036366a028..80454762b3058 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs @@ -47,6 +47,13 @@ unsafe fn predicate(p: svbool_t) { //[aarch64]~| ERROR type `svbool_t` cannot be used with this register class in stable } +#[cfg(aarch64)] +unsafe fn modifier(x: f64) -> f64 { + let y: f64; + unsafe { asm!("mov {1:z}.d, {0:z}.d", in(vreg) x, out(vreg) y) }; + y +} + #[cfg(loongarch)] #[repr(simd)] pub struct i8x16([i8; 16]); From 6dc606cded012dc13102a4c1e4a9ff18a11b0f8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 28 Oct 2026 12:37:18 +0100 Subject: [PATCH 2/3] ensure the `z` asm template modifier is gated under `asm_experimental_reg` This also correctly rejects the previous test. The other tests relying on the modifier are changed to enable the feature. --- compiler/rustc_ast_lowering/src/asm.rs | 3 ++- compiler/rustc_target/src/asm/aarch64.rs | 15 ++++++++++++-- compiler/rustc_target/src/asm/mod.rs | 14 +++++++++---- tests/assembly-llvm/asm/aarch64-modifiers.rs | 2 +- tests/ui/asm/aarch64/bad-reg.stderr | 4 ++-- ...e-gate-asm_experimental_reg.aarch64.stderr | 20 ++++++++++++++++++- ...gate-asm_experimental_reg.loongarch.stderr | 8 ++++---- .../feature-gate-asm_experimental_reg.rs | 2 ++ 8 files changed, 53 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 71bcdb0e27e8f..e7534c058c7f0 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -261,7 +261,8 @@ impl<'hir> LoweringContext<'_, 'hir> { if class == asm::InlineAsmRegClass::Err { continue; } - let valid_modifiers = class.valid_modifiers(asm_arch.unwrap()); + let valid_modifiers = + class.valid_modifiers(asm_arch.unwrap(), allow_experimental_reg); if !valid_modifiers.contains(&modifier) { let sub = if valid_modifiers.is_empty() { InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier { diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 83d249262c104..4136d1a624588 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -18,10 +18,21 @@ def_reg_class! { } impl AArch64InlineAsmRegClass { - pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { + pub fn valid_modifiers( + self, + _arch: super::InlineAsmArch, + allow_experimental_reg: bool, + ) -> &'static [char] { match self { Self::reg => &['w', 'x'], - Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v', 'z'], + Self::vreg | Self::vreg_low16 => { + if allow_experimental_reg { + &['b', 'h', 's', 'd', 'q', 'v', 'z'] + } else { + &['b', 'h', 's', 'd', 'q', 'v'] + } + } + Self::preg | Self::ffr => &[], } } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 6f9751e807490..500010dc426f4 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -711,13 +711,19 @@ impl InlineAsmRegClass { }) } - /// Returns the list of template modifiers that can be used with this - /// register class. - pub fn valid_modifiers(self, arch: InlineAsmArch) -> &'static [char] { + /// Returns the list of template modifiers that can be used with this register class, as well as + /// whether the `asm_experimental_reg` feature is enabled: there can be template modifiers that + /// apply to currently unstable registers, and we don't want to make these modifiers usable + /// without the feature gate. + pub fn valid_modifiers( + self, + arch: InlineAsmArch, + allow_experimental_reg: bool, + ) -> &'static [char] { match self { Self::X86(r) => r.valid_modifiers(arch), Self::Arm(r) => r.valid_modifiers(arch), - Self::AArch64(r) => r.valid_modifiers(arch), + Self::AArch64(r) => r.valid_modifiers(arch, allow_experimental_reg), Self::Amdgpu(r) => r.valid_modifiers(arch), Self::RiscV(r) => r.valid_modifiers(arch), Self::Nvptx(r) => r.valid_modifiers(arch), diff --git a/tests/assembly-llvm/asm/aarch64-modifiers.rs b/tests/assembly-llvm/asm/aarch64-modifiers.rs index 66be35de574f6..5c68c25a7b902 100644 --- a/tests/assembly-llvm/asm/aarch64-modifiers.rs +++ b/tests/assembly-llvm/asm/aarch64-modifiers.rs @@ -5,7 +5,7 @@ //@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: aarch64 -#![feature(no_core)] +#![feature(asm_experimental_reg, no_core)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register)] diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr index 8937509763dec..14ffdb3e0059f 100644 --- a/tests/ui/asm/aarch64/bad-reg.stderr +++ b/tests/ui/asm/aarch64/bad-reg.stderr @@ -30,7 +30,7 @@ LL | asm!("{:r}", in(vreg) foo); | | | template modifier | - = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`, and `z` + = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` error: invalid asm template modifier `r` for this register class --> $DIR/bad-reg.rs:26:15 @@ -40,7 +40,7 @@ LL | asm!("{:r}", in(vreg_low16) foo); | | | template modifier | - = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`, and `z` + = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` error: asm template modifiers are not allowed for `const` arguments --> $DIR/bad-reg.rs:28:15 diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr index f19cb17a04a29..8c26351a9ea89 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr @@ -8,6 +8,24 @@ LL | asm!("/* {0} */", in(preg) p); = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error: invalid asm template modifier `z` for this register class + --> $DIR/feature-gate-asm_experimental_reg.rs:53:24 + | +LL | unsafe { asm!("mov {1:z}.d, {0:z}.d", in(vreg) x, out(vreg) y) }; + | ^^^^^ template modifier ----------- argument + | + = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` + +error: invalid asm template modifier `z` for this register class + --> $DIR/feature-gate-asm_experimental_reg.rs:53:33 + | +LL | unsafe { asm!("mov {1:z}.d, {0:z}.d", in(vreg) x, out(vreg) y) }; + | ^^^^^ ---------- argument + | | + | template modifier + | + = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` + error[E0658]: type `svint32_t` cannot be used with this register class in stable --> $DIR/feature-gate-asm_experimental_reg.rs:33:32 | @@ -48,6 +66,6 @@ LL | asm!("/* {0} */", in(preg) p); = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr index 80ecc34905df6..0eee8e9af60af 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.loongarch.stderr @@ -1,5 +1,5 @@ error[E0658]: register class `vreg` can only be used as a clobber in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:67:41 + --> $DIR/feature-gate-asm_experimental_reg.rs:69:41 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: register class `vreg` can only be used as a clobber in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:67:54 + --> $DIR/feature-gate-asm_experimental_reg.rs:69:54 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `i8x16` cannot be used with this register class in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:67:51 + --> $DIR/feature-gate-asm_experimental_reg.rs:69:51 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^ @@ -29,7 +29,7 @@ LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `i8x16` cannot be used with this register class in stable - --> $DIR/feature-gate-asm_experimental_reg.rs:67:63 + --> $DIR/feature-gate-asm_experimental_reg.rs:69:63 | LL | asm!("xvadd.h {1:u}, {0:u}, {0:u}", out(vreg) y, in(vreg) x); | ^ diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs index 80454762b3058..f6c03e246dc46 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.rs @@ -51,6 +51,8 @@ unsafe fn predicate(p: svbool_t) { unsafe fn modifier(x: f64) -> f64 { let y: f64; unsafe { asm!("mov {1:z}.d, {0:z}.d", in(vreg) x, out(vreg) y) }; + //[aarch64]~^ ERROR invalid asm template modifier `z` for this register class + //[aarch64]~| ERROR invalid asm template modifier `z` for this register class y } From fd05e392b029aa87705c26cfe671569a19b73b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 28 Oct 2026 15:06:20 +0100 Subject: [PATCH 3/3] introduce unstable template modifier diagnostic variant This improves the error when using the `z` template modifier on stable, pointing towards the expected feature gate to enable it. --- compiler/rustc_ast_lowering/src/asm.rs | 50 +++++++++++++------ .../rustc_ast_lowering/src/diagnostics.rs | 12 +++++ ...e-gate-asm_experimental_reg.aarch64.stderr | 16 ++++-- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index e7534c058c7f0..92b3f77ce4a56 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -264,22 +264,42 @@ impl<'hir> LoweringContext<'_, 'hir> { let valid_modifiers = class.valid_modifiers(asm_arch.unwrap(), allow_experimental_reg); if !valid_modifiers.contains(&modifier) { - let sub = if valid_modifiers.is_empty() { - InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier { - class_name: class.name(), - } + // First check if the requested modifier is missing from the valid + // values because experimental registers are disabled. + let unstable_modifiers = class.valid_modifiers(asm_arch.unwrap(), true); + if !allow_experimental_reg && unstable_modifiers.contains(&modifier) { + self.tcx.sess.create_feature_err( + InvalidAsmTemplateModifierRegClass { + placeholder_span, + op_span: op_sp, + modifier: modifier.to_string(), + sub: InvalidAsmTemplateModifierRegClassSub::ModifierIsGated { + class_name: class.name(), + feature: sym::asm_experimental_reg, + stable_modifiers: valid_modifiers.to_vec().into(), + all_modifiers: unstable_modifiers.to_vec().into(), + }, + }, + sym::asm_experimental_reg, + ).emit(); } else { - InvalidAsmTemplateModifierRegClassSub::SupportModifier { - class_name: class.name(), - modifiers: valid_modifiers.to_vec().into(), - } - }; - self.dcx().emit_err(InvalidAsmTemplateModifierRegClass { - placeholder_span, - op_span: op_sp, - modifier: modifier.to_string(), - sub, - }); + let sub = if valid_modifiers.is_empty() { + InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier { + class_name: class.name(), + } + } else { + InvalidAsmTemplateModifierRegClassSub::SupportModifier { + class_name: class.name(), + modifiers: valid_modifiers.to_vec().into(), + } + }; + self.dcx().emit_err(InvalidAsmTemplateModifierRegClass { + placeholder_span, + op_span: op_sp, + modifier: modifier.to_string(), + sub, + }); + } } } hir::InlineAsmOperand::Const { .. } => { diff --git a/compiler/rustc_ast_lowering/src/diagnostics.rs b/compiler/rustc_ast_lowering/src/diagnostics.rs index 8c298c57040e9..35a787f62858b 100644 --- a/compiler/rustc_ast_lowering/src/diagnostics.rs +++ b/compiler/rustc_ast_lowering/src/diagnostics.rs @@ -266,6 +266,18 @@ pub(crate) enum InvalidAsmTemplateModifierRegClassSub { SupportModifier { class_name: Symbol, modifiers: DiagSymbolList }, #[note("the `{$class_name}` register class does not support template modifiers")] DoesNotSupportModifier { class_name: Symbol }, + + /// Enabling a feature is needed to use the requested modifier. + #[note( + "the `{$class_name}` register class only supports the following template modifiers on stable: {$stable_modifiers}" + )] + #[note("enabling the `{$feature}` feature will allow using: {$all_modifiers}")] + ModifierIsGated { + class_name: Symbol, + feature: Symbol, + stable_modifiers: DiagSymbolList, + all_modifiers: DiagSymbolList, + }, } #[derive(Diagnostic)] diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr index 8c26351a9ea89..e1ac256ab7a79 100644 --- a/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_reg.aarch64.stderr @@ -8,15 +8,19 @@ LL | asm!("/* {0} */", in(preg) p); = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: invalid asm template modifier `z` for this register class +error[E0658]: invalid asm template modifier `z` for this register class --> $DIR/feature-gate-asm_experimental_reg.rs:53:24 | LL | unsafe { asm!("mov {1:z}.d, {0:z}.d", in(vreg) x, out(vreg) y) }; | ^^^^^ template modifier ----------- argument | - = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` + = note: the `vreg` register class only supports the following template modifiers on stable: `b`, `h`, `s`, `d`, `q`, and `v` + = note: enabling the `asm_experimental_reg` feature will allow using: `b`, `h`, `s`, `d`, `q`, `v`, and `z` + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: invalid asm template modifier `z` for this register class +error[E0658]: invalid asm template modifier `z` for this register class --> $DIR/feature-gate-asm_experimental_reg.rs:53:33 | LL | unsafe { asm!("mov {1:z}.d, {0:z}.d", in(vreg) x, out(vreg) y) }; @@ -24,7 +28,11 @@ LL | unsafe { asm!("mov {1:z}.d, {0:z}.d", in(vreg) x, out(vreg) y) }; | | | template modifier | - = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v` + = note: the `vreg` register class only supports the following template modifiers on stable: `b`, `h`, `s`, `d`, `q`, and `v` + = note: enabling the `asm_experimental_reg` feature will allow using: `b`, `h`, `s`, `d`, `q`, `v`, and `z` + = note: see issue #133416 for more information + = help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: type `svint32_t` cannot be used with this register class in stable --> $DIR/feature-gate-asm_experimental_reg.rs:33:32