Rollup of 7 pull requests
Successful merges:
- rust-lang/rust#147701 (rustdoc: don't ignore path distance for doc aliases)
- rust-lang/rust#148735 (Fix ICE caused by invalid spans for shrink_file)
- rust-lang/rust#148839 (fix rtsan_nonblocking_async lint closure ICE)
- rust-lang/rust#148846 (add a test for combining RPIT with explicit tail calls)
- rust-lang/rust#148872 (fix: Do not ICE when missing match arm with ill-formed subty is met)
- rust-lang/rust#148880 (Remove explicit install of `eslint` inside of `tidy`'s Dockerfile)
- rust-lang/rust#148883 (bootstrap: dont require cmake if local-rebuild is enabled)
r? `@ghost`
`@rustbot` modify labels: rollup
fix: Do not ICE when missing match arm with ill-formed subty is met
Fixesrust-lang/rust#148192
The ICE comes from the following line, calling `normalize_erasing_regions` to a projection type whose trait bound is not met:
https://github.com/rust-lang/rust/blob/2fcbda6c1a70606bdb09857e01d01fc6229da712/compiler/rustc_pattern_analysis/src/rustc.rs#L185-L194
The above function is called while trying to lint missing match arms, or scrutinize ctors of missing(not necessary error) match arms.
So, the following code can trigger ICEs.
```rust
trait WhereTrait {
type Type;
}
fn foo(e: Enum) {
match e {
Enum::Map(_) => (), // ICE, while trying to lint missing arms
}
if let Enum::Map(_) = e {} // ICE, while trying to scrutinize missing ctors (even worse)
}
enum Enum {
Map(()),
Map2(<() as WhereTrait>::Type),
}
```
This ICE won't be triggered with the following code, as this is filtered out before `check_match` as the existence of ill-formed type inside the variant marks the body as tainted by error in `hir_typeck`, but for the above code, the `hir_typeck` complains nothing because everything it sees is locally correct.
```rust
fn foo(e: Enum) {
match e {
Enum::Map2(_) => (), // No ICE
}
}
```
I've considered visiting and wf checking for the match scrutinee before entering `check_match`, but that might regress the perf and I think just emitting delayed bug would enough as the normalization failure would be originated by other errors like ill-formdness.
add a test for combining RPIT with explicit tail calls
tracking issue: https://github.com/rust-lang/rust/issues/112788
fixes https://github.com/rust-lang/rust/issues/139305
Combining return position impl trait (RPIT) with guaranteed tail calls does not currently work, but at least it does not ICE any more.
Using RPIT probably should work, see also https://github.com/rust-lang/rust/issues/144953.
The snippet in the issue is not valid for a variety of reasons, and based on the assert that got triggered the ICE was just any `-> impl Trait` at all, so I've made a minimal example using RPIT.
r? `@WaffleLapkin`
Fix ICE caused by invalid spans for shrink_file
Fixesrust-lang/rust#148732
There are two issues in this function:
1. the original issue is caused by a typo error, which is fixed in the first commit
2. another different ice(Patch span `7..7` is beyond the end of buffer `0`) will be reported after fixing the first one, is caused by spans cross file boundaries due to macro expansion. It is fixed in the second commit.
r? `@nnethercote`
edited: also fixesrust-lang/rust#148684, added a new testcase for it in the last commit.
New format_args!() and fmt::Arguments implementation
Part of https://github.com/rust-lang/rust/issues/99012
This is a new implementation of `format_args!()` and `fmt::Arguments`. With this implementation, `fmt::Arguments` is only two pointers in size. (Instead of six, before.) This makes it the same size as a `&str` and makes it fit in a register pair.
---
This `fmt::Arguments` can store a `&'static str` _without any indirection_ or additional storage. This means that simple cases like `print_fmt(format_args!("hello"))` are now just as efficient for the caller as `print_str("hello")`, as shown by this example:
> code:
> ```rust
> fn main() {
> println!("Hello, world!");
> }
> ```
>
> before:
> ```asm
> main:
> sub rsp, 56
> lea rax, [rip + .Lanon_hello_world]
> mov qword ptr [rsp + 8], rax
> mov qword ptr [rsp + 16], 1
> mov qword ptr [rsp + 24], 8
> xorps xmm0, xmm0
> movups xmmword ptr [rsp + 32], xmm0
> lea rdi, [rsp + 8]
> call qword ptr [rip + std::io::stdio::_print]
> add rsp, 56
> ret
> ```
>
> after:
> ```asm
> main:
> lea rsi, [rip + .Lanon_hello_world]
> mov edi, 29
> jmp qword ptr [rip + std::io::stdio::_print]
> ```
(`panic!("Hello, world!");` shows a similar change.)
---
This implementation stores all static information as just a single (byte) string, without any indirection:
> code:
> ```rust
> format_args!("Hello, {name:-^20}!")
> ```
>
> lowering before:
> ```rust
> fmt::Arguments::new_v1_formatted(
> &["Hello, ", "!\n"],
> &args,
> &[
> Placeholder {
> position: 0usize,
> flags: 3355443245u32,
> precision: format_count::Implied,
> width: format_count::Is(20u16),
> },
> ],
> )
> ```
>
> lowering after:
> ```rust
> fmt::Arguments::new(
> b"\x07Hello, \xc3-\x00\x00\xc8\x14\x00\x02!\n\x00",
> &args,
> )
> ```
This saves a ton of pointers and simplifies the expansion significantly, but does mean that individual pieces (e.g. `"Hello, "` and `"!\n"`) cannot be reused. (Those pieces are often smaller than a pointer to them, though, in which case reusing them is useless.)
---
The details of the new representation are documented in [library/core/src/fmt/mod.rs](https://github.com/m-ou-se/rust/blob/new-fmt-args-alt/library/core/src/fmt/mod.rs#L609-L712).
cmse: add test for `async` and `const` functions
tracking issue: https://github.com/rust-lang/rust/issues/81391
tracking issue: https://github.com/rust-lang/rust/issues/75835
Some additional tests that seemed useful while working on the RFC text.
`async` functions are disallowed (because `-> impl Trait` is not supported).
`const` entry functions are allowed, `nonsecure-call` does not make sense, because this abi can only be used on function pointers, which cannot be evaluated during constant evaluation.
The async test is in the `c-variadic.rs` file because it has the minicore-compatible machinery for defining an async function. Splitting that logic out (like `minisimd.rs`) turns out to be complicated because the async stuff relies on types defined by minicore.
r? `````@davidtwco`````
Adjust spans into the `for` loops context before creating the new desugaring spans.
When lowering `for` loops, the spans for the `into_iter` call and the `Some` pattern used the span of the provided pattern and head expression. If either of those came from a different `SyntaxContext` this would result in some very strange contexts. e.g.:
```rust
macro_rules! m { ($e:expr) => { { $e } } }
for _ in m!(expr) {}
```
This would result in the `into_iter` call have a context chain of `desugar => m!() => root` which is completely nonsensical; `m!()` does not have a `for` loop. The `into_iter` call also ends up located at `{ $e }` rather than inside the `for _ in _` part.
This fixes that by walking the spans up to the `for` loop's context first. This will not handle adjusting the location of macro variable expansions (e.g. `for _ in $e`), but this does adjust the context to match the `for` loops.
---
This ended up causing rust-lang/rust-clippy#16008. Clippy should be using a `debug_assert` rather than `unreachable`, but it still results in a bug either way.
[rustdoc] Fix invalid jump to def macro link generation
Follow-up of https://github.com/rust-lang/rust/issues/147820.
I realized that when there was no intra-doc link linking to the same item, then the generated link for macros in jump to def would be invalid.
To make the code less redundant, I merged the "registering" of items and the href generation use the same code for macros.
r? `````@notriddle`````
Improve diagnostics for buffer reuse with borrowed references
Addresses rust-lang/rust#147694
I'm not sure the current note wording is the best so I appreciate any feedback.
This is useful when you have two dependencies that use different trait for
the same thing and with the same name. The user can accidentally implement
the bad one which might be confusing. This commits refactorizes existing
diagnostics about multiple different crates with the same version and adds
a note when similarly named traits are found. All diagnostics are merged
into a single one.
Document (and test) a problem with `Clone`/`Copy` deriving.
I think this is useful information. I have worked on `derive` impls quite a bit and didn't know about this issue until today.
r? `@saethlin`
Port `cfg_select!` to the new attribute parsing system
Best reviewed commit by commit, since it involves some moving around of code
r? `````@jdonszelmann`````
Check unsafety for non-macro attributes in `validate_attr`
r? `````@jdonszelmann`````
Also adds a test for a previously untested case, unnecessary unsafe on a proc macro attribute
In preparation for https://github.com/rust-lang/rust/issues/148453
Provide more context when mutably borrowing an imutably borrowed value
Point at statics and consts being mutable borrowed or written to:
```
error[E0594]: cannot assign to immutable static item `NUM`
--> $DIR/E0594.rs:4:5
|
LL | static NUM: i32 = 18;
| --------------- this `static` cannot be written to
...
LL | NUM = 20;
| ^^^^^^^^ cannot assign
```
Point at the expression that couldn't be mutably borrowed from a pattern:
```
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/mut-pattern-of-immutable-borrow.rs:19:14
|
LL | match &arg.field {
| ---------- this cannot be borrowed as mutable
LL | Some(ref mut s) => s.push('a'),
| ^^^^^^^^^ cannot borrow as mutable
```
Partially address rust-lang/rust#74617.
Special case detecting `'static` lifetime requirement coming from `-> Box<dyn Trait>`
```
error[E0310]: the parameter type `R` may not live long enough
--> $DIR/implicit-static-lifetime-in-dyn-trait-return-type.rs:10:5
|
LL | fn bb<R>(r: R) -> Box<dyn Foo> {
| ------- this `dyn Trait` has an implicit `'static` lifetime bound
LL | Box::new(Bar(r))
| ^^^^^^^^^^^^^^^^
| |
| the parameter type `R` must be valid for the static lifetime...
| ...so that the type `R` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
LL | fn bb<R: 'static>(r: R) -> Box<dyn Foo> {
| +++++++++
```
Partly address rust-lang/rust#41966 and rust-lang/rust#54753. rust-lang/rust#103849, which shows a case where there's an intermediary binding, is not addressed at all, as aren't cases *other* than `Box<dyn Trait>` return type.
rustdoc: Erase `#![doc(document_private_items)]`
I just found out about the existence of `#![doc(document_private_items)]`. Apparently it was added by PR rust-lang/rust#50669 back in 2018 without any tests or docs as a replacement for some specific forms of the removed `#![doc(passes)]` / `#![doc(no_default_passes)]`.
However, rustc and rustdoc actually emit the deny-by-default lint `invalid_doc_attributes` for it (but if you allow it, the attribute does function)! To be more precise since PR rust-lang/rust#82708 (1.52, May 2021) which introduced lint `invalid_doc_attributes`, rust{,do}c has emitted a future-incompat warning for this attribute. And since PR rust-lang/rust#111505 (1.78, May 2024) that lint is deny by default. I presume nobody knew this attribute existed and thus it was never allowlisted.
Given the fact that since 2021 nobody has ever opened a ticket ([via](https://github.com/rust-lang/rust/issues?q=is%3Aissue+document_private_items)) complaining about the lint emission and the fact that GitHub code search doesn't yield any actual uses ([via](https://github.com/search?q=%2F%23%21%5C%5Bdoc%5C%28.*%3Fdocument_private_items%2F+language%3ARust&type=code&ref=advsearch)), I'm led to believe that nobody knows about and uses this attribute.
I don't find the existence of this attribute to be justified since in my view the flag `--document-private-items` is strictly superior: In most if not all cases, you don't want to "couple" your crate with this "mode" even if you gate it behind a cfg; instead, you most likely want to set this manually at invocation time, via a build config file like `.cargo/config.toml` or via a command runner like `just` I'd say.
Because of this I propose to wipe this attribute from existence. I don't believe it's worth cratering this (i.e., temporarily emitting a hard error for this attribute and running crater) given the fact that it's been undocumented since forever and led to a warning for years.
`c_variadic`: Add future-incompatibility warning for `...` arguments without a pattern outside of `extern` blocks
This PR makes `...` arguments without a pattern in non-foreign functions (such as the argument in `unsafe extern "C" fn f(...) {}`) a future-compatibility warning; making this error would be consistent with how `unsafe extern "C" fn f(u32) {}` is handled. Allowing `...` arguments without a pattern in non-foreign functions is a source of confusion for programmers coming from C, where the `...` parameter is never named and instead calling `va_start` is required; disallowing `...` arguments without a pattern also improves the overall consistency of the Rust language by matching the treatment of other arguments without patterns. `...` arguments without a pattern in `extern` blocks (such as `unsafe extern "C" { fn f(...); }`) continue to compile without warnings after this PR, as they are already stable and heavily used (and don't cause the mentioned confusion as they are just being used in function declarations).
As all the syntax gating for `c_variadic` has been done post-expansion, this is technically a breaking change. In particular, code like this has compiled on stable since Rust 1.35.0:
```rust
#[cfg(any())] // Equivalent to the more recent #[cfg(false)]
unsafe extern "C" fn bar(_: u32, ...) {}
```
Since this is more or less a stability hole and a Crater run shows only the `binrw` crate is using this, I think it would be ok to break this. This will require a lang FCP.
The idea of rejecting `...` pre-expansion was first raised here https://github.com/rust-lang/rust/pull/143546#issuecomment-3043142052.
Tracking issue: rust-lang/rust#44930
cc `@folkertdev` `@workingjubilee`
r? `@joshtriplett`
Add new `function_casts_as_integer` lint
The `function_casts_as_integer` lint detects cases where users cast a function pointer into an integer.
*warn-by-default*
### Example
```rust
fn foo() {}
let x = foo as usize;
```
```
warning: casting a function into an integer implicitly
--> $DIR/function_casts_as_integer.rs:9:17
|
LL | let x = foo as usize;
| ^^^^^^^^
|
help: add `fn() as usize`
|
LL | let x = foo as fn() as usize;
| +++++++
```
### Explanation
You should never cast a function directly into an integer but go through a cast as `fn` first to make it obvious what's going on. It also allows to prevent confusion with (associated) constants.
Related to https://github.com/rust-lang/rust/issues/81686 and https://stackoverflow.com/questions/68701177/whats-the-meaning-of-casting-a-rust-enum-variant-to-a-numeric-data-type
r? ````@urgau````
Implement `&pin` patterns and `ref pin` binding modes
Implement `&pin` patterns and `ref pin` binding modes, part of [pin ergonomics](https://github.com/rust-lang/rust/issues/130494).
r? `@Nadrieril`
cc `@traviscross` `@eholk`
stop specializing on `Copy`
fixes https://github.com/rust-lang/rust/issues/132442
`std` specializes on `Copy` to optimize certain library functions such as `clone_from_slice`. This is unsound, however, as the `Copy` implementation may not be always applicable because of lifetime bounds, which specialization does not take into account; the result being that values are copied even though they are not `Copy`. For instance, this code:
```rust
struct SometimesCopy<'a>(&'a Cell<bool>);
impl<'a> Clone for SometimesCopy<'a> {
fn clone(&self) -> Self {
self.0.set(true);
Self(self.0)
}
}
impl Copy for SometimesCopy<'static> {}
let clone_called = Cell::new(false);
// As SometimesCopy<'clone_called> is not 'static, this must run `clone`,
// setting the value to `true`.
let _ = [SometimesCopy(&clone_called)].clone();
assert!(clone_called.get());
```
should not panic, but does ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6be7a48cad849d8bd064491616fdb43c)).
To solve this, this PR introduces a new `unsafe` trait: `TrivialClone`. This trait may be implemented whenever the `Clone` implementation is equivalent to copying the value (so e.g. `fn clone(&self) -> Self { *self }`). Because of lifetime erasure, there is no way for the `Clone` implementation to observe lifetime bounds, meaning that even if the `TrivialClone` has stricter bounds than the `Clone` implementation, its invariant still holds. Therefore, it is sound to specialize on `TrivialClone`.
I've changed all `Copy` specializations in the standard library to specialize on `TrivialClone` instead. Unfortunately, the unsound `#[rustc_unsafe_specialization_marker]` attribute on `Copy` cannot be removed in this PR as `hashbrown` still depends on it. I'll make a PR updating `hashbrown` once this lands.
With `Copy` no longer being considered for specialization, this change alone would result in the standard library optimizations not being applied for user types unaware of `TrivialClone`. To avoid this and restore the optimizations in most cases, I have changed the expansion of `#[derive(Clone)]`: Currently, whenever both `Clone` and `Copy` are derived, the `clone` method performs a copy of the value. With this PR, the derive macro also adds a `TrivialClone` implementation to make this case observable using specialization. I anticipate that most users will use `#[derive(Clone, Copy)]` whenever both are applicable, so most users will still profit from the library optimizations.
Unfortunately, Hyrum's law applies to this PR: there are some popular crates which rely on the precise specialization behaviour of `core` to implement "specialization at home", e.g. [`libAFL`](https://github.com/AFLplusplus/LibAFL/blob/89cff637025c1652c24e8d97a30a2e3d01f187a4/libafl_bolts/src/tuples.rs#L27-L49). I have no remorse for breaking such horrible code, but perhaps we should open other, better ways to satisfy their needs – for example by dropping the `'static` bound on `TypeId::of`...