These are `Self` in almost all printers except one, which can just store
the state as a field instead. This simplifies the printer and allows for
further simplifications, for example using `&mut self` instead of
passing around the printer.
It's a better name, and lets "active features" refer to the features
that are active in a particular program, due to being declared or
enabled by the edition.
The commit also renames `Features::enabled` as `Features::active` to
match this; I changed my mind and have decided that "active" is a little
better thatn "enabled" for this, particularly because a number of
pre-existing comments use "active" in this way.
Finally, the commit renames `Status::Stable` as `Status::Accepted`, to
match `ACCEPTED_FEATURES`.
Format all the let-chains in compiler crates
Since rust-lang/rustfmt#5910 has landed, soon we will have support for formatting let-chains (as soon as rustfmt syncs and beta gets bumped).
This PR applies the changes [from master rustfmt to rust-lang/rust eagerly](https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/out.20formatting.20of.20prs/near/374997516), so that the next beta bump does not have to deal with a 200+ file diff and can remain concerned with other things like `cfg(bootstrap)` -- #113637 was a pain to land, for example, because of let-else.
I will also add this commit to the ignore list after it has landed.
The commands that were run -- I'm not great at bash-foo, but this applies rustfmt to every compiler crate, and then reverts the two crates that should probably be formatted out-of-tree.
```
~/rustfmt $ ls -1d ~/rust/compiler/* | xargs -I@ cargo run --bin rustfmt -- `@/src/lib.rs` --config-path ~/rust --edition=2021 # format all of the compiler crates
~/rust $ git checkout HEAD -- compiler/rustc_codegen_{gcc,cranelift} # revert changes to cg-gcc and cg-clif
```
cc `@rust-lang/rustfmt`
r? `@WaffleLapkin` or `@Nilstrieb` who said they may be able to review this purely mechanical PR :>
cc `@Mark-Simulacrum` and `@petrochenkov,` who had some thoughts on the order of operations with big formatting changes in https://github.com/rust-lang/rust/pull/95262#issue-1178993801. I think the situation has changed since then, given that let-chains support exists on master rustfmt now, and I'm fairly confident that this formatting PR should land even if *bootstrap* rustfmt doesn't yet format let-chains in order to lessen the burden of the next beta bump.
Fix AFIT lint message to mention pitfall
Addresses https://github.com/rust-lang/rust/pull/116184#issuecomment-1745194387 by adding a short note. Not sure exactly of the wording -- I don't think this should be a blocker for the stabilization PR since we can iterate on this lint's messaging in the next few weeks in the worst case.
r? `@tmandry` cc `@traviscross` `@jonhoo`
Stabilize `async fn` and return-position `impl Trait` in trait
# Stabilization report
This report proposes the stabilization of `#![feature(return_position_impl_trait_in_trait)]` ([RPITIT][RFC 3425]) and `#![feature(async_fn_in_trait)]` ([AFIT][RFC 3185]). These are both long awaited features that increase the expressiveness of the Rust language and trait system.
Closes#91611
[RFC 3185]: https://rust-lang.github.io/rfcs/3185-static-async-fn-in-trait.html
[RFC 3425]: https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html
## Updates from thread
The thread has covered two major concerns:
* [Given that we don't have RTN, what should we stabilize?](https://github.com/rust-lang/rust/pull/115822#issuecomment-1731149475) -- proposed resolution is [adding a lint](https://github.com/rust-lang/rust/pull/115822#issuecomment-1728354622) and [careful messaging](https://github.com/rust-lang/rust/pull/115822#issuecomment-1731136169)
* [Interaction between outlives bounds and capture semantics](https://github.com/rust-lang/rust/pull/115822#issuecomment-1731153952) -- This is fixable in a forwards-compatible way via #116040, and also eventually via ATPIT.
## Stabilization Summary
This stabilization allows the following examples to work.
### Example of return-position `impl Trait` in trait definition
```rust
trait Bar {
fn bar(self) -> impl Send;
}
```
This declares a trait method that returns *some* type that implements `Send`. It's similar to writing the following using an associated type, except that the associated type is anonymous.
```rust
trait Bar {
type _0: Send;
fn bar(self) -> Self::_0;
}
```
### Example of return-position `impl Trait` in trait implementation
```rust
impl Bar for () {
fn bar(self) -> impl Send {}
}
```
This defines a method implementation that returns an opaque type, just like [RPIT][RFC 1522] does, except that all in-scope lifetimes are captured in the opaque type (as is already true for `async fn` and as is expected to be true for RPIT in Rust Edition 2024), as described below.
[RFC 1522]: https://rust-lang.github.io/rfcs/1522-conservative-impl-trait.html
### Example of `async fn` in trait
```rust
trait Bar {
async fn bar(self);
}
impl Bar for () {
async fn bar(self) {}
}
```
This declares a trait method that returns *some* [`Future`](https://doc.rust-lang.org/core/future/trait.Future.html) and a corresponding method implementation. This is equivalent to writing the following using RPITIT.
```rust
use core::future::Future;
trait Bar {
fn bar(self) -> impl Future<Output = ()>;
}
impl Bar for () {
fn bar(self) -> impl Future<Output = ()> { async {} }
}
```
The desirability of this desugaring being available is part of why RPITIT and AFIT are being proposed for stabilization at the same time.
## Motivation
Long ago, Rust added [RPIT][RFC 1522] and [`async`/`await`][RFC 2394]. These are major features that are widely used in the ecosystem. However, until now, these feature could not be used in *traits* and trait implementations. This left traits as a kind of second-class citizen of the language. This stabilization fixes that.
[RFC 2394]: https://rust-lang.github.io/rfcs/2394-async_await.html
### `async fn` in trait
Async/await allows users to write asynchronous code much easier than they could before. However, it doesn't play nice with other core language features that make Rust the great language it is, like traits. Support for `async fn` in traits has been long anticipated and was not added before due to limitations in the compiler that have now been lifted.
`async fn` in traits will unblock a lot of work in the ecosystem and the standard library. It is not currently possible to write a trait that is implemented using `async fn`. The workarounds that exist are undesirable because they require allocation and dynamic dispatch, and any trait that uses them will become obsolete once native `async fn` in trait is stabilized.
We also have ample evidence that there is demand for this feature from the [`async-trait` crate][async-trait], which emulates the feature using dynamic dispatch. The async-trait crate is currently the #5 async crate on crates.io ranked by recent downloads, receiving over 78M all-time downloads. According to a [recent analysis][async-trait-analysis], 4% of all crates use the `#[async_trait]` macro it provides, representing 7% of all function and method signatures in trait definitions on crates.io. We think this is a *lower bound* on demand for the feature, because users are unlikely to use `#[async_trait]` on public traits on crates.io for the reasons already given.
[async-trait]: https://crates.io/crates/async-trait
[async-trait-analysis]: https://rust-lang.zulipchat.com/#narrow/stream/315482-t-compiler.2Fetc.2Fopaque-types/topic/RPIT.20capture.20rules.20.28capturing.20everything.29/near/389496292
### Return-position `impl Trait` in trait
`async fn` always desugars to a function that returns `impl Future`.
```rust!
async fn foo() -> i32 { 100 }
// Equivalent to:
fn foo() -> impl Future<Output = i32> { async { 100 } }
```
All `async fn`s today can be rewritten this way. This is useful because it allows adding behavior that runs at the time of the function call, before the first `.await` on the returned future.
In the spirit of supporting the same set of features on `async fn` in traits that we do outside of traits, it makes sense to stabilize this as well. As described by the [RPITIT RFC][rpitit-rfc], this includes the ability to mix and match the equivalent forms in traits and their corresponding impls:
```rust!
trait Foo {
async fn foo(self) -> i32;
}
// Can be implemented as:
impl Foo for MyType {
fn foo(self) -> impl Future<Output = i32> {
async { 100 }
}
}
```
Return-position `impl Trait` in trait is useful for cases beyond async, just as regular RPIT is. As a simple example, the RFC showed an alternative way of writing the `IntoIterator` trait with one fewer associated type.
```rust!
trait NewIntoIterator {
type Item;
fn new_into_iter(self) -> impl Iterator<Item = Self::Item>;
}
impl<T> NewIntoIterator for Vec<T> {
type Item = T;
fn new_into_iter(self) -> impl Iterator<Item = T> {
self.into_iter()
}
}
```
[rpitit-rfc]: https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html
## Major design decisions
This section describes the major design decisions that were reached after the RFC was accepted:
- EDIT: Lint against async fn in trait definitions
- Until the [send bound problem](https://smallcultfollowing.com/babysteps/blog/2023/02/01/async-trait-send-bounds-part-1-intro/) is resolved, the use of `async fn` in trait definitions could lead to a bad experience for people using work-stealing executors (by far the most popular choice). However, there are significant use cases for which the current support is all that is needed (single-threaded executors, such as those used in embedded use cases, as well as thread-per-core setups). We are prioritizing serving users well over protecting people from misuse, and therefore, we opt to stabilize the full range of functionality; however, to help steer people correctly, we are will issue a warning on the use of `async fn` in trait definitions that advises users about the limitations. (See [this summary comment](https://github.com/rust-lang/rust/pull/115822#issuecomment-1731149475) for the details of the concern, and [this comment](https://github.com/rust-lang/rust/pull/115822#issuecomment-1728354622) for more details about the reasoning that led to this conclusion.)
- Capture rules:
- The RFC's initial capture rules for lifetimes in impls/traits were found to be imprecisely precise and to introduce various inconsistencies. After much discussion, the decision was reached to make `-> impl Trait` in traits/impls capture *all* in-scope parameters, including both lifetimes and types. This is a departure from the behavior of RPITs in other contexts; an RFC is currently being authored to change the behavior of RPITs in other contexts in a future edition.
- Major discussion links:
- [Lang team design meeting from 2023-07-26](https://hackmd.io/sFaSIMJOQcuwCdnUvCxtuQ?view)
- Refinement:
- The [refinement RFC] initially proposed that impl signatures that are more specific than their trait are not allowed unless the `#[refine]` attribute was included, but left it as an open question how to implement this. The stabilized proposal is that it is not a hard error to omit `#[refine]`, but there is a lint which fires if the impl's return type is more precise than the trait. This greatly simplified the desugaring and implementation while still achieving the original goal of ensuring that users do not accidentally commit to a more specific return type than they intended.
- Major discussion links:
- [Zulip thread](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/.60.23.5Brefine.5D.60.20as.20a.20lint)
[refinement RFC]: https://rust-lang.github.io/rfcs/3245-refined-impls.html
## What is stabilized
### Async functions in traits and trait implementations
* `async fn` are now supported in traits and trait implementations.
* Associated functions in traits that are `async` may have default bodies.
### Return-position impl trait in traits and trait implementations
* Return-position `impl Trait`s are now supported in traits and trait implementations.
* Return-position `impl Trait` in implementations are treated like regular return-position `impl Trait`s, and therefore behave according to the same inference rules for hidden type inference and well-formedness.
* Associated functions in traits that name return-position `impl Trait`s may have default bodies.
* Implementations may provide either concrete types or `impl Trait` for each corresponding `impl Trait` in the trait method signature.
For a detailed exploration of the technical implementation of return-position `impl Trait` in traits, see [the dev guide](https://rustc-dev-guide.rust-lang.org/return-position-impl-trait-in-trait.html).
### Mixing `async fn` in trait and return-position `impl Trait` in trait
A trait function declaration that is `async fn ..() -> T` may be satisfied by an implementation function that returns `impl Future<Output = T>`, or vice versa.
```rust
trait Async {
async fn hello();
}
impl Async for () {
fn hello() -> impl Future<Output = ()> {
async {}
}
}
trait RPIT {
fn hello() -> impl Future<Output = String>;
}
impl RPIT for () {
async fn hello() -> String {
"hello".to_string()
}
}
```
### Return-position `impl Trait` in traits and trait implementations capture all in-scope lifetimes
Described above in "major design decisions".
### Return-position `impl Trait` in traits are "always revealing"
When a trait uses `-> impl Trait` in return position, it logically desugars to an associated type that represents the return (the actual implementation in the compiler is different, as described below). The value of this associated type is determined by the actual return type written in the impl; if the impl also uses `-> impl Trait` as the return type, then the value of the associated type is an opaque type scoped to the impl method (similar to what you would get when calling an inherent function returning `-> impl Trait`). As with any associated type, the value of this special associated type can be revealed by the compiler if the compiler can figure out what impl is being used.
For example, given this trait:
```rust
trait AsDebug {
fn as_debug(&self) -> impl Debug;
}
```
A function working with the trait generically is only able to see that the return value is `Debug`:
```rust
fn foo<T: AsDebug>(t: &T) {
let u = t.as_debug();
println!("{}", u); // ERROR: `u` is not known to implement `Display`
}
```
But if a function calls `as_debug` on a known type (say, `u32`), it may be able to resolve the return type more specifically, if that implementation specifies a concrete type as well:
```rust
impl AsDebug for u32 {
fn as_debug(&self) -> u32 {
*self
}
}
fn foo(t: &u32) {
let u: u32 = t.as_debug(); // OK!
println!("{}", t.as_debug()); // ALSO OK (since `u32: Display`).
}
```
The return type used in the impl therefore represents a **semver binding** promise from the impl author that the return type of `<u32 as AsDebug>::as_debug` will not change. This could come as a surprise to users, who might expect that they are free to change the return type to any other type that implements `Debug`. To address this, we include a [`refining_impl_trait` lint](https://github.com/rust-lang/rust/pull/115582) that warns if the impl uses a specific type -- the `impl AsDebug for u32` above, for example, would toggle the lint.
The lint message explains what is going on and encourages users to `allow` the lint to indicate that they meant to refine the return type:
```rust
impl AsDebug for u32 {
#[allow(refining_impl_trait)]
fn as_debug(&self) -> u32 {
*self
}
}
```
[RFC #3245](https://github.com/rust-lang/rfcs/pull/3245) proposed a new attribute, `#[refine]`, that could also be used to "opt-in" to refinements like this (and which would then silence the lint). That RFC is not currently implemented -- the `#[refine]` attribute is also expected to reveal other details from the signature and has not yet been fully implemented.
### Return-position `impl Trait` and `async fn` in traits are opted-out of object safety checks when the parent function has `Self: Sized`
```rust
trait IsObjectSafe {
fn rpit() -> impl Sized where Self: Sized;
async fn afit() where Self: Sized;
}
```
Traits that mention return-position `impl Trait` or `async fn` in trait when the associated function includes a `Self: Sized` bound will remain object safe. That is because the associated function that defines them will be opted-out of the vtable of the trait, and the associated types will be unnameable from any trait object.
This can alternatively be seen as a consequence of https://github.com/rust-lang/rust/pull/112319#issue-1742251747 and the desugaring of return-position `impl Trait` in traits to associated types which inherit the where-clauses of the associated function that defines them.
## What isn't stabilized (aka, potential future work)
### Dynamic dispatch
As stabilized, traits containing RPITIT and AFIT are **not dyn compatible**. This means that you cannot create `dyn Trait` objects from them and can only use static dispatch. The reason for this limitation is that dynamic dispatch support for RPITIT and AFIT is more complex than static dispatch, as described on the [async fundamentals page](https://rust-lang.github.io/async-fundamentals-initiative/evaluation/challenges/dyn_traits.html). The primary challenge to using `dyn Trait` in today's Rust is that **`dyn Trait` today must list the values of all associated types**. This means you would have to write `dyn for<'s> Trait<Foo<'s> = XXX>` where `XXX` is the future type defined by the impl, such as `F_A`. This is not only verbose (or impossible), it also uniquely ties the `dyn Trait` to a particular impl, defeating the whole point of `dyn Trait`.
The precise design for handling dynamic dispatch is not yet determined. Top candidates include:
- [callee site selection][], in which we permit unsized return values so that the return type for an `-> impl Foo` method be can be `dyn Foo`, but then users must specify the type of wide pointer at the call-site in some fashion.
- [`dyn*`][], where we create a built-in encapsulation of a "wide pointer" and map the associated type corresponding to an RPITIT to the corresponding `dyn*` type (`dyn*` itself is not exposed to users as a type in this proposal, though that could be a future extension).
[callee site selection]: https://smallcultfollowing.com/babysteps/blog/2022/09/21/dyn-async-traits-part-9-callee-site-selection/
[`dyn*`]: https://smallcultfollowing.com/babysteps/blog/2022/03/29/dyn-can-we-make-dyn-sized/
### Where-clause bounds on return-position `impl Trait` in traits or async futures (RTN/ART)
One limitation of async fn in traits and RPITIT as stabilized is that there is no way for users to write code that adds additional bounds beyond those listed in the `-> impl Trait`. The most common example is wanting to write a generic function that requires that the future returned from an `async fn` be `Send`:
```rust
trait Greet {
async fn greet(&self);
}
fn greet_in_parallel<G: Greet>(g: &G) {
runtime::spawn(async move {
g.greet().await; //~ ERROR: future returned by `greet` may not be `Send`
})
}
```
Currently, since the associated types added for the return type are anonymous, there is no where-clause that could be added to make this code compile.
There have been various proposals for how to address this problem (e.g., [return type notation][rtn] or having an annotation to give a name to the associated type), but we leave the selection of one of those mechanisms to future work.
[rtn]: https://smallcultfollowing.com/babysteps/blog/2023/02/13/return-type-notation-send-bounds-part-2/
In the meantime, there are workarounds that one can use to address this problem, listed below.
#### Require all futures to be `Send`
For many users, the trait may only ever be used with `Send` futures, in which case one can write an explicit `impl Future + Send`:
```rust
trait Greet {
fn greet(&self) -> impl Future<Output = ()> + Send;
}
```
The nice thing about this is that it is still compatible with using `async fn` in the trait impl. In the async working group case studies, we found that this could work for the [builder provider API](https://rust-lang.github.io/async-fundamentals-initiative/evaluation/case-studies/builder-provider-api.html). This is also the default approach used by the `#[async_trait]` crate which, as we have noted, has seen widespread adoption.
#### Avoid generics
This problem only applies when the `Self` type is generic. If the `Self` type is known, then the precise return type from an `async fn` is revealed, and the `Send` bound can be inferred thanks to auto-trait leakage. Even in cases where generics may appear to be required, it is sometimes possible to rewrite the code to avoid them. The [socket handler refactor](https://rust-lang.github.io/async-fundamentals-initiative/evaluation/case-studies/socket-handler.html) case study provides one such example.
### Unify capture behavior for `-> impl Trait` in inherent methods and traits
As stabilized, the capture behavior for `-> impl Trait` in a trait (whether as part of an async fn or a RPITIT) captures all types and lifetimes, whereas the existing behavior for inherent methods only captures types and lifetimes that are explicitly referenced. Capturing all lifetimes in traits was necessary to avoid various surprising inconsistencies; the expressed intent of the lang team is to extend that behavior so that we also capture all lifetimes in inherent methods, which would create more consistency and also address a common source of user confusion, but that will have to happen over the 2024 edition. The RFC is in progress. Should we opt not to accept that RFC, we can bring the capture behavior for `-> impl Trait` into alignment in other ways as part of the 2024 edition.
### `impl_trait_projections`
Orthgonal to `async_fn_in_trait` and `return_position_impl_trait_in_trait`, since it can be triggered on stable code. This will be stabilized separately in [#115659](https://github.com/rust-lang/rust/pull/115659).
<details>
If we try to write this code without `impl_trait_projections`, we will get an error:
```rust
#![feature(async_fn_in_trait)]
trait Foo {
type Error;
async fn foo(&mut self) -> Result<(), Self::Error>;
}
impl<T: Foo> Foo for &mut T {
type Error = T::Error;
async fn foo(&mut self) -> Result<(), Self::Error> {
T::foo(self).await
}
}
```
The error relates to the use of `Self` in a trait impl when the self type has a lifetime. It can be worked around by rewriting the impl not to use `Self`:
```rust
#![feature(async_fn_in_trait)]
trait Foo {
type Error;
async fn foo(&mut self) -> Result<(), Self::Error>;
}
impl<T: Foo> Foo for &mut T {
type Error = T::Error;
async fn foo(&mut self) -> Result<(), <&mut T as Foo>::Error> {
T::foo(self).await
}
}
```
</details>
## Tests
Tests are generally organized between return-position `impl Trait` and `async fn` in trait, when the distinction matters.
* RPITIT: https://github.com/rust-lang/rust/tree/master/tests/ui/impl-trait/in-trait
* AFIT: https://github.com/rust-lang/rust/tree/master/tests/ui/async-await/in-trait
## Remaining bugs and open issues
* #112047: Indirection introduced by `async fn` and return-position `impl Trait` in traits may hide cycles in opaque types, causing overflow errors that can only be discovered by monomorphization.
* #111105 - `async fn` in trait is susceptible to issues with checking auto traits on futures' generators, like regular `async`. This is a manifestation of #110338.
* This was deemed not blocking because fixing it is forwards-compatible, and regular `async` is subject to the same issues.
* #104689: `async fn` and return-position `impl Trait` in trait requires the late-bound lifetimes in a trait and impl function signature to be equal.
* This can be relaxed in the future with a smarter lexical region resolution algorithm.
* #102527: Nesting return-position `impl Trait` in trait deeply may result in slow compile times.
* This has only been reported once, and can be fixed in the future.
* #108362: Inference between return types and generics of a function may have difficulties when there's an `.await`.
* This isn't related to AFIT (https://github.com/rust-lang/rust/issues/108362#issuecomment-1717927918) -- using traits does mean that there's possibly easier ways to hit it.
* #112626: Because `async fn` and return-position `impl Trait` in traits lower to associated types, users may encounter strange behaviors when implementing circularly dependent traits.
* This is not specific to RPITIT, and is a limitation of associated types: https://github.com/rust-lang/rust/issues/112626#issuecomment-1603405105
* **(Nightly)** #108309: `async fn` and return-position `impl Trait` in trait do not support specialization. This was deemed not blocking, since it can be fixed in the future (e.g. #108321) and specialization is a nightly feature.
#### (Nightly) Return type notation bugs
RTN is not being stabilized here, but there are some interesting outstanding bugs. None of them are blockers for AFIT/RPITIT, but I'm noting them for completeness.
<details>
* #109924 is a bug that occurs when a higher-ranked trait bound has both inference variables and associated types. This is pre-existing -- RTN just gives you a more convenient way of producing them. This should be fixed by the new trait solver.
* #109924 is a manifestation of a more general issue with `async` and auto-trait bounds: #110338. RTN does not cause this issue, just allows us to put `Send` bounds on the anonymous futures that we have in traits.
* #112569 is a bug similar to associated type bounds, where nested bounds are not implied correctly.
</details>
## Alternatives
### Do nothing
We could choose not to stabilize these features. Users that can use the `#[async_trait]` macro would continue to do so. Library maintainers would continue to avoid async functions in traits, potentially blocking the stable release of many useful crates.
### Stabilize `impl Trait` in associated type instead
AFIT and RPITIT solve the problem of returning unnameable types from trait methods. It is also possible to solve this by using another unstable feature, `impl Trait` in an associated type. Users would need to define an associated type in both the trait and trait impl:
```rust!
trait Foo {
type Fut<'a>: Future<Output = i32> where Self: 'a;
fn foo(&self) -> Self::Fut<'_>;
}
impl Foo for MyType {
type Fut<'a> where Self: 'a = impl Future<Output = i32>;
fn foo(&self) -> Self::Fut<'_> {
async { 42 }
}
}
```
This also has the advantage of allowing generic code to bound the associated type. However, it is substantially less ergonomic than either `async fn` or `-> impl Future`, and users still expect to be able to use those features in traits. **Even if this feature were stable, we would still want to stabilize AFIT and RPITIT.**
That said, we can have both. `impl Trait` in associated types is desireable because it can be used in existing traits with explicit associated types, among other reasons. We *should* stabilize this feature once it is ready, but that's outside the scope of this proposal.
### Use the old capture semantics for RPITIT
We could choose to make the capture rules for RPITIT consistent with the existing rules for RPIT. However, there was strong consensus in a recent [lang team meeting](https://hackmd.io/sFaSIMJOQcuwCdnUvCxtuQ?view) that we should *change* these rules, and furthermore that new features should adopt the new rules.
This is consistent with the tenet in RFC 3085 of favoring ["Uniform behavior across editions"](https://rust-lang.github.io/rfcs/3085-edition-2021.html#uniform-behavior-across-editions) when possible. It greatly reduces the complexity of the feature by not requiring us to answer, or implement, the design questions that arise out of the interaction between the current capture rules and traits. This reduction in complexity – and eventual technical debt – is exactly in line with the motivation listed in the aforementioned RFC.
### Make refinement a hard error
Refinement (`refining_impl_trait`) is only a concern for library authors, and therefore doesn't really warrant making into a deny-by-default warning or an error.
Additionally, refinement is currently checked via a lint that compares bounds in the `impl Trait`s in the trait and impl syntactically. This is good enough for a warning that can be opted-out, but not if this were a hard error, which would ideally be implemented using fully semantic, implicational logic. This was implemented (#111931), but also is an unnecessary burden on the type system for little pay-off.
## History
- Dec 7, 2021: [RFC #3185: Static async fn in traits](https://rust-lang.github.io/rfcs/3185-static-async-fn-in-trait.html) merged
- Sep 9, 2022: [Initial implementation](https://github.com/rust-lang/rust/pull/101224) of AFIT and RPITIT landed
- Jun 13, 2023: [RFC #3425: Return position `impl Trait` in traits](https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html) merged
<!--These will render pretty when pasted into github-->
Non-exhaustive list of PRs that are particularly relevant to the implementation:
- #101224
- #103491
- #104592
- #108141
- #108319
- #108672
- #112988
- #113182 (later made redundant by #114489)
- #113215
- #114489
- #115467
- #115582
Doc co-authored by `@nikomatsakis,` `@tmandry,` `@traviscross.` Thanks also to `@spastorino,` `@cjgillot` (for changes to opaque captures!), `@oli-obk` for many reviews, and many other contributors and issue-filers. Apologies if I left your name off 😺
const-eval: make misalignment a hard error
It's been a future-incompat error (showing up in cargo's reports) since https://github.com/rust-lang/rust/pull/104616, Rust 1.68, released in March. That should be long enough.
The question for the lang team is simply -- should we move ahead with this, making const-eval alignment failures a hard error? (It turns out some of them accidentally already were hard errors since #104616. But not all so this is still a breaking change. Crater found no regression.)
Fix duplicate note on internal feature gates with associated issues
Fixes#116293
Note sure if I should add tests because the issue occurs only for feature gates having associated issues and that set of feature gates will change unpredictably leading to an unnecessary churn in tests.
The BuiltinInternalFeatures gate already has a struct level #[note]
attribute. The additional note field in it caused a duplicate to be
displayed when it was set to Some(...) which happened when the
feature had an associated issue
Fix overflow checking in range patterns
When a range pattern contains an overflowing literal, if we're not careful we might not notice the overflow and use the wrapped value. This makes for confusing error messages because linting against overflowing literals is only done in a later pass. So when a range is invalid we check for overflows to provide a better error.
This check didn't use to handle negative types; this PR fixes that. First commit adds tests, second cleans up without changing behavior, third does the fix.
EDIT: while I was at it, I fixed a small annoyance about the span of the overflow lint on negated literals.
Fixes https://github.com/rust-lang/rust/issues/94239
Clarify `invalid_reference_casting` lint around interior mutable types
This is PR intends to clarify the `invalid_reference_casting` lint around interior mutable types by adding a note for them saying that they should go through `UnsafeCell::get`.
So for this code:
```rust
let cell = &std::cell::UnsafeCell::new(0);
let _num = &mut *(cell as *const _ as *mut i32);
```
the following note will be added to the lint output:
```diff
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:68:16
|
LL | let _num = &mut *(cell as *const _ as *mut i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html>
+ = note: even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`
```
Suggestion are welcome around the note contents.
Fixes https://github.com/rust-lang/rust/issues/116410
cc `@RalfJung`
non_lifetime_binders: fix ICE in lint opaque-hidden-inferred-bound
Opaque types like `impl for<T> Trait<T>` would previously lead to an ICE.
r? `@compiler-errors`
We're stabilizing `async fn` in trait (AFIT), but we have some
reservations about how people might use this in the definitions of
publicly-visible traits, so we're going to lint about that.
This is a bit of an odd lint for `rustc`. We normally don't lint just
to have people confirm that they understand how Rust works. But in
this one exceptional case, this seems like the right thing to do as
compared to the other plausible alternatives.
In this commit, we describe the nature of this odd lint.
Fix `noop_method_call` detection
This needs to be merged before #116198 can compile. The error occurs before the compiler is built so this needs to be a separate PR.
Simplify some of the logic in the `invalid_reference_casting` lint
This PR simplifies 2 areas of the logic for the `invalid_reference_casting` lint:
- The init detection: we now use the newly added `expr_or_init` function instead of a manual detection
- The ref-to-mut-ptr casting detection logic: I simplified this logic by caring less hardly about the order of the casting operations
Those two simplifications permits us to detect more cases, as can be seen in the test output changes.
Improve invalid UTF-8 lint by finding the expression initializer
This PR introduce a small mechanism to walk up the HIR through bindings, if/else, consts, ... when trying lint on invalid UTF-8.
Fixes https://github.com/rust-lang/rust/issues/115208
Make useless_ptr_null_checks smarter about some std functions
This teaches the `useless_ptr_null_checks` lint that some std functions can't ever return null pointers, because they need to point to valid data, get references as input, etc.
This is achieved by introducing an `#[rustc_never_returns_null_ptr]` attribute and adding it to these std functions (gated behind bootstrap `cfg_attr`).
Later on, the attribute could maybe be used to tell LLVM that the returned pointer is never null. I don't expect much impact of that though, as the functions are pretty shallow and usually the input data is already never null.
Follow-up of PR #113657Fixes#114442
Improve invalid let expression handling
- Move all of the checks for valid let expression positions to parsing.
- Add a field to ExprKind::Let in AST/HIR to mark whether it's in a valid location.
- Suppress some later errors and MIR construction for invalid let expressions.
- Fix a (drop) scope issue that was also responsible for #104172.
Fixes#104172Fixes#104868
Don't ICE when computing ctype's `repr_nullable_ptr` for possibly-unsized ty
We may not always be able to compute the layout of a type like `&T` when `T: ?Sized`, even if we're able to estimate its size skeleton.
r? davidtwco
Fixes#115628
There was an incomplete version of the check in parsing and a second
version in AST validation. This meant that some, but not all, invalid
uses were allowed inside macros/disabled cfgs. It also means that later
passes have a hard time knowing when the let expression is in a valid
location, sometimes causing ICEs.
- Add a field to ExprKind::Let in AST/HIR to mark whether it's in a
valid location.
- Suppress later errors and MIR construction for invalid let
expressions.
Call `LateLintPass::check_attribute` from `with_lint_attrs`
Fixes#115571
For regular `register_late_pass` lints also means that `last_node_with_lint_attrs` is correct when in `check_attribute`, I've added a test that previously failed for `clippy::allow_attributes`
As far as I can see the only late lint in rustc that uses `check_attribute` is `unstable_features` which is allow by default and deprecated so this is mostly for clippy (or future rustc lints)
The lint panicked for an input like 'extern "C" fn(Option<&<T as FooTrait>::FooType>)' because the type T therein cannot be normalized. The normalization failure caused SizeSkeleton::compute() to return an error and trigger a panic in the unwrap().
Lint on invalid usage of `UnsafeCell::raw_get` in reference casting
This PR proposes to take into account `UnsafeCell::raw_get` method call for non-Freeze types for the `invalid_reference_casting` lint.
The goal of this is to catch those kind of invalid reference casting:
```rust
fn as_mut<T>(x: &T) -> &mut T {
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
}
```
r? `@est31`
refactor(lint): translate `RenamedOrRemovedLint`
I was trying to address <https://github.com/rust-lang/cargo/issues/12495> and found that maybe I should refactor relevant lints a bit.
This PR translates `RenamedOrRemovedLint` into fluent file. To make diagnostic types clearer and easier to organize, this PR splits it into two structs.
The second commit adds lifetime annotations for removing unnecessary clones. If people feel too noisy, we can revert such change.
### Possibly relevant UI tests:
* `tests/ui/lint-removed*`
* `tests/ui/lint-renamed*`
* `tests/ui/rustdoc-renamed.rs`
* `tests/rustdoc-ui/lints/unknown-renamed-lints.rs`
Add support for `ptr::write`s for the `invalid_reference_casting` lint
This PR adds support for `ptr::write` and others for the `invalid_reference_casting` lint.
Detecting instances where instead of using the deref (`*`) operator to assign someone uses `ptr::write`, `ptr::write_unaligned` or `ptr::write_volatile`.
```rust
let data_len = 5u64;
std::ptr::write(
std::mem::transmute::<*const u64, *mut u64>(&data_len),
new_data_len,
);
```
r? ``@est31``
Warn on elided lifetimes in associated constants (`ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT`)
Elided lifetimes in associated constants (in impls) erroneously resolve to fresh lifetime parameters on the impl since #97313. This is not correct behavior (see #38831).
I originally opened #114716 to fix this, but given the time that has passed, the crater results seem pretty bad: https://github.com/rust-lang/rust/pull/114716#issuecomment-1682091952
This PR alternatively implements a lint against this behavior, and I'm hoping to bump this to deny in a few versions.
Also consider `mem::transmute` with the `invalid_reference_casting` lint
This PR extend the `invalid_reference_casting` lint with regard to the `std::mem::transmute` function.
```
error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
--> $DIR/reference_casting.rs:27:16
|
LL | let _num = &mut *std::mem::transmute::<_, *mut i32>(&num);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
*I encourage anyone reviewing this PR to do so [without whitespaces](https://github.blog/2011-10-21-github-secrets/#whitespace).*
rustc: Move `features` from `Session` to `GlobalCtxt`
Removes one more piece of mutable state.
Follow up to #114622.
The rule I used for passing feature in function signatures:
- if a crate already depends on `rustc_middle`, then `Session` is replaced with `TyCtxt`
- otherwise session and features are passed as a pair `sess: &Session, features: &Features`
The code in `rustc_lint` is ultimately used for implementing a trait from `rustc_expand`, so it also doesn't use tcx despite the dependency on `rustc_middle`.
Avoid invalid NaN lint machine-applicable suggestion in const context
This PR removes the machine-applicable suggestion in const context for the `invalid_nan_comparision` lint ~~and replace it with a simple help~~.
Fixes https://github.com/rust-lang/rust/issues/114471
Convert builtin "global" late lints to run per module
The compiler currently has 4 non-incremental lints:
1. `clashing_extern_declarations`;
2. `missing_debug_implementations`;
3. ~`unnameable_test_items`;~ changed by https://github.com/rust-lang/rust/pull/114414
4. `missing_docs`.
Non-incremental lints get reexecuted for each compilation, which is slow. Moreover, those lints are allow-by-default, so run for nothing most of the time. This PR attempts to make them more incremental-friendly.
`clashing_extern_declarations` is moved to a standalone query.
`missing_debug_implementation` can use `non_blanket_impls_for_ty` instead of recomputing it.
`missing_docs` is harder as it needs to track if there is a `doc(hidden)` module surrounding. I hack around this using the lint level engine. That's easy to implement and allows to re-enable the lint for a re-exported module, while a more proper solution would reuse the same device as `unnameable_test_items`.
Add separate feature gate for async fn track caller
This patch adds a feature gate `async_fn_track_caller` that is separate from `closure_track_caller`. This is to allow enabling `async_fn_track_caller` separately.
Fixes#110009
Improve spans for indexing expressions
fixes#114388
Indexing is similar to method calls in having an arbitrary left-hand-side and then something on the right, which is the main part of the expression. Method calls already have a span for that right part, but indexing does not. This means that long method chains that use indexing have really bad spans, especially when the indexing panics and that span in coverted into a panic location.
This does the same thing as method calls for the AST and HIR, storing an extra span which is then put into the `fn_span` field in THIR.
r? compiler-errors
Indexing is similar to method calls in having an arbitrary
left-hand-side and then something on the right, which is the main part
of the expression. Method calls already have a span for that right part,
but indexing does not. This means that long method chains that use
indexing have really bad spans, especially when the indexing panics and
that span in coverted into a panic location.
This does the same thing as method calls for the AST and HIR, storing an
extra span which is then put into the `fn_span` field in THIR.
Add `internal_features` lint
Implements https://github.com/rust-lang/compiler-team/issues/596
Also requires some more test blessing for codegen tests etc
`@jyn514` had the idea of just `allow`ing the lint by default in the test suite. I'm not sure whether this is a good idea, but it's definitely one worth considering. Additional input encouraged.
Expand, rename and improve `incorrect_fn_null_checks` lint
This PR,
- firstly, expand the lint by now linting on references
- secondly, it renames the lint `incorrect_fn_null_checks` -> `useless_ptr_null_checks`
- and thirdly it improves the lint by catching `ptr::from_mut`, `ptr::from_ref`, as well as `<*mut _>::cast` and `<*const _>::cast_mut`
Fixes https://github.com/rust-lang/rust/issues/113601
cc ```@est31```
It lints against features that are inteded to be internal to the
compiler and standard library. Implements MCP #596.
We allow `internal_features` in the standard library and compiler as those
use many features and this _is_ the standard library from the "internal to the compiler and
standard library" after all.
Marking some features as internal wasn't exactly the most scientific approach, I just marked some
mostly obvious features. While there is a categorization in the macro,
it's not very well upheld (should probably be fixed in another PR).
We always pass `-Ainternal_features` in the testsuite
About 400 UI tests and several other tests use internal features.
Instead of throwing the attribute on each one, just always allow them.
There's nothing wrong with testing internal features^^
This patch adds a feature gate `async_fn_track_caller` that is separate from `closure_track_caller`. This is to allow enabling `async_fn_track_caller` separately.
Fixes#110009
Improve `invalid_reference_casting` lint
This PR is a follow-up to https://github.com/rust-lang/rust/pull/111567 and https://github.com/rust-lang/rust/pull/113422.
This PR does multiple things:
- First it adds support for deferred de-reference, the goal is to support code like this, where the casting and de-reference are not done on the same expression
```rust
let myself = self as *const Self as *mut Self;
*myself = Self::Ready(value);
```
- Second it does not lint anymore on SB/TB UB code by only checking assignments (`=`, `+=`, ...) and creation of mutable references `&mut *`
- Thirdly it greatly improves the diagnostics in particular for cast from `&mut` to `&mut` or assignments
- ~~And lastly it renames the lint from `cast_ref_to_mut` to `invalid_reference_casting` which is more consistent with the ["rules"](https://github.com/rust-lang/rust-clippy/issues/2845) and also more consistent with what the lint checks~~ *https://github.com/rust-lang/rust/pull/113422*
This PR is best reviewed commit by commit.
r? compiler
Rename and allow `cast_ref_to_mut` lint
This PR is a small subset of https://github.com/rust-lang/rust/pull/112431, that is the renaming of the lint (`cast_ref_to_mut` -> `invalid_reference_casting`).
BUT also temporarily change the default level of the lint from deny-by-default to allow-by-default until https://github.com/rust-lang/rust/pull/112431 is merged.
r? `@Nilstrieb`
fix(resolve): update the ambiguity glob binding as warning recursively
Fixes#47525Fixes#56593, but `issue-56593-2.rs` is not fixed to ensure backward compatibility.
Fixes#98467Fixes#105235Fixes#112713
This PR had added a field called `warn_ambiguous` in `NameBinding` which is only for back compatibly reason and used for lint.
More details: https://github.com/rust-lang/rust/pull/112743
r? `@petrochenkov`
lint/ctypes: fix `()` return type checks
Fixes#113436.
`()` is normally FFI-unsafe, but is FFI-safe when used as a return type. It is also desirable that a transparent newtype for `()` is FFI-safe when used as a return type.
In order to support this, when a type was deemed FFI-unsafe, because of a `()` type, and was used in return type - then the type was considered FFI-safe. However, this was the wrong approach - it didn't check that the `()` was part of a transparent newtype! The consequence of this is that the presence of a `()` type in a more complex return type would make it the entire type be considered safe (as long as the `()` type was the first that the lint found) - which is obviously incorrect.
Instead, this logic is removed, and after [consultation with t-lang](https://github.com/rust-lang/rust/issues/113436#issuecomment-1640756721), I've fixed the bugs and inconsistencies and made `()` FFI-safe within types.
I also refactor a function, but that's not too exciting.
Now that this lint runs on any external-ABI fn-ptr, normalization won't
always succeed, so use `try_normalize_erasing_regions` instead.
Signed-off-by: David Wood <david@davidtw.co>
Consider `()` within types to be FFI-safe, and `()` to be FFI-safe as a
return type (incl. when in a transparent newtype).
Signed-off-by: David Wood <david@davidtw.co>
`()` is normally FFI-unsafe, but is FFI-safe when used as a return type.
It is also desirable that a transparent newtype for `()` is FFI-safe when
used as a return type.
In order to support this, when an type was deemed FFI-unsafe, because of
a `()` type, and was used in return type - then the type was considered
FFI-safe. However, this was the wrong approach - it didn't check that the
`()` was part of a transparent newtype! The consequence of this is that
the presence of a `()` type in a more complex return type would make it
the entire type be considered safe (as long as the `()` type was the
first that the lint found) - which is obviously incorrect.
Instead, this logic is removed, and a unit return type or a transparent
wrapper around a unit is checked for directly for functions and fn-ptrs.
Signed-off-by: David Wood <david@davidtw.co>
Fix removal span calculation of `unused_qualifications` suggestion
Given a path such as `std::ops::Index<str>`, calculate the unnecessary qualification removal span by computing the beginning of the entire span until the ident span of the last path segment, which handles generic arguments and lifetime arguments in the last path segment. Previous logic only kept the ident span of the last path segment which is incorrect.
Closes#113808.
Uplift `clippy::fn_null_check` lint
This PR aims at uplifting the `clippy::fn_null_check` lint into rustc.
## `incorrect_fn_null_checks`
(warn-by-default)
The `incorrect_fn_null_checks` lint checks for expression that checks if a function pointer is null.
### Example
```rust
let fn_ptr: fn() = /* somehow obtained nullable function pointer */
if (fn_ptr as *const ()).is_null() { /* ... */ }
```
### Explanation
Function pointers are assumed to be non-null, checking for their nullity is incorrect.
-----
Mostly followed the instructions for uplifting a clippy lint described here: https://github.com/rust-lang/rust/pull/99696#pullrequestreview-1134072751
`@rustbot` label: +I-lang-nominated
r? compiler
Remove chalk support from the compiler
Removes chalk (`-Ztrait-solver=chalk`) from the compiler and prunes any dead code resulting from this, mainly:
* Remove the chalk compatibility layer in `compiler/rustc_traits/src/chalk`
* Remove the chalk flag `-Ztrait-solver=chalk` and its `TraitEngine` implementation
* Remove `TypeWellFormedFromEnv` (and its many `bug!()` match arms)
* Remove the chalk migration mode from compiletest
* Remove the `chalkify` UI tests (do we want to keep any of these, but migrate them to `-Ztrait-solver=next`??)
Fulfills rust-lang/types-team#93.
r? `@jackh726`
Extend previous checks for external ABI fn-ptrs to use in internal
statics, constants, type aliases and algebraic data types.
Signed-off-by: David Wood <david.wood@huawei.com>
Extend previous commit's support for checking for external fn-ptrs in
internal fn types to report errors for multiple found fn-ptrs.
Signed-off-by: David Wood <david.wood@huawei.com>
Instead of skipping functions with internal ABIs, check that the
signature doesn't contain any fn-ptr types with external ABIs that
aren't FFI-safe.
Signed-off-by: David Wood <david.wood@huawei.com>
Extend `unused_must_use` to cover block exprs
Given code like
```rust
#[must_use]
fn foo() -> i32 {
42
}
fn warns() {
{
foo();
}
}
fn does_not_warn() {
{
foo()
};
}
fn main() {
warns();
does_not_warn();
}
```
### Before This PR
```
warning: unused return value of `foo` that must be used
--> test.rs:8:9
|
8 | foo();
| ^^^^^
|
= note: `#[warn(unused_must_use)]` on by default
help: use `let _ = ...` to ignore the resulting value
|
8 | let _ = foo();
| +++++++
warning: 1 warning emitted
```
### After This PR
```
warning: unused return value of `foo` that must be used
--> test.rs:8:9
|
8 | foo();
| ^^^^^
|
= note: `#[warn(unused_must_use)]` on by default
help: use `let _ = ...` to ignore the resulting value
|
8 | let _ = foo();
| +++++++
warning: unused return value of `foo` that must be used
--> test.rs:14:9
|
14 | foo()
| ^^^^^
|
help: use `let _ = ...` to ignore the resulting value
|
14 | let _ = foo();
| +++++++ +
warning: 2 warnings emitted
```
Fixes#104253.
This commit reverts a change made in #111425.
It was believed that this change was necessary for implementing type privacy lints, but #111801 showed that it was not necessary.
Quite opposite, the revert fixes some issues.
This is apparently where it's busting stack, and the comments for `ensure_sufficient_stack` say that
> E.g. almost any call to visit_expr or equivalent can benefit from this.
Uplift `clippy::cmp_nan` lint
This PR aims at uplifting the `clippy::cmp_nan` lint into rustc.
## `invalid_nan_comparisons`
~~(deny-by-default)~~ (warn-by-default)
The `invalid_nan_comparisons` lint checks comparison with `f32::NAN` or `f64::NAN` as one of the operand.
### Example
```rust,compile_fail
let a = 2.3f32;
if a == f32::NAN {}
```
### Explanation
NaN does not compare meaningfully to anything – not even itself – so those comparisons are always false.
-----
Mostly followed the instructions for uplifting a clippy lint described here: https://github.com/rust-lang/rust/pull/99696#pullrequestreview-1134072751
`@rustbot` label: +I-lang-nominated
r? compiler
Rollup of 3 pull requests
Successful merges:
- #112260 (Improve document of `unsafe_code` lint)
- #112429 ([rustdoc] List matching impls on type aliases)
- #112442 (Deduplicate identical region constraints in new solver)
r? `@ghost`
`@rustbot` modify labels: rollup
Uplift `clippy::undropped_manually_drops` lint
This PR aims at uplifting the `clippy::undropped_manually_drops` lint.
## `undropped_manually_drops`
(warn-by-default)
The `undropped_manually_drops` lint check for calls to `std::mem::drop` with a value of `std::mem::ManuallyDrop` which doesn't drop.
### Example
```rust
struct S;
drop(std::mem::ManuallyDrop::new(S));
```
### Explanation
`ManuallyDrop` does not drop it's inner value so calling `std::mem::drop` will not drop the inner value of the `ManuallyDrop` either.
-----
Mostly followed the instructions for uplifting an clippy lint described here: https://github.com/rust-lang/rust/pull/99696#pullrequestreview-1134072751
`@rustbot` label: +I-lang-nominated
r? compiler
-----
For Clippy:
changelog: Moves: Uplifted `clippy::undropped_manually_drops` into rustc
Extra context for unreachable_pub lint
While experienced Rustaceans no doubt know this sort of thing already, as more of a newbie I had trouble understanding why I was triggering the lint. Hopefully this expanded explanation saves someone else some head-scratching.
Fixes#110922
Uplift `clippy::invalid_utf8_in_unchecked` lint
This PR aims at uplifting the `clippy::invalid_utf8_in_unchecked` lint into two lints.
## `invalid_from_utf8_unchecked`
(deny-by-default)
The `invalid_from_utf8_unchecked` lint checks for calls to `std::str::from_utf8_unchecked` and `std::str::from_utf8_unchecked_mut` with an invalid UTF-8 literal.
### Example
```rust
unsafe {
std::str::from_utf8_unchecked(b"cl\x82ippy");
}
```
### Explanation
Creating such a `str` would result in undefined behavior as per documentation for `std::str::from_utf8_unchecked` and `std::str::from_utf8_unchecked_mut`.
## `invalid_from_utf8`
(warn-by-default)
The `invalid_from_utf8` lint checks for calls to `std::str::from_utf8` and `std::str::from_utf8_mut` with an invalid UTF-8 literal.
### Example
```rust
std::str::from_utf8(b"ru\x82st");
```
### Explanation
Trying to create such a `str` would always return an error as per documentation for `std::str::from_utf8` and `std::str::from_utf8_mut`.
-----
Mostly followed the instructions for uplifting a clippy lint described here: https://github.com/rust-lang/rust/pull/99696#pullrequestreview-1134072751
````@rustbot```` label: +I-lang-nominated
r? compiler
-----
For Clippy:
changelog: Moves: Uplifted `clippy::invalid_utf8_in_unchecked` into rustc
Each of `{D,Subd}iagnosticMessage::{Str,Eager}` has a comment:
```
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
```
This commit answers that question in the affirmative. It's not the most
compelling change ever, but it might be worth merging.
This requires changing the `impl<'a> From<&'a str>` impls to `impl
From<&'static str>`, which involves a bunch of knock-on changes that
require/result in call sites being a little more precise about exactly
what kind of string they use to create errors, and not just `&str`. This
will result in fewer unnecessary allocations, though this will not have
any notable perf effects given that these are error paths.
Note that I was lazy within Clippy, using `to_string` in a few places to
preserve the existing string imprecision. I could have used `impl
Into<{D,Subd}iagnosticMessage>` in various places as is done in the
compiler, but that would have required changes to *many* call sites
(mostly changing `&format("...")` to `format!("...")`) which didn't seem
worthwhile.
Add warn-by-default lint when local binding shadows exported glob re-export item
This PR introduces a warn-by-default rustc lint for when a local binding (a use statement, or a type declaration) produces a name which shadows an exported glob re-export item, causing the name from the exported glob re-export to be hidden (see #111336).
### Unresolved Questions
- [x] ~~Is this approach correct? While it passes the UI tests, I'm not entirely convinced it is correct.~~ Seems to be ok now.
- [x] ~~What should the lint be called / how should it be worded? I don't like calling `use x::*;` or `struct Foo;` a "local binding" but they are `NameBinding`s internally if I'm not mistaken.~~ ~~The lint is called `local_binding_shadows_glob_reexport` for now, unless a better name is suggested.~~ `hidden_glob_reexports`.
Fixes#111336.
Ensure Fluent messages are in alphabetical order
Fixes#111847
This adds a tidy check to ensure Fluent messages are in alphabetical order, as well as sorting all existing messages. I think the error could be worded better, would appreciate suggestions.
<details>
<summary>Script used to sort files</summary>
```py
import sys
import re
fn = sys.argv[1]
with open(fn, 'r') as f:
data = f.read().split("\n")
chunks = []
cur = ""
for line in data:
if re.match(r"^([a-zA-Z0-9_]+)\s*=\s*", line):
chunks.append(cur)
cur = ""
cur += line + "\n"
chunks.append(cur)
chunks.sort()
with open(fn, 'w') as f:
f.write(''.join(chunks).strip("\n\n") + "\n")
```
</details>
Consider lint check attributes on match arms
Currently, lint check attributes on match arms have no effect for some lints. This PR makes some lint passes to take those attributes into account.
- `LateContextAndPass` for late lint doesn't update `last_node_with_lint_attrs` when it visits match arms. This leads to lint check attributes on match arms taking no effects on late lints that operate on the arms' pattern:
```rust
match value {
#[deny(non_snake_case)]
PAT => {} // `non_snake_case` only warned due to default lint level
}
```
To be honest, I'm not sure whether this is intentional or just an oversight. I've dug the implementation history and searched up issues/PRs but couldn't find any discussion on this.
- `MatchVisitor` doesn't update its lint level when it visits match arms. This leads to check lint attributes on match arms taking no effect on some lints handled by this visitor, namely: `bindings_with_variant_name` and `irrefutable_let_patterns`.
This seems to be a fallout from #108504. Before 05082f57af, when the visitor operated on HIR rather than THIR, check lint attributes for the said lints were effective. [This playground][play] compiles successfully on current stable (1.69) but fails on current beta and nightly.
I wasn't sure where best to place the test for this. Let me know if there's a better place.
[play]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=38432b79e535cb175f8f7d6d236d29c3
[play-match]: https://play.rust-lang.org/?version=beta&mode=debug&edition=2021&gist=629aa71b7c84b269beadeba664e2221d
Dont check `must_use` on nested `impl Future` from fn
Fixes (but does not close, per beta policy) #111484
Also fixes a `FIXME` left in the code about (presumably) false-positives on non-async `#[must_use] fn() -> impl Future` cases, though if that's not desirable to include in the beta backport then I can certainly revert it.
Beta nominating as it fixes a beta ICE.
Document that `missing_copy_implementations` and `missing_debug_implementations` only apply to public items.
I encountered #111359 (fixed) and noticed that the documentation didn't say that it was _intended_ that `missing_debug_implementations` only applies to public items. This PR fixes that, and makes the same wording change to `missing_copy_implementations` which has the same condition.
I chose the words to also be similar to `missing_docs` which already had such a remark.
Introduce `DynSend` and `DynSync` auto trait for parallel compiler
part of parallel-rustc #101566
This PR introduces `DynSend / DynSync` trait and `FromDyn / IntoDyn` structure in rustc_data_structure::marker. `FromDyn` can dynamically check data structures for thread safety when switching to parallel environments (such as calling `par_for_each_in`). This happens only when `-Z threads > 1` so it doesn't affect single-threaded mode's compile efficiency.
r? `@cjgillot`
Uplift `clippy::{drop,forget}_{ref,copy}` lints
This PR aims at uplifting the `clippy::drop_ref`, `clippy::drop_copy`, `clippy::forget_ref` and `clippy::forget_copy` lints.
Those lints are/were declared in the correctness category of clippy because they lint on useless and most probably is not what the developer wanted.
## `drop_ref` and `forget_ref`
The `drop_ref` and `forget_ref` lint checks for calls to `std::mem::drop` or `std::mem::forget` with a reference instead of an owned value.
### Example
```rust
let mut lock_guard = mutex.lock();
std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex
// still locked
operation_that_requires_mutex_to_be_unlocked();
```
### Explanation
Calling `drop` or `forget` on a reference will only drop the reference itself, which is a no-op. It will not call the `drop` or `forget` method on the underlying referenced value, which is likely what was intended.
## `drop_copy` and `forget_copy`
The `drop_copy` and `forget_copy` lint checks for calls to `std::mem::forget` or `std::mem::drop` with a value that derives the Copy trait.
### Example
```rust
let x: i32 = 42; // i32 implements Copy
std::mem::forget(x) // A copy of x is passed to the function, leaving the
// original unaffected
```
### Explanation
Calling `std::mem::forget` [does nothing for types that implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the value will be copied and moved into the function on invocation.
-----
Followed the instructions for uplift a clippy describe here: https://github.com/rust-lang/rust/pull/99696#pullrequestreview-1134072751
cc `@m-ou-se` (as T-libs-api leader because the uplifting was discussed in a recent meeting)
While experienced Rustaceans no doubt know this sort of thing already, as more of a newbie I had trouble understanding why I was triggering the lint.
Hopefully this expanded explanation saves someone else some head-scratching.
Introduce `AliasKind::Inherent` for inherent associated types
Allows us to check (possibly generic) inherent associated types for well-formedness.
Type inference now also works properly.
Follow-up to #105961. Supersedes #108430.
Fixes#106722.
Fixes#108957.
Fixes#109768.
Fixes#109789.
Fixes#109790.
~Not to be merged before #108860 (`AliasKind::Weak`).~
CC `@jackh726`
r? `@compiler-errors`
`@rustbot` label T-types F-inherent_associated_types
Emit while_true lint spanning the entire loop condition
The lint that suggests `loop {}` instead of `while true {}` has functionality to 'pierce' parenthesis in cases like `while (true) {}`. In these cases, the emitted span only went to the hi of the `true` itself, not spanning the entire loop condition.
Before:
```
warning: denote infinite loops with `loop { ... }`
--> /tmp/foobar.rs:2:5
|
2 | while ((((((true)))))) {}
| ^^^^^^^^^^^^^^^^ help: use `loop`
|
= note: `#[warn(while_true)]` on by default
```
After:
```
warning: denote infinite loops with `loop { ... }`
--> /tmp/foobar.rs:2:5
|
2 | while ((((((true)))))) {}
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `loop`
|
= note: `#[warn(while_true)]` on by default
```
This is especially a problem for rustfix.
added TraitAlias to check_item() for missing_docs
As in issue #111025 the `missing_docs` was not being triggered for trait aliases. I added `TraitAlias` to the pattern match for check_item(), and the lint seems to be behaving appropriately
The lint that suggests `loop {}` instead of `while true {}` has functionality to 'pierce' parenthesis
in cases like `while (true) {}`. In these cases, the emitted span only went to the hi of the `true`
itself, not spanning the entire loop condition.
Before:
```
warning: denote infinite loops with `loop { ... }`
--> /tmp/foobar.rs:2:5
|
2 | while ((((((true)))))) {}
| ^^^^^^^^^^^^^^^^ help: use `loop`
|
= note: `#[warn(while_true)]` on by default
```
After:
```
warning: denote infinite loops with `loop { ... }`
--> /tmp/foobar.rs:2:5
|
2 | while ((((((true)))))) {}
| ^^^^^^^^^^^^^^^^^^^^^^ help: use `loop`
|
= note: `#[warn(while_true)]` on by default
```