Stabilize `asm_cfg`
tracking issue: https://github.com/rust-lang/rust/issues/140364
closes https://github.com/rust-lang/rust/issues/140364
Reference PR:
- https://github.com/rust-lang/reference/pull/2063
# Request for Stabilization
## Summary
The `cfg_asm` feature allows `#[cfg(...)]` and `#[cfg_attr(...)]` on the arguments of the assembly macros, for instance:
```rust
asm!( // or global_asm! or naked_asm!
"nop",
#[cfg(target_feature = "sse2")]
"nop",
// ...
#[cfg(target_feature = "sse2")]
a = const 123, // only used on sse2
);
```
## Semantics
Templates, operands, `options` and `clobber_abi` in the assembly macros (`asm!`, `naked_asm!` and `global_asm!`) can be annotated with `#[cfg(...)]` and `#[cfg_attr(...)]`. When the condition evaluates to true, the annotated argument has no effect, and is completely ignored when expanding the assembly macro.
## Documentation
reference PR: https://github.com/rust-lang/reference/pull/2063
## Tests
- [tests/ui/asm/cfg.rs](https://github.com/rust-lang/rust/blob/master/tests/ui/asm/cfg.rs) checks that `cfg`'d arguments where the condition evaluates to false have no effect
- [tests/ui/asm/cfg-parse-error.rs](https://github.com/rust-lang/rust/blob/master/tests/ui/asm/cfg.rs) checks the parsing rules (parsing effectively assumes that the cfg conditions are all true)
## History
- https://github.com/rust-lang/rust/issues/140279
- https://github.com/rust-lang/rust/pull/140367
# Resolved questions
**how are other attributes handled**
Other attributes are parsed, but explicitly rejected.
# unresolved questions
**operand before template**
The current implementation expects at least one template string before any operands. In the example below, if the `cfg` condition evaluates to true, the assembly block is ill-formed. But even when it evaluates to `false` this block is rejected, because the parser still expects just a template (a template is parsed as an expression and then validated to ensure that it is or expands to a string literal).
Changing how this works is difficult.
```rust
// This is rejected because `a = out(reg) x` does not parse as an expresion.
asm!(
#[cfg(false)]
a = out(reg) x, //~ ERROR expected token: `,`
"",
);
```
**lint on positional arguments?**
Adding a lint to warn on the definition or use of positional arguments being `cfg`'d out was discussed in https://github.com/rust-lang/rust/issues/140279#issuecomment-2832237372 and subsequent comments. Such a lint is not currently implemented, but that may not be a blocker based on the comments there.
r? `@traviscross` (I'm assuming you'll reassign as needed)
Provide additional context to errors involving const traits
When encountering an unmet `Ty: [const] Trait` bound, if `Trait` is `#[const_trait]` and there's an `impl Trait for Ty` point at it. If local, suggest `impl const Trait for Ty`, otherwise just point at it.
```
error[E0277]: the trait bound `NonConstAdd: [const] Add` is not satisfied
--> $DIR/assoc-type.rs:37:16
|
LL | type Bar = NonConstAdd;
| ^^^^^^^^^^^
|
note: required by a bound in `Foo::Bar`
--> $DIR/assoc-type.rs:33:15
|
LL | type Bar: [const] Add;
| ^^^^^^^^^^^ required by this bound in `Foo::Bar`
help: make the `impl` of trait `Add` `const`
|
LL | impl const Add for NonConstAdd {
| +++++
```
```
error[E0277]: the trait bound `T: [const] PartialEq` is not satisfied
--> tests/ui/traits/const-traits/call-generic-method-fail.rs:5:5
|
5 | *t == *t
| ^^^^^^^^
|
note: trait `PartialEq` is implemented but not `const`
--> /home/gh-estebank/rust/library/core/src/ptr/const_ptr.rs:1590:1
|
1590 | impl<T: PointeeSized> PartialEq for *const T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: trait `PartialEq` is implemented but not `const`
--> /home/gh-estebank/rust/library/core/src/ptr/mut_ptr.rs:2011:1
|
2011 | impl<T: PointeeSized> PartialEq for *mut T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
Point at trait and associated item when that associated item is used in a const context. Suggest making the trait `#[const_trait]`.
```
error[E0015]: cannot call non-const method `<() as Trait>::foo` in constant functions
--> $DIR/inline-incorrect-early-bound-in-ctfe.rs:26:8
|
LL | ().foo();
| ^^^^^
|
note: method `foo` is not const because trait `Trait` is not const
--> $DIR/inline-incorrect-early-bound-in-ctfe.rs:13:1
|
LL | trait Trait {
| ^^^^^^^^^^^ this trait is not const
LL | fn foo(self);
| ------------- this method is not const
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider making trait `Trait` const
|
LL + #[const_trait]
LL | trait Trait {
|
```
The `needs-asm-support` directive checks whether the host architecture
supports inline assembly, not the target architecture. For tests that
explicitly specify a target via `--target` in their compile-flags, this
directive is incorrect and unnecessary.
These tests are cross-compiling to specific targets (like x86_64, arm,
aarch64, riscv, etc.) that are already known to have stable asm support.
The directive was causing these tests to be incorrectly skipped on hosts
that don't support asm, even though the target does.
Tests with explicit targets should rely on `needs-llvm-components` to
ensure the appropriate backend is available, rather than checking host
asm support.
Improve documentation about `needs-asm-support` directive.
Where supported, VSX is a 64x128b register set which encompasses
both the floating point and vector registers.
In the type tests, xvsqrtdp is used as it is the only two-argument
vsx opcode supported by all targets on llvm. If you need to copy
a vsx register, the preferred way is "xxlor xt, xa, xa".
Sanitizers target modificators
Depends on bool flag fix: https://github.com/rust-lang/rust/pull/138483.
Some sanitizers need to be target modifiers, and some do not. For now, we should mark all sanitizers as target modifiers except for these: AddressSanitizer, LeakSanitizer
For kCFI, the helper flag -Zsanitizer-cfi-normalize-integers should also be a target modifier.
Many test errors was with sanizer flags inconsistent with std deps. Tests are fixed with `-C unsafe-allow-abi-mismatch`.
If the baseline s390x cpu is changed to a newer variant, such as z13,
the vector feature may be enabled by default. When rust is packaged
on fedora 38 and newer, it is set to z13.
Explicitly disable vector support on the baseline test for consistent
results across s390x cpus.
Use `splice` to avoid shifting the other items twice.
Put `extern crate std;` first so it's already resolved when we resolve `::std::prelude::rust_20XX`.
From `#[align]` -> `#[rustc_align]`. Attributes starting with `rustc`
are always perma-unstable and feature-gated by `feature(rustc_attrs)`.
See regression RUST-143834.
For the underlying problem where even introducing new feature-gated
unstable built-in attributes can break user code such as
```rs
macro_rules! align {
() => {
/* .. */
};
}
pub(crate) use align; // `use` here becomes ambiguous
```
refer to RUST-134963.
Since the `#[align]` attribute is still feature-gated by
`feature(fn_align)`, we can rename it as a mitigation. Note that
`#[rustc_align]` will obviously mean that current unstable user code
using `feature(fn_aling)` will need additionally `feature(rustc_attrs)`,
but this is a short-term mitigation to buy time, and is expected to be
changed to a better name with less collision potential.
See
<https://rust-lang.zulipchat.com/#narrow/channel/238009-t-compiler.2Fmeetings/topic/.5Bweekly.5D.202025-07-17/near/529290371>
where mitigation options were considered.
fix `-Zsanitizer=kcfi` on `#[naked]` functions
fixes https://github.com/rust-lang/rust/issues/143266
With `-Zsanitizer=kcfi`, indirect calls happen via generated intermediate shim that forwards the call. The generated shim preserves the attributes of the original, including `#[unsafe(naked)]`. The shim is not a naked function though, and violates its invariants (like having a body that consists of a single `naked_asm!` call).
My fix here is to match on the `InstanceKind`, and only use `codegen_naked_asm` when the instance is not a `ReifyShim`. That does beg the question whether there are other `InstanceKind`s that could come up. As far as I can tell the answer is no: calling via `dyn` seems to work find, and `#[track_caller]` is disallowed in combination with `#[naked]`.
r? codegen
````@rustbot```` label +A-naked
cc ````@maurer```` ````@rcvalle````
There are many places that join path segments with `::` to produce a
string. A lot of these use `join("::")`. Many in rustdoc use
`join_with_double_colon`, and a few use `.joined("..")`. One in Clippy
uses `itertools::join`. A couple of them look for `kw::PathRoot` in the
first segment, which can be important.
This commit introduces `rustc_ast::join_path_{syms,ident}` to do the
joining for everyone. `rustc_ast` is as good a location for these as
any, being the earliest-running of the several crates with a `Path`
type. Two functions are needed because `Ident` printing is more complex
than simple `Symbol` printing.
The commit also removes `join_with_double_colon`, and
`estimate_item_path_byte_length` with it.
There are still a handful of places that join strings with "::" that are
unchanged. They are not that important: some of them are in tests, and
some of them first split a path around "::" and then rejoin with "::".
This fixes one test case where `{{root}}` shows up in an error message.