Fix, document, and test parser and pretty-printer edge cases related to braced macro calls
_Review note: this is a deceptively small PR because it comes with 145 lines of docs and 196 lines of tests, and only 25 lines of compiler code changed. However, I recommend reviewing it 1 commit at a time because much of the effect of the code changes is non-local i.e. affecting code that is not visible in the final state of the PR. I have paid attention that reviewing the PR one commit at a time is as easy as I can make it. All of the code you need to know about is touched in those commits, even if some of those changes disappear by the end of the stack._
This is a follow-up to https://github.com/rust-lang/rust/pull/119105. One case that is not relevant to `-Zunpretty=expanded`, but which came up as I'm porting #119105 and #118726 into `syn`'s printer and `prettyplease`'s printer where it **is** relevant, and is also relevant to rustc's `stringify!`, is statement boundaries in the vicinity of braced macro calls.
Rustc's AST pretty-printer produces invalid syntax for statements that begin with a braced macro call:
```rust
macro_rules! stringify_item {
($i:item) => {
stringify!($i)
};
}
macro_rules! repro {
($e:expr) => {
stringify_item!(fn main() { $e + 1; })
};
}
fn main() {
println!("{}", repro!(m! {}));
}
```
**Before this PR:** output is not valid Rust syntax.
```console
fn main() { m! {} + 1; }
```
```console
error: leading `+` is not supported
--> <anon>:1:19
|
1 | fn main() { m! {} + 1; }
| ^ unexpected `+`
|
help: try removing the `+`
|
1 - fn main() { m! {} + 1; }
1 + fn main() { m! {} 1; }
|
```
**After this PR:** valid syntax.
```console
fn main() { (m! {}) + 1; }
```
The change to the test is a little goofy because the compiler was
guessing "correctly" before that `falsy! {}` is the condition as opposed
to the else body. But I believe this change is fundamentally correct.
Braced macro invocations in statement position are most often item-like
(`thread_local! {...}`) as opposed to parenthesized macro invocations
which are condition-like (`cfg!(...)`).
Always hide private fields in aliased type
This PR adds a new rustdoc pass that unconditionally always strips all private fields in aliased type, since showing them, even with `--document-private-items`, is confusing, unhelpful, and run backwards to the "Aliased type" feature, which is to show the type as it would be seen by the user.
r? ```@GuillaumeGomez```
Fixes#124938Fixes#123860
Clean up users of rust_dbg_call
`rust_dbg_call` is a C test helper that until this PR was declared in C with `void*` arguments and used in Rust _mostly_ with `libc::uintptr_t` arguments. Nearly every user just wants to pass integers around, so I've changed all users to `uint64_t` or `u64`.
The single test that actually used the pointer-ness of the argument is a test for ensuring that Rust can make extern calls outside of tasks. Rust hasn't had tasks for quite a few years now, so I'm deleting that test under the same logic as the test deleted in https://github.com/rust-lang/rust/pull/124073
Make sure we consume a generic arg when checking mistyped turbofish
When recovering un-turbofish-ed args in expr position (e.g. `let x = a<T, U>();` in `check_mistyped_turbofish_with_multiple_type_params`, we used `parse_seq_to_before_end` to parse the fake generic args; however, it used `parse_generic_arg` which *optionally* parses a generic arg. If it doesn't end up parsing an arg, it returns `Ok(None)` and consumes no tokens. If we don't find a delimiter after this (`,`), we try parsing *another* element. In this case, we just infinitely loop looking for a subsequent element.
We can fix this by making sure that we either parse a generic arg or error in `parse_seq_to_before_end`'s callback.
Fixes#124897
ignore generics args in attribute paths
Fixes#97006Fixes#123911Fixes#123912
This patch ensures that we no longer have to handle invalid generic arguments in attribute paths.
r? `@petrochenkov`
Avoid `alloca`s in codegen for simple `mir::Aggregate` statements
The core idea here is to remove the abstraction penalty of simple newtypes in codegen.
Even something simple like constructing a
```rust
#[repr(transparent)] struct Foo(u32);
```
forces an `alloca` to be generated in nightly right now.
Certainly LLVM can optimize that away, but it would be nice if it didn't have to.
Quick example:
```rust
#[repr(transparent)]
pub struct Transparent32(u32);
#[no_mangle]
pub fn make_transparent(x: u32) -> Transparent32 {
let a = Transparent32(x);
a
}
```
on nightly we produce <https://rust.godbolt.org/z/zcvoM79ae>
```llvm
define noundef i32 `@make_transparent(i32` noundef %x) unnamed_addr #0 {
%a = alloca i32, align 4
store i32 %x, ptr %a, align 4
%0 = load i32, ptr %a, align 4, !noundef !3
ret i32 %0
}
```
but after this PR we produce
```llvm
define noundef i32 `@make_transparent(i32` noundef %x) unnamed_addr #0 {
start:
ret i32 %x
}
```
(even before the optimizer runs).
Refactor float `Primitive`s to a separate `Float` type
Now there are 4 of them, it makes sense to refactor `F16`, `F32`, `F64` and `F128` out of `Primitive` and into a separate `Float` type (like integers already are). This allows patterns like `F16 | F32 | F64 | F128` to be simplified into `Float(_)`, and is consistent with `ty::FloatTy`.
As a side effect, this PR also makes the `Ty::primitive_size` method work with `f16` and `f128`.
Tracking issue: #116909
`@rustbot` label +F-f16_and_f128
Fix parse error message for meta items
Addresses https://github.com/rust-lang/rust/issues/122796#issuecomment-2010803906, cc [``@]Thomasdezeeuw.``
For attrs inside of a macro like `#[doc(alias = $ident)]` or `#[cfg(feature = $ident)]` where `$ident` is a macro metavariable of fragment kind `ident`, we used to say the following when expanded (with `$ident` ⟼ `ident`):
```
error: expected unsuffixed literal or identifier, found `ident`
--> weird.rs:6:19
|
6 | #[cfg(feature = $ident)]
| ^^^^^^
...
11 | m!(id);
| ------ in this macro invocation
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
```
This was incorrect and caused confusion, justifiably so (see #122796).
In this position, we only accept/expect *unsuffixed literals* which consist of numeric & string literals as well as the boolean literals / the keywords / the reserved identifiers `false` & `true` **but not** arbitrary identifiers.
Furthermore, we used to suggest garbage when encountering unexpected non-identifier tokens:
```
error: expected unsuffixed literal, found `-`
--> weird.rs:16:17
|
16 | #[cfg(feature = -1)]
| ^
|
help: surround the identifier with quotation marks to parse it as a string
|
16 | #[cfg(feature =" "-1)]
| + +
```
Now we no longer do.
Display walltime benchmarks with subnanosecond precision
With modern CPUs running at more than one cycle per nanosecond the current precision is insufficient to resolve differences worth several cycles per iteration.
Granted, walltime benchmarks often are noisy but occasionally, especially when no allocations are involved, the difference really is just a few cycles.
example results when benchmarking 1-4 serialized ADD instructions and an empty bench body
```
running 4 tests
test add ... bench: 0.24 ns/iter (+/- 0.00)
test add2 ... bench: 0.48 ns/iter (+/- 0.01)
test add3 ... bench: 0.72 ns/iter (+/- 0.01)
test add4 ... bench: 0.96 ns/iter (+/- 0.01)
test empty ... bench: 0.24 ns/iter (+/- 0.00)
```