This query has a name that sounds general-purpose, but in fact it has
coverage-specific semantics, and (fortunately) is only used by coverage code.
Because it is only ever called once (from one designated CGU), it doesn't need
to be a query, and we can change it to a regular function instead.
When the number of type parameters in the associated function of an impl
and its trait differ, we now *always* point at the trait one, even if it
comes from a foreign crate. When it is local, we point at the specific
params, when it is foreign, we point at the whole associated item.
Fix#69944.
When encountering a binding that isn't found but has a typo suggestion
for a binding with a leading underscore, suggest changing the binding
definition instead of the use place.
Fix#60164.
Move where doc comment meant as comment check
The new place makes more sense and covers more cases beyond individual statements.
```
error: expected one of `.`, `;`, `?`, `else`, or an operator, found doc comment `//!foo
--> $DIR/doc-comment-in-stmt.rs:25:22
|
LL | let y = x.max(1) //!foo
| ^^^^^^ expected one of `.`, `;`, `?`, `else`, or an operator
|
help: add a space before `!` to write a regular comment
|
LL | let y = x.max(1) // !foo
| +
```
Fix#65329.
Uplift movability and mutability, the simple way
Just make type_ir a dependency of ast. This can be relaxed later if we want to make the dependency less heavy. Part of rust-lang/types-team#124.
r? `@lcnr` or `@jackh726`
The new place makes more sense and covers more cases beyond individual
statements.
```
error: expected one of `.`, `;`, `?`, `else`, or an operator, found doc comment `//!foo
--> $DIR/doc-comment-in-stmt.rs:25:22
|
LL | let y = x.max(1) //!foo
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected one of `.`, `;`, `?`, `else`, or an operator
|
help: add a space before `!` to write a regular comment
|
LL | let y = x.max(1) // !foo
| +
```
Fix#65329.
Fix duplicate labels emitted in `render_multispan_macro_backtrace()`
This PR replaces the `Vec` used to store labels with an `FxIndexSet` in order to eliminate duplicates
Fixes#116836
The `Instance::body()` returns a monomorphized body.
For that, we had to implement visitor that monomorphize types and
constants. We are also introducing the RustcInternal trait that will
allow us to convert back from Stable to Internal.
Note that this trait is not yet visible for our users as it depends on
Tables. We should probably add a new trait that can be exposed.
Implement rustc part of RFC 3127 trim-paths
This PR implements (or at least tries to) [RFC 3127 trim-paths](https://github.com/rust-lang/rust/issues/111540), the rustc part. That is `-Zremap-path-scope` with all of it's components/scopes.
`@rustbot` label: +F-trim-paths
This commit improves warnings emitted for malformed on unimplemented
attributes by:
* Improving the span of the warnings
* Adding a label message to them
* Separating the messages for missing and unexpected options
* Adding a help message that says which options are supported
Use v0.0.0 in compiler crates
I may be totally off base here, but my understanding is that it's conventional to use v0.0.0 to reflect the unversioned nature of the compiler crates. Fix that for some of the compiler crates that were created recently.
Don't ICE when encountering unresolved regions in `fully_resolve`
We can encounter unresolved regions due to unconstrained impl lifetime arguments because `collect_return_position_impl_trait_in_trait_tys` runs before WF actually checks that the impl is well-formed.
Fixes#116525
Bump `COINDUCTIVE_OVERLAP_IN_COHERENCE` to deny + warn in deps
1.73 is the first place this shows up in stable (recall that there was only 1 regression), so let's bump this to deny on nightly.
r? lcnr
coverage: Move most per-function coverage info into `mir::Body`
Currently, all of the coverage information collected by the `InstrumentCoverage` pass is smuggled through MIR in the form of individual `StatementKind::Coverage` statements, which must then be reassembled by coverage codegen.
That's awkward for a number of reasons:
- While some of the coverage statements do care about their specific position in the MIR control-flow graph, many of them don't, and are just tacked onto the function's first BB as metadata carriers.
- MIR inlining can result in coverage statements being duplicated, so coverage codegen has to jump through hoops to avoid emitting duplicate mappings.
- MIR optimizations that would delete coverage statements need to carefully copy them into the function's first BB so as not to omit them from coverage reports.
- The order in which coverage codegen sees coverage statements is dependent on MIR optimizations/inlining, which can cause unnecessary churn in the emitted coverage mappings.
- We don't have a good way to annotate MIR-level functions with extra coverage info that doesn't belong in a statement.
---
This PR therefore takes most of the per-function coverage info and stores it in a field in `mir::Body` as `Option<Box<FunctionCoverageInfo>>`.
(This adds one pointer to the size of `mir::Body`, even when coverage is not enabled.)
Coverage statements still need to be injected into MIR in some cases, but only when they actually affect codegen (counters) or are needed to detect code that has been optimized away as unreachable (counters/expressions).
---
By the end of this PR, the information stored in `FunctionCoverageInfo` is:
- A hash of the function's source code (needed by LLVM's coverage map format)
- The number of coverage counters added by coverage instrumentation
- A table of coverage expressions, associating each expression ID with its operator (add or subtract) and its two operands
- The list of mappings, associating each covered code region with a counter/expression/zero value
---
~~This is built on top of #115301, so I'll rebase and roll a reviewer once that lands.~~
r? `@ghost`
`@rustbot` label +A-code-coverage
Removes the backwards-compatible `LinkSelfContainedDefault`, by
incorporating the remaining specifics into `LinkSelfContained`.
Then renames the modern options to keep the old name.
This new description reflects the changes made in this PR, and should hopefully
be more useful to non-coverage developers who need to care about coverage
statements.
Even though expression details are now stored in the info structure, we still
need to inject `ExpressionUsed` statements into MIR, because if one is missing
during codegen then we know that it was optimized out and we can remap all of
its associated code regions to zero.
Previously, mappings were attached to individual coverage statements in MIR.
That necessitated special handling in MIR optimizations to avoid deleting those
statements, since otherwise codegen would be unable to reassemble the original
list of mappings.
With this change, a function's list of mappings is now attached to its MIR
body, and survives intact even if individual statements are deleted by
optimizations.
this ensures roundtripping of stable and unstable values:
- backwards-compatible values can be deserialized, as well as the new
unstable values
- unstable values are serialized.
Instead of modifying the accumulated expressions in-place, we now build a set
of expressions that are known to be zero, and then consult that set on the fly
when converting the expression data for FFI.
This will be necessary when moving mappings and expression data into function
coverage info, which can't be mutated during codegen.
Don't compare host param by name
Seems sketchy to be searching for `sym::host` by name, especially when we can get the actual index with not very much work.
r? fee1-dead
Coverage codegen can now allocate arrays based on the number of
counters/expressions originally used by the instrumentor.
The existing query that inspects coverage statements is still used for
determining the number of counters passed to `llvm.instrprof.increment`. If
some high-numbered counters were removed by MIR optimizations, the instrumented
binary can potentially use less memory and disk space at runtime.
This allows coverage information to be attached to the function as a whole when
appropriate, instead of being smuggled through coverage statements in the
function's basic blocks.
As an example, this patch moves the `function_source_hash` value out of
individual `CoverageKind::Counter` statements and into the per-function info.
When synthesizing unused functions for coverage purposes, the absence of this
info is taken to indicate that a function was not eligible for coverage and
should not be synthesized.
Remove lots of generics from `ty::print`
All of these generics mostly resolve to the same thing, which means we can remove them, greatly simplifying the types involved in pretty printing and unlocking another simplification (that is not performed in this PR): Using `&mut self` instead of passing `self` through the return type.
cc `@eddyb` you probably know why it's like this, just checking in and making sure I didn't do anything bad
r? oli-obk
Use `YYYY-MM-DDTHH_MM_SS` as datetime format for ICE dump files
Windows paths do not support `:`, so use a datetime format in ICE dump paths that Windows will accept.
CC #116809, fix#115180.
Remove `IdFunctor` trait.
It's defined in `rustc_data_structures` but is only used in
`rustc_type_ir`. The code is shorter and easier to read if we remove
this layer of abstraction and just do the things directly where they are
needed.
r? `@BoxyUwU`
Implement an internal lint encouraging use of `Span::eq_ctxt`
Adds a new Rustc internal lint that forbids use of `.ctxt() == .ctxt()` for spans, encouraging use of `.eq_ctxt()` instead (see https://github.com/rust-lang/rust/issues/49509).
Also fixed a few violations of the lint in the Rustc codebase (a fun additional way I could test my code). Edit: MIR opt folks I believe that's why you're CC'ed, just a heads up.
Two things I'm not sure about:
1. The way I chose to detect calls to `Span::ctxt`. I know adding diagnostic items to methods is generally discouraged, but after some searching and experimenting I couldn't find anything else that worked, so I went with it. That said, I'm happy to implement something different if there's a better way out there. (For what it's worth, if there is a better way, it might be worth documenting in the rustc-dev-guide, which I'm happy to take care of)
2. The error message for the lint. Ideally it would probably be good to give some context as to why the suggestion is made (e.g. `rustc::default_hash_types` tells the user that it's because of performance), but I don't have that context so I couldn't put it in the error message. Happy to iterate on the error message based on feedback during review.
r? ``@oli-obk``
Add MonoItems and Instance to stable_mir
Also add a few methods to instantiate instances and get an instance definition. We're still missing support to actually monomorphize the instance body.
This is related to https://github.com/rust-lang/project-stable-mir/issues/36
r? ``@oli-obk``
``@oli-obk`` is that what you were thinking? I incorporated ``@bjorn3`` idea of just adding a Shim instance definition in https://github.com/rust-lang/rust/pull/116465.
Special case iterator chain checks for suggestion
When encountering method call chains of `Iterator`, check for trailing `;` in the body of closures passed into `Iterator::map`, as well as calls to `<T as Clone>::clone` when `T` is a type param and `T: !Clone`.
Fix#9082.
Add new simpler and more explicit syntax for check-cfg
<details>
<summary>
Old proposition (before the MCP)
</summary>
This PR adds a new simpler and more explicit syntax for check-cfg. It consist of two new form:
- `exhaustive(names, values)`
- `configure(name, "value1", "value2", ... "valueN")`
The preview forms `names(...)` and `values(...)` have implicit meaning that are not strait-forward. In particular `values(foo)`&`values(bar)` and `names(foo, bar)` are not equivalent which has created [some confusions](https://github.com/rust-lang/rust/pull/98080).
Also the `names()` and `values()` form are not clear either and again created some confusions where peoples believed that `values()`&`values(foo)` could be reduced to just `values(foo)`.
To fix that the two new forms are made to be explicit and simpler. See the table of correspondence:
- `names()` -> `exhaustive(names)`
- `values()` -> `exhaustive(values)`
- `names(foo)` -> `exhaustive(names)`&`configure(foo)`
- `values(foo)` -> `configure(foo)`
- `values(feat, "foo", "bar")` -> `configure(feat, "foo", "bar")`
- `values(foo)`&`values(bar)` -> `configure(foo, bar)`
- `names()`&`values()`&`values(my_cfg)` -> `exhaustive(names, values)`&`configure(my_cfg)`
Another benefits of the new syntax is that it allow for further options (like conditional checking for --cfg, currently always on) without syntax change.
The two previous forms are deprecated and will be removed once cargo and beta rustc have the necessary support.
</details>
This PR is the first part of the implementation of [MCP636 - Simplify and improve explicitness of the check-cfg syntax](https://github.com/rust-lang/compiler-team/issues/636).
## New `cfg` form
It introduces the new [`cfg` form](https://github.com/rust-lang/compiler-team/issues/636) and deprecate the other two:
```
rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
```
## Default built-in names and values
It also changes the default for the built-in names and values checking.
- Built-in values checking would always be activated as long as a `--check-cfg` argument is present
- Built-in names checking would always be activated as long as a `--check-cfg` argument is present **unless** if any `cfg(any())` arg is passed
~~**Note: depends on https://github.com/rust-lang/rust/pull/111068 but is reviewable (last two commits)!**~~
Resolve https://github.com/rust-lang/compiler-team/issues/636
r? `@petrochenkov`
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 defined in `rustc_data_structures` but is only used in
`rustc_type_ir`. The code is shorter and easier to read if we remove
this layer of abstraction and just do the things directly where they are
needed.
docs: add Rust logo to more compiler crates
c6e6ecb1af added it to some of the compiler's crates, but avoided adding it to all of them to reduce bit-rot. This commit adds to more.
r? `@GuillaumeGomez`
Use tidy to enforce alphabetical dependency ordering
I get annoyed when dependencies in `Cargo.toml` files are not in alphabetical order. The [style guide](https://github.com/rust-lang/rust/blob/master/src/doc/style-guide/src/cargo.md) agrees with me.
There are ongoing efforts to provide linting/formatting of `Cargo.toml` files, e.g. https://github.com/rust-lang/rustfmt/pull/5240, https://crates.io/crates/cargo-toml-lint, and https://github.com/TimonPost/cargo-toml-format. But it's far from clear what's the right approach.
So this PR does something very simple: it uses the order checking already present in tidy. This allows incremental application of ordering, starting right now, and avoiding the need for any kind of all-at-once conversion.
If we do end up using some more comprehensive `Cargo.toml` linting/formatting solution in the future, the `tidy-alphabetical` lines will be easy to remove.
r? `@wesleywiser`
Fix a performance regression in obligation deduplication.
Commit 8378487 from #114611 changed the location of an obligation deduplication step in `opt_normalize_projection_type`. This meant that deduplication stopped happening on one path where it was still necessary, causing a couple of drastic performance regressions.
This commit moves the deduplication back to the old location. The good news is that #114611 had four commits and 8378487 was of minimal importance, so the perf benefits from that PR remain.
Fixes#116780, #116797.
r? `@compiler-errors`
Commit 8378487 from #114611 changed the location of an obligation
deduplication step in `opt_normalize_projection_type`. This meant that
deduplication stopped happening on one path where it was still
necessary, causing a couple of drastic performance regressions.
This commit moves the deduplication back to the old location. The good
news is that #114611 had four commits and 8378487 was of minimal
importance, so the perf benefits from that PR remain.
Fixes#116780, #116797.
Preserve unicode escapes in format string literals when pretty-printing AST
Fixes#116799
Thanks to `@Nilstrieb` for the pointer to the correct location, that was really helpful for someone unfamiliar with the codebase.
Make `rustc_onunimplemented` export path agnostic
This makes it so that all the matchers that match against paths use the definition path instead of the export path. This removes all duplication around `std`/`alloc`/`core`.
This is not necessarily optimal because we now depend on internal implementation details like `core::ops::control_flow::ControlFlow`, which is not very nice and probably not acceptable for a stable `on_unimplemented`.
An alternative would be to just string-replace normalize away `alloc`/`core` to `std` as a special case, keeping the export paths but making it so that we're still fully standard library flavor agnostic.
Looking at the diff, I'm starting to think that some simple string replacement would go a long way towards fixing the problem of duplication while keeping export paths...
What do you prefer?
Also `@weiznich` for your thoughts about the stable version.
r? compiler-errors
Fix implied outlives check for GAT in RPITIT
We enforce certain `Self: 'lt` bounds for GATs to save space for more sophisticated implied bounds, but those currently operate on the HIR. Code was easily reworked to operate on def-ids so that we can properly let these suggestions propagate through synthetic associated types like RPITITs and AFITs.
r? `@jackh726` or `@aliemjay`
Fixes#116789
coverage: Several small cleanups in `spans`
While investigating the details of coverage span processing, I noticed several opportunities to make the code simpler and clearer.
---
`@rustbot` label +A-code-coverage
Also add a few methods to instantiate instances and get an instance
definition.
We're still missing support to actually monomorphize the instance body.
This makes it so that all the matchers that match against paths use the
definition path instead of the export path. This removes all duplication
around `std`/`alloc`/`core`.
This is not necessarily optimal because we now depend on internal
implementation details like `core::ops::control_flow::ControlFlow`,
which is not very nice and probably not acceptable for a stable
`on_unimplemented`.
An alternative would be to just string-replace normalize away
`alloc`/`core` to `std` as a special case, keeping the export paths but
making it so that we're still fully standard library flavor agnostic.
Remove `DefiningAnchor::Bubble` from opaque wf check
Set the defining anchor to `DefiningAnchor::Bind(parent_def_id)` where `parent_def_id` is the first parent def-id that isn't an opaque.
This "fixes" some of the nested-return-type wf tests. If we *do* want these to be hard-errors for TAITs, we should probably make those error separately from this check (i.e. via some check like the code in the `OPAQUE_HIDDEN_INFERRED_BOUND` lint). The fact that some of these tests fail but not all of them seems kinda coincidental.
r? oli-obk
Suggest trait bounds for used associated type on type param
Fix#101351.
When an associated type on a type parameter is used, and the type parameter isn't constrained by the correct trait, suggest the appropriate trait bound:
```
error[E0220]: associated type `Associated` not found for `T`
--> file.rs:6:15
|
6 | field: T::Associated,
| ^^^^^^^^^^ there is a similarly named associated type `Associated` in the trait `Foo`
|
help: consider restricting type parameter `T`
|
5 | struct Generic<T: Foo> {
| +++++
```
When an associated type on a type parameter has a typo, suggest fixing
it:
```
error[E0220]: associated type `Baa` not found for `T`
--> $DIR/issue-55673.rs:9:8
|
LL | T::Baa: std::fmt::Debug,
| ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
|
help: change the associated type name to use `Bar` from `Foo`
|
LL | T::Bar: std::fmt::Debug,
| ~~~
```
Add `Config::hash_untracked_state` callback
For context, I'm looking to use [late module passes](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LintStore.html#structfield.late_module_passes) in Clippy which unlike regular late passes run incrementally per module
However we have a config file which can change between runs, we need changes to that to invalidate the `lint_mod` query. This PR adds a side channel for us to hash some extra state into `Options` in order to do that
This does not make any changes to Clippy, I plan to do that in a PR to the Clippy repo along with some other required changes
An alternative implementation would be to add a new query to track this state and override the `lint_mod` query in Clippy to first call that
cc `@rust-lang/clippy`
THIR unsafety checking was getting a cycle of
function unsafety checking
-> building THIR for the function
-> evaluating pattern inline constants in the function
-> building MIR for the inline constant
-> checking unsafety of functions (so that THIR can be stolen)
This is fixed by not stealing THIR when generating MIR but instead when
unsafety checking.
This leaves an issue with pattern inline constants not being unsafety
checked because they are evaluated away when generating THIR.
To fix that we now represent inline constants in THIR patterns and
visit them in THIR unsafety checking.
don't UB on dangling ptr deref, instead check inbounds on projections
This implements https://github.com/rust-lang/reference/pull/1387 in Miri. See that PR for what the change is about.
Detecting dangling references in `let x = &...;` is now done by validity checking only, so some tests need to have validity checking enabled. There is no longer inherently a "nodangle" check in evaluating the expression `&*ptr` (aside from the aliasing model).
r? `@oli-obk`
Based on:
- https://github.com/rust-lang/reference/pull/1387
- https://github.com/rust-lang/rust/pull/115524
interpret: clean up AllocBytes
Fixes https://github.com/rust-lang/miri/issues/2836
Nothing has moved here in half a year, so let's just remove these unused stubs -- they need a proper re-design anyway.
r? `@oli-obk`
Interacting with `basic_coverage_blocks` directly makes it easier to satisfy
the borrow checker when mutating `pending_dups` while reading other fields.
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`.
`State` is used to distinguish active vs accepted vs removed features.
However, these can also be distinguished by their location, in
`ACTIVE_FEATURES`, `ACCEPTED_FEATURES`, and `REMOVED_FEATURES`.
So this commit removes `State` and moves the internals of its variants
next to the `Feature` in each element of `*_FEATURES`, introducing new
types `ActiveFeature` and `RemovedFeature`. (There is no need for
`AcceptedFeature` because `State::Accepted` had no fields.)
This is a tighter type representation, avoids the need for some runtime
checks, and makes the code a bit shorter.
use `PatKind::Error` when an ADT const value has violation
Fixes#115599
Since the [to_pat](https://github.com/rust-lang/rust/pull/111913/files#diff-6d8d99538aca600d633270051580c7a9e40b35824ea2863d9dda2c85a733b5d9R126-R155) behavior has been changed in the #111913 update, the kind of `inlined_const_ast_pat` has transformed from `PatKind::Leaf { pattern: Pat { kind: Wild, ..} } ` to `PatKind::Constant`. This caused a scenario where there are no matched candidates, leading to a testing of the candidates. This process ultimately attempts to test the string const, triggering the `bug!` invocation finally.
r? ``@oli-obk``
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 a spot I wrote the wrong word
I was reading this comment while I was looking at #116505, and it garden-path-sentence'd me, so fix that for people in the future.
Prevent more spurious unreachable pattern lints
Continues the work of https://github.com/rust-lang/rust/pull/115937 by introducing `PatKind::Error`, to be used instead of `PatKind::Wild` when an error was raised during pattern lowering. Most of match checking lints are skipped when a `PatKind::Error` is encountered. This avoids confusing extra warnings when a pattern is malformed. Now `PatKind::Wild` should indicate an actual wildcard pattern.
r? `@oli-obk`
Rollup of 5 pull requests
Successful merges:
- #115653 (Guarantee that Layout::align returns a non-zero power of two)
- #116577 (add `SAFETY` block on the usage of unsafe `getuid`)
- #116618 (Add the V (vector) extension to the riscv64-linux-android target spec)
- #116679 (Remove some unnecessary `unwrap`s)
- #116689 (explicitly handle auto trait leakage in coherence)
r? `@ghost`
`@rustbot` modify labels: rollup
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`
Add ability to get lines/filename for Span in smir
Wasn't sure about how to structure lines, so went with safest option, also I'm not sure why `span_to_lines` returns `vec`.
Addresses https://github.com/rust-lang/project-stable-mir/issues/44
r? ``@oli-obk``
linker: also pass debuginfo compression flags
We support compressing debuginfo during codegen, but until this patch we didn't pass the flag to the linker. Doing so means we'll respect the requested compression even when building binaries or dylibs. This produces much smaller binaries: in my testing a debug build of ripgrep goes from 85M to 32M, and the target/ directory (after a clean build in both cases) goes from 508M to 329M just by enabling zlib compression of debuginfo.
const_eval: allow function pointer signatures containing &mut T in const contexts
potentially fixes#114994
We utilize a `TypeVisitor` here in order to more easily handle control flow.
- In the event the typekind the Visitor sees is a function pointer, we skip over it
- However, otherwise we do one of two things:
- If we find a mutable reference, check it, then continue visiting types
- If we find any other type, continue visiting types
This means we will check if the function pointer _itself_ is mutable, but not if any of the types _within_ are.
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 😺
When encountering method call chains of `Iterator`, check for trailing
`;` in the body of closures passed into `Iterator::map`, as well as
calls to `<T as Clone>::clone` when `T` is a type param and `T: !Clone`.
Fix#9082.
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.)
Detect ruby-style closure in parser
When parsing a closure without a body that is surrounded by a block, suggest moving the opening brace after the closure head.
Fix#116608.
Fix#101351.
When an associated type on a type parameter is used, and the type
parameter isn't constrained by the correct trait, suggest the
appropriate trait bound:
```
error[E0220]: associated type `Associated` not found for `T`
--> file.rs:6:15
|
6 | field: T::Associated,
| ^^^^^^^^^^ there is a similarly named associated type `Associated` in the trait `Foo`
|
help: consider restricting type parameter `T`
|
5 | struct Generic<T: Foo> {
| +++++
```
When an associated type on a type parameter has a typo, suggest fixing
it:
```
error[E0220]: associated type `Baa` not found for `T`
--> $DIR/issue-55673.rs:9:8
|
LL | T::Baa: std::fmt::Debug,
| ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
|
help: change the associated type name to use `Bar` from `Foo`
|
LL | T::Bar: std::fmt::Debug,
| ~~~
```
We support compressing debuginfo during codegen, but until this patch we
didn't pass the flag to the linker. Doing so means we'll respect the
requested compression even when building binaries or dylibs. This
produces much smaller binaries: in my testing a debug build of ripgrep
goes from 85M to 32M, and the target/ directory (after a clean build in
both cases) goes from 508M to 329M just by enabling zlib compression of
debuginfo.
This add a new form and deprecated the other ones:
- cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))
- cfg(name1, ..., nameN) or cfg(name1, ..., nameN, values())
- cfg(any())
It also changes the default exhaustiveness to be enable-by-default in
the presence of any --check-cfg arguments.
On type error involving closure, avoid ICE
When we encounter a type error involving a closure, we try to typeck prior closure invocations to see if they influenced the current expected type. When trying to do so, ensure that the closure was defined in our current scope.
Fix#116658.
Improve check-cfg diagnostics
This PR tries to improve some of the diagnostics of check-cfg.
The main changes is the unexpected name or value being added to the main diagnostic:
```diff
- warning: unexpected `cfg` condition name
+ warning: unexpected `cfg` condition name: `widnows`
```
It also cherry-pick the better sensible logic for when we print the list of expected values when we have a matching value for a very similar name.
Address https://github.com/rust-lang/rust/pull/111072#discussion_r1356818100
r? `@petrochenkov`
Streamline `rustc_driver_impl` pretty-printing.
This PR simplifies a lot of unnecessary structure in
`rustc_driver_impl/src/pretty.rs`. It removes some traits and functions,
simplifies some structs, renames some things for increased consistency, and
eliminates some boilerplate code. Overall it cuts more than 150 lines of code.
r? `@compiler-errors`
Remove cgu_reuse_tracker from Session
This removes a bit of global mutable state.
It will now miss post-lto cgu reuse when ThinLTO determines that a cgu doesn't get changed, but there weren't any tests for this anyway and a test for it would be fragile to the exact implementation of ThinLTO in LLVM.
When we encounter a type error involving a closure, we try to typeck
prior closure invocations to see if they influenced the current expected
type. When trying to do so, ensure that the closure was defined in our
current scope.
Fix#116658.
exhaustiveness: Rework constructor splitting
`SplitWildcard` was pretty opaque. I replaced it with a more legible abstraction: `ConstructorSet` represents the set of constructors for patterns of a given type. This clarifies responsibilities: `ConstructorSet` handles one clear task, and diagnostic-related shenanigans can be done separately.
I'm quite excited, I had has this in mind for years but could never quite introduce it. This opens up possibilities, including type-specific optimisations (like using a `FxHashSet` to collect enum variants, which had been [hackily attempted some years ago](https://github.com/rust-lang/rust/pull/76918)), my one-pass rewrite (https://github.com/rust-lang/rust/pull/116042), and future librarification.
`NoAnn` and `IdentifiedAnnotation` impl both `pprust_ast::PpAnn` and
`pprust_hir::PpAnn`, which is a bit confusing, because the optional
`tcx` is only needed for the HIR cases. (Currently the `tcx` is
unnecessarily provided in the `expanded` AST cases.)
This commit splits each one into `Ast` and `Hir` versions, which makes
things clear about where the `tcx` is needed. The commit also renames
all the traits so they consistently end with `Ann`.
`call_with_pp_support_ast` and `call_with_pp_support_hir` how each have
a single call site. This commit inlines and removes them, which also
removes the need for all the supporting traits: `Sess`,
`AstPrinterSupport`, and `HirPrinterSupport`. The `sess` member is also
removed from several structs.
The handling of the `PpMode` variants is currently spread across three
functions: `print_after_parsing`, `print_after_hir_lowering`, and
`print_with_analysis`. Each one handles some of the variants. This split
is primarily because `print_after_parsing` has slightly different
arguments to the other two.
This commit changes the structure. It merges the three functions into a
single `print` function, and encapsulates the different arguments in a
new enum `PrintExtra`.
Benefits:
- The code is a little shorter.
- All the `PpMode` variants are handled in a single `match`, with no
need for `unreachable!` arms.
- It enables the trait removal in the subsequent commit by reducing
the number of `call_with_pp_support_ast` call sites from two to one.
First, both `AstPrinterSupport` and `HirPrinterSupport` have a `sess`
method. This commit introduces a `Sess` trait and makes the support
traits be subtraits of `Sess`, to avoid some duplication.
Second, both support traits have a `pp_ann` method that isn't needed if
we enable `trait_upcasting`. This commit removes those methods.
(Both of these traits will be removed in a subsequent commit, as will
the `trait_upcasting` use.)
`phase_3_run_analysis_passes` no longer exists, and AFAICT this code has
been refactored so much since this comment was written that it no longer
has any useful meaning.
Copy 1-element arrays as scalars, not vectors
For `[T; 1]` it's silly to copy as `<1 x T>` when we can just copy as `T`.
Inspired by https://github.com/rust-lang/rust/issues/101210#issuecomment-1732470941, which pointed out that `Option<[u8; 1]>` was codegenning worse than `Option<u8>`.
(I'm not sure *why* LLVM doesn't optimize out `<1 x u8>`, but might as well just not emit it in the first place in this codepath.)
---
I think I bit off too much in #116479; let me try just the scalar case first.
r? `@ghost`
coverage: Clarify loop-edge detection and graph traversal
This is a collection of improvements to two semi-related pieces of code:
- The code in `counters` that detects which graph edges don't exit a loop, and would therefore be good candidates to have their coverage computed as an expression rather than having a physical counter.
- The code in `graph` that traverses the coverage BCB graph in a particular order, and tracks loops and loop edges along the way (which is relevant to the above).
I was originally only planning to make the `graph` changes, but there was going to be a lot of indentation churn in `counters` anyway, and once I started looking I noticed a lot of opportunities for simplification.
---
`@rustbot` label +A-code-coverage
Handle several `#[diagnostic::on_unimplemented]` attributes correctly
This PR fixes an issues where rustc would ignore subsequent `#[diagnostic::on_unimplemented]` attributes. The [corresponding RFC](https://rust-lang.github.io/rfcs/3368-diagnostic-attribute-namespace.html) specifies that the first matching instance of each option is used. Invalid attributes are linted and otherwise ignored.
Having to keep passing in a graph reference was a holdover from when the graph
was partly mutated during traversal. As of #114354 that is no longer necessary,
so we can simplify the traversal code by storing a graph reference as a field
in `TraverseCoverageGraphWithLoops`.
The previous code was storing the worklist in a vector, and then selectively
adding items to the start or end of the vector. That's a perfect use-case for a
double-ended queue.
This change also reveals that the existing code was a bit confused about which
end of the worklist is the front or back. For now, items are always removed
from the front of the queue (instead of the back), and code that adds items to
the queue has been flipped, to preserve the existing behaviour.
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.
Use structured suggestion for #113174
When encountering a for loop that is rejected by the borrow checker because it is being advanced within its body, provide a structured suggestion for `while let Some(pat) = iter.next()`.
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
This PR fixes an issues where rustc would ignore subsequent
`#[diagnostic::on_unimplemented]` attributes. The [corresponding
RFC](https://rust-lang.github.io/rfcs/3368-diagnostic-attribute-namespace.html)
specifies that the first matching instance of each option is used.
Invalid attributes are linted and otherwise ignored.
Rollup of 5 pull requests
Successful merges:
- #116219 (Relate alias ty with variance)
- #116315 (Do not check for impossible predicates in const-prop lint.)
- #116436 (Structurally normalize for closure)
- #116597 (Prevent showing methods from blanket impls of not available foreign traits to show up in the search results)
- #116627 (small cleanup)
r? `@ghost`
`@rustbot` modify labels: rollup
When encountering a for loop that is rejected by the borrow checker
because it is being advanced within its body, provide a structured
suggestion for `while let Some(pat) = iter.next()`.
Do not check for impossible predicates in const-prop lint.
The enclosing query already checks for them, and replaces the body with a single `unreachable` if they are indeed impossible.
Relate alias ty with variance
In the new solver, turns out that the subst-relate branch of the alias-relate predicate was relating args invariantly even for opaques, which have variance 💀.
This change is a bit more invasive, but I'd rather not special-case it [here](aeaa5c30e5/compiler/rustc_trait_selection/src/solve/alias_relate.rs (L171-L190)) and then have it break elsewhere. I'm doing a perf run to see if the extra call to `def_kind` is that expensive, if it is, I'll reconsider.
r? ``@lcnr``
Compute NLL loan scopes using the polonius model
For a *location-insensitive* analysis (that is, without expressiveness improvements for users yet), this PR implements loans going out of scope using reachability and liveness, rather than checking if the issuing region's values contain a given CFG point. This is equivalent to NLL scopes and computes the same data.
r? `@matthewjasper`
A couple of notes:
- there are some assumptions about SCC representatives, placeholders, free regions, and member constraints that I believe hold, and they're documented in the code
- this passes all the UI tests with `-Zpolonius=next` -- the perf is [not terrible](https://github.com/rust-lang/rust/pull/112432#issuecomment-1749685862) and there are a bunch of ways to improve it in the future.
- there's a fixme left, hopefully Matthew you know a clean way to get the information it mentions.
Implement `-Clink-self-contained=-linker` opt out
This implements the `-Clink-self-contained` opt out necessary to switch to lld by changing rustc's defaults instead of cargo's.
Components that are enabled and disabled on the CLI are recorded, for the purpose of being merged with the ones which the target spec will declare (I'll open another PR for that tomorrow, for easier review).
For MCP510, we now check whether using the self-contained linker is disabled on the CLI. Right now it would only be sensible to with `-Zgcc-ld=lld` (and I'll add some checks that we don't both enable and disable a component on the CLI in a future PR), but the goal is to simplify adding the check of the target's enabled components here in the follow-up PRs.
r? `@petrochenkov`
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
Also consider call and yield as MIR SSA.
The SSA analysis on MIR only considered `Assign` statements as defining a SSA local.
This PR adds assignments as part of a `Call` or `Yield` terminator in that category.
This mainly allows to perform CopyProp on a call return place.
The only subtlety is in the dominance property: the assignment is only complete at the beginning of the target block.
In smir use `FxIndexMap` to store indexed ids
Previously we used `vec` for storing indexed types, which is fine for small cases but will lead to huge performance issues when we use `smir` for real world cases.
Addresses https://github.com/rust-lang/project-stable-mir/issues/35
r? ``@oli-obk``