Trivial tweaks to stop tracking source span directly
Firstly, remove some unnecessary work from `sccs_info`. This included debug printing which ends up giving all mir borrowck queries a dependency edge from the query to `source_span` (I think?).
Secondly, turn some calls from `hir_span` (which does some span adjustment, and thus incurs span tracking, which causes a dependency edge from the query to `source_span`) to `def_span`, which should cache better.
r? oli-obk
add sret handling for scalar autodiff
r? `@oli-obk`
Fixing one of the todo's which I left in my previous batching PR.
This one handles sret for scalar autodiff. `sret` mostly shows up when we try to return a lot of scalar floats.
People often start testing autodiff which toy functions which just use a few scalars as inputs and outputs, and those were the most likely to be affected by this issue. So this fix should make learning/teaching hopefully a bit easier.
Tracking:
- https://github.com/rust-lang/rust/issues/124509
Stop calling `source_span` query in significant drop order code
`source_span` is only meant for incremental tracking. I don't really think we need to highlight the whole drop impl span anyways; it can be quite large.
r? oli-obk
Remove support for `extern "rust-intrinsic"` blocks
Part of rust-lang/rust#132735
Looked manageable and there didn't appear to have been progress in the last two weeks,
so decided to give it a try.
coverage: Build the CGU's global file table as late as possible
Embedding coverage metadata in the output binary is a delicate dance, because per-function records need to embed references to the per-CGU filename table, but we only want to include files in that table if they are successfully used by at least one function.
The way that we build the file tables has changed a few times over the last few years. This particular change is motivated by experimental work on properly supporting macro-expansion regions, which adds some additional constraints that our previous implementation wasn't equipped to deal with.
LLVM is very strict about not allowing unused entries in local file tables. Currently that's not much of an issue, because we assume one source file per function, but to support expansion regions we need the flexibility to avoid committing to the use of a file until we're completely sure that we are able and willing to produce at least one coverage mapping region for it. In particular, when preparing a function's covfun record, we need the flexibility to decide at a late stage that a particular file isn't needed/usable after all.
(It's OK for the *global* file table to contain unused entries, but we would still prefer to avoid that if possible, and this implementation also achieves that.)
Default auto traits: fix perf
Skip computing `requires_default_supertraits` if `experimental-default-bounds` option is not enabled. Possible perf fix for https://github.com/rust-lang/rust/pull/120706
r? lcnr
Implement `super let`
Tracking issue: https://github.com/rust-lang/rust/issues/139076
This implements `super let` as proposed in #139080, based on the following two equivalence rules.
1. For all expressions `$expr` in any context, these are equivalent:
- `& $expr`
- `{ super let a = & $expr; a }`
2. And, additionally, these are equivalent in any context when `$expr` is a temporary (aka rvalue):
- `& $expr`
- `{ super let a = $expr; & a }`
So far, this experiment has a few interesting results:
## Interesting result 1
In this snippet:
```rust
super let a = f(&temp());
```
I originally expected temporary `temp()` would be dropped at the end of the statement (`;`), just like in a regular `let`, because `temp()` is not subject to temporary lifetime extension.
However, it turns out that that would break the fundamental equivalence rules.
For example, in
```rust
g(&f(&temp()));
```
the temporary `temp()` will be dropped at the `;`.
The first equivalence rule tells us this must be equivalent:
```rust
g({ super let a = &f(&temp()); a });
```
But that means that `temp()` must live until the last `;` (after `g()`), not just the first `;` (after `f()`).
While this was somewhat surprising to me at first, it does match the exact behavior we need for `pin!()`: The following _should work_. (See also https://github.com/rust-lang/rust/issues/138718)
```rust
g(pin!(f(&mut temp())));
```
Here, `temp()` lives until the end of the statement. This makes sense from the perspective of the user, as no other `;` or `{}` are visible. Whether `pin!()` uses a `{}` block internally or not should be irrelevant.
This means that _nothing_ in a `super let` statement will be dropped at the end of that super let statement. It does not even need its own scope.
This raises questions that are useful for later on:
- Will this make temporaries live _too long_ in cases where `super let` is used not in a hidden block in a macro, but as a visible statement in code like the following?
```rust
let writer = {
super let file = File::create(&format!("/home/{user}/test"));
Writer::new(&file)
};
```
- Is a `let` statement in a block still the right syntax for this? Considering it has _no_ scope of its own, maybe neither a block nor a statement should be involved
This leads me to think that instead of `{ super let $pat = $init; $expr }`, we might want to consider something like `let $pat = $init in $expr` or `$expr where $pat = $init`. Although there are also issues with these, as it isn't obvious anymore if `$init` should be subject to temporary lifetime extension. (Do we want both `let _ = _ in ..` and `super let _ = _ in ..`?)
## Interesting result 2
What about `super let x;` without initializer?
```rust
let a = {
super let x;
x = temp();
&x
};
```
This works fine with the implementation in this PR: `x` is extended to live as long as `a`.
While it matches my expectations, a somewhat interesting thing to realize is that these are _not_ equivalent:
- `super let x = $expr;`
- `super let x; x = $expr;`
In the first case, all temporaries in $expr will live at least as long as (the result of) the surrounding block.
In the second case, temporaries will be dropped at the end of the assignment statement. (Because the assignment statement itself "is not `super`".)
This difference in behavior might be confusing, but it _might_ be useful.
One might want to extend the lifetime of a variable without extending all the temporaries in the initializer expression.
On the other hand, that can also be expressed as:
- `let x = $expr; super let x = x;` (w/o temporary lifetime extension), or
- `super let x = { $expr };` (w/ temporary lifetime extension)
So, this raises these questions:
- Do we want to accept `super let x;` without initializer at all?
- Does it make sense for statements other than let statements to be "super"? An expression statement also drops temporaries at its `;`, so now that we discovered that `super let` basically disables that `;` (see interesting result 1), is there a use to having other statements without their own scope? (I don't think that's ever useful?)
## Interesting result 3
This works now:
```rust
super let Some(x) = a.get(i) else { return };
```
I didn't put in any special cases for `super let else`. This is just the behavior that 'naturally' falls out when implementing `super let` without thinking of the `let else` case.
- Should `super let else` work?
## Interesting result 4
This 'works':
```rust
fn main() {
super let a = 123;
}
```
I didn't put in any special cases for `super let` at function scope. I had expected the code to cause an ICE or other weird failure when used at function body scope, because there's no way to let the variable live as long as the result of the function.
This raises the question:
- Does this mean that this behavior is the natural/expected behavior when `super let` is used at function scope? Or is this just a quirk and should we explicitly disallow `super let` in a function body? (Probably the latter.)
---
The questions above do not need an answer to land this PR. These questions should be considered when redesigning/rfc'ing/stabilizing the feature.
Simplify `thir::PatKind::ExpandedConstant`
I made it a bit less ad-hoc. In particular, I removed `is_inline: bool` that was just caching the output of `tcx.def_kind(def_id)`. This makes inline consts a tiny bit less special in patterns.
r? `@oli-obk`
cc `@Zalathar`
Add new `PatKind::Missing` variants
To avoid some ugly uses of `kw::Empty` when handling "missing" patterns, e.g. in bare fn tys. Helps with #137978. Details in the individual commits.
r? ``@oli-obk``
More trivial tweaks
Found some really tiny nits when trying to find places that span tracking caused queries to be recomputed in incremental; these probably don't need a perf run b/c they're so simple.
r? oli-obk
Make the UnifyKey and UnifyValue imports non-nightly
Explicitly depend on ena in rustc_type_ir and import types from there.
This is required for rust-analyzer to use the new solver.
r? types
fix usage of `autodiff` macro with inner functions
This PR adds additional handling into the expansion step of the `std::autodiff` macro (in `compiler/rustc_builtin_macros/src/autodiff.rs`), which allows the macro to be applied to inner functions.
```rust
#![feature(autodiff)]
use std::autodiff::autodiff;
fn main() {
#[autodiff(d_inner, Forward, Dual, DualOnly)]
fn inner(x: f32) -> f32 {
x * x
}
}
```
Previously, the compiler didn't allow this due to only handling `Annotatable::Item` and `Annotatable::AssocItem` and missing the handling of `Annotatable::Stmt`. This resulted in the rather generic error
```
error: autodiff must be applied to function
--> src/main.rs:6:5
|
6 | / fn inner(x: f32) -> f32 {
7 | | x * x
8 | | }
| |_____^
error: could not compile `enzyme-test` (bin "enzyme-test") due to 1 previous error
```
This issue was originally reported [here](https://github.com/EnzymeAD/rust/issues/184).
Quick question: would it make sense to add a ui test to ensure there is no regression on this?
This is my first contribution, so I'm extra grateful for any piece of feedback!! :D
r? `@oli-obk`
Tracking issue for autodiff: #124509
coverage: Deal with unused functions and their names in one place
When coverage codegen creates dummy instances and covfun records for unused functions, we already know that they are unused, so we might as well set up the special array of unused function names at the same time.
---
The first commit only moves code around; all significant changes are in the second commit.
There should be no change in compiler output.
- fix errors caused by the move of `ast::Item::ident` (see #138740)
- move the logic of getting `sig`, `vis`, and `ident` from two seperate
`match` statements into one (less repetition especially with the
nested `match`)
Add `*_value` methods to proc_macro lib
This is the (re-)implementation of https://github.com/rust-lang/libs-team/issues/459.
It allows to get the actual value (unescaped) of the different string literals.
It was originally done in https://github.com/rust-lang/rust/pull/136355 but it broke the artifacts build so we decided to move the crate to crates.io to go around this limitation.
Part of https://github.com/rust-lang/rust/issues/136652.
Considering this is a copy-paste of the originally approved PR, no need to go through the whole process again. \o/
r? `@Urgau`
Refactor Apple version handling in the compiler
Move various Apple version handling code in the compiler out `rustc_codegen_ssa` and into a place where it can be accessed by `rustc_attr_parsing`, which I found to be necessary when doing https://github.com/rust-lang/rust/pull/136867. Thought I'd split it out to make it easier to land, and to make further changes like https://github.com/rust-lang/rust/pull/131477 have fewer conflicts / PR dependencies.
There should be no functional changes in this PR.
`@rustbot` label O-apple
r? rust-lang/compiler
In `simplify_repeated_aggregate`, don't test first element against itself
r? `@saethlin`
Noticed that in `InstSimplifyContext::simplify_repeated_aggregate`, we're accidentally evaluating the first element's value twice, and then comparing it with itself, instead of just checking whether the rest of the elements are equal to the first one.
This will probably save very few cycles, but since `InstSimplify` is always enabled, this might improve perf by a bit.
Update the minimum external LLVM to 19
With this change, we'll have stable support for LLVM 19 and 20.
For reference, the previous increase to LLVM 18 was #130487.
cc `@rust-lang/wg-llvm`
r? nikic
StableMIR: Prepare for refactoring
Temporarily make `stable_mir` "parasitic" on the `rustc_smir` crate.
It aims to resolve the circular dependency that would arise if we directly invert the dependency order between `rustc_smir` and `stable_mir`.
Once the refactoring is complete (`rustc_smir` does not depend on `stable_mir`), we will migrate it back to the `stable_mir` crate. See more details: [here](https://hackmd.io/jBRkZLqAQL2EVgwIIeNMHg).
Folder experiment: Micro-optimize RegionEraserVisitor
**NOTE:** This is one of a series of perf experiments that I've come up with while sick in bed. I'm assigning them to lqd b/c you're a good reviewer and you'll hopefully be awake when these experiments finish, lol.
r? lqd
The region eraser is very hot, so let's see if we can avoid erasing types (and visiting consts and preds that don't have region-ful types) unnecessarily.
hygiene: Avoid recursion in syntax context decoding
#139241 has two components
- Avoiding recursion during syntax context decoding
- Encoding/decoding only the non-redundant data, and recalculating the redundant data again during decoding
Both of these parts may influence compilation times, possibly in opposite directions.
So this PR contains only the first part to evaluate its effect in isolation.
Apply `Recovery::Forbidden` when reparsing pasted macro fragments.
Fixes#137874.
The changes to the output of `tests/ui/associated-consts/issue-93835.rs`
partly undo the changes seen when `NtTy` was removed in #133436, which
is good.
r? ``@petrochenkov``
replace extra_filename with strict version hash in metrics file names
Should resolve the potential issue of overwriting metrics from the same crate when compiled with different features or flags.
r? `````@estebank`````
try-job: test-various
Autodiff batching
Enzyme supports batching, which is especially known from the ML side when training neural networks.
There we would normally have a training loop, where in each iteration we would pass in some data (e.g. an image), and a target vector. Based on how close we are with our prediction we compute our loss, and then use backpropagation to compute the gradients and update our weights.
That's quite inefficient, so what you normally do is passing in a batch of 8/16/.. images and targets, and compute the gradients for those all at once, allowing better optimizations.
Enzyme supports batching in two ways, the first one (which I implemented here) just accepts a Batch size,
and then each Dual/Duplicated argument has not one, but N shadow arguments. So instead of
```rs
for i in 0..100 {
df(x[i], y[i], 1234);
}
```
You can now do
```rs
for i in 0..100.step_by(4) {
df(x[i+0],x[i+1],x[i+2],x[i+3], y[i+0], y[i+1], y[i+2], y[i+3], 1234);
}
```
which will give the same results, but allows better compiler optimizations. See the testcase for details.
There is a second variant, where we can mark certain arguments and instead of having to pass in N shadow arguments, Enzyme assumes that the argument is N times longer. I.e. instead of accepting 4 slices with 12 floats each, we would accept one slice with 48 floats. I'll implement this over the next days.
I will also add more tests for both modes.
For any one preferring some more interactive explanation, here's a video of Tim's llvm dev talk, where he presents his work. https://www.youtube.com/watch?v=edvaLAL5RqU
I'll also add some other docs to the dev guide and user docs in another PR.
r? ghost
Tracking:
- https://github.com/rust-lang/rust/issues/124509
- https://github.com/rust-lang/rust/issues/135283
Use the span of the whole bound when the diagnostic talks about a bound
While it makes sense that the host predicate only points to the `~const` part, as whether the actual trait bound is satisfied is checked separately, the user facing diagnostic is talking about the entire trait bound, at which point it makes more sense to just highlight the entire bound
r? `@compiler-errors` or `@fee1-dead`
ToSocketAddrs: fix typo
It's "a function", never "an function".
I noticed the same typo somewhere in the compiler sources so figured I'd fix it there as well.
Fix `Debug` impl for `LateParamRegionKind`.
It uses `Br` prefixes which are inappropriate and appear to have been incorrectly copy/pasted from the `Debug` impl for `BoundRegionKind`.
r? `@BoxyUwU`
AsyncDestructor: replace fields with impl_did
The future and ctor fields aren't actually used, and the way they are extracted is obviously wrong – swapping the order of the items in the source code will give wrong results.
Instead, store just the LocalDefId of the impl, which is enough for the only use of this data.
Remove `rustc_middle::ty::util::ExplicitSelf`.
It's an old (2017 or earlier) type that describes a `self` receiver. It's only used in `rustc_hir_analysis` for two error messages, and much of the complexity isn't used. I suspect it used to be used for more things.
This commit removes it, and moves a greatly simplified version of the `determine` method into `rustc_hir_analysis`, renamed as `get_self_string`. The big comment on the method is removed because it no longer seems relevant.
r? `@BoxyUwU`
add `TypingMode::Borrowck`
Shares the first commit with #138499, doesn't really matter which PR to land first 😊😁
Introduces `TypingMode::Borrowck` which unlike `TypingMode::Analysis`, uses the hidden type computed by HIR typeck as the initial value of opaques instead of an unconstrained infer var. This is a part of https://github.com/rust-lang/types-team/issues/129.
Using this new `TypingMode` is unfortunately a breaking change for now, see tests/ui/impl-trait/non-defining-uses/as-projection-term.rs. Using an inference variable as the initial value results in non-defining uses in the defining scope. We therefore only enable it if with `-Znext-solver=globally` or `-Ztyping-mode-borrowck`
To do that the PR contains the following changes:
- `TypeckResults::concrete_opaque_type` are already mapped to the definition of the opaque type
- writeback now checks that the non-lifetime parameters of the opaque are universal
- for this, `fn check_opaque_type_parameter_valid` is moved from `rustc_borrowck` to `rustc_trait_selection`
- we add a new `query type_of_opaque_hir_typeck` which, using the same visitors as MIR typeck, attempts to merge the hidden types from HIR typeck from all defining scopes
- done by adding a `DefiningScopeKind` flag to toggle between using borrowck and HIR typeck
- the visitors stop checking that the MIR type matches the HIR type. This is trivial as the HIR type are now used as the initial hidden types of the opaque. This check is useful as a safeguard when not using `TypingMode::Borrowck`, but adding it to the new structure is annoying and it's not soundness critical, so I intend to not add it back.
- add a `TypingMode::Borrowck` which behaves just like `TypingMode::Analysis` except when normalizing opaque types
- it uses `type_of_opaque_hir_typeck(opaque)` as the initial value after replacing its regions with new inference vars
- it uses structural lookup in the new solver
fixes#112201, fixes#132335, fixes#137751
r? `@compiler-errors` `@oli-obk`
Demote i686-pc-windows-gnu to Tier 2
In accordance with [RFC 3771](https://github.com/rust-lang/rfcs/pull/3771). FCP has been completed.
tracking issue #138422
I also added a stub doc page for the target and renamed the windows-gnullvm page for consistency.
Rollup of 8 pull requests
Successful merges:
- #138949 (Rename `is_like_osx` to `is_like_darwin`)
- #139295 (Remove creation of duplicate `AnonPipe`)
- #139313 (Deduplicate some `rustc_middle` function bodies by calling the `rustc_type_ir` equivalent)
- #139317 (compiletest: Encapsulate all of the code that touches libtest)
- #139322 (Add helper function for checking LLD usage to `run-make-support`)
- #139335 (Pass correct param-env to `error_implies`)
- #139342 (Add a mailmap entry for myself)
- #139349 (adt_destructor: sanity-check returned item)
r? `@ghost`
`@rustbot` modify labels: rollup
Pass correct param-env to `error_implies`
Duplicated comment from the test:
In the error reporting code, when reporting fulfillment errors for goals A and B, we try to see if elaborating A will result in another goal that can equate with B. That would signal that B is "implied by" A, allowing us to skip reporting it, which is beneficial for cutting down on the number of diagnostics we report.
In the new trait solver especially, but even in the old trait solver through things like defining opaque type usages, this `can_equate` call was not properly taking the param-env of the goals, resulting in nested obligations that had empty param-envs. If one of these nested obligations was a `ConstParamHasTy` goal, then we would ICE, since those goals are particularly strict about the param-env they're evaluated in.
This is morally a fix for <https://github.com/rust-lang/rust/issues/139314>, but that repro uses details about how defining usages in the `check_opaque_well_formed` code can spring out of type equality, and will likely stop failing soon coincidentally once we start using `PostBorrowck` mode in that check. Instead, we use lazy normalization to end up generating an alias-eq goal whose nested goals woul trigger the ICE instead, since this is a lot more stable.
Fixes https://github.com/rust-lang/rust/issues/139314
r? ``@oli-obk`` or reassign
Deduplicate some `rustc_middle` function bodies by calling the `rustc_type_ir` equivalent
Maybe in the future we can use method delegation, but I'd rather avoid that for now (I don't even know if it can do that already)
Rename `is_like_osx` to `is_like_darwin`
Replace `is_like_osx` with `is_like_darwin`, which more closely describes reality (OS X is the pre-2016 name for macOS, and is by now quite outdated; Darwin is the overall name for the OS underlying Apple's macOS, iOS, etc.).
``@rustbot`` label O-apple
r? compiler
Folder experiment: Monomorphize region resolver
**NOTE:** This is one of a series of perf experiments that I've come up with while sick in bed. I'm assigning them to lqd b/c you're a good reviewer and you'll hopefully be awake when these experiments finish, lol.
r? lqd
This is actually two tweaks to the `RegionFolder`, monomorphizing its callback and accounting for flags to avoid folding unnecessarily.
The future and ctor fields aren't actually used, and the way they are
extracted is obviously wrong – swapping the order of the items in the
source code will give wrong results.
Instead, store just the LocalDefId of the impl, which is enough for the
only use of this data.
Fixes#137874.
Removes `tests/crashes/137874.rs`; the new test is simpler (defines its
own macro) but tests the same thing.
The changes to the output of `tests/ui/associated-consts/issue-93835.rs`
partly undo the changes seen when `NtTy` was removed in #133436, which
is good.
Initial support for auto traits with default bounds
This PR is part of ["MCP: Low level components for async drop"](https://github.com/rust-lang/compiler-team/issues/727)
Tracking issue: #138781
Summary: https://github.com/rust-lang/rust/pull/120706#issuecomment-1934006762
### Intro
Sometimes we want to use type system to express specific behavior and provide safety guarantees. This behavior can be specified by various "marker" traits. For example, we use `Send` and `Sync` to keep track of which types are thread safe. As the language develops, there are more problems that could be solved by adding new marker traits:
- to forbid types with an async destructor to be dropped in a synchronous context a trait like `SyncDrop` could be used [Async destructors, async genericity and completion futures](https://sabrinajewson.org/blog/async-drop).
- to support [scoped tasks](https://without.boats/blog/the-scoped-task-trilemma/) or in a more general sense to provide a [destruction guarantee](https://zetanumbers.github.io/book/myosotis.html) there is a desire among some users to see a `Leak` (or `Forget`) trait.
- Withoutboats in his [post](https://without.boats/blog/changing-the-rules-of-rust/) reflected on the use of `Move` trait instead of a `Pin`.
All the traits proposed above are supposed to be auto traits implemented for most types, and usually implemented automatically by compiler.
For backward compatibility these traits have to be added implicitly to all bound lists in old code (see below). Adding new default bounds involves many difficulties: many standard library interfaces may need to opt out of those default bounds, and therefore be infected with confusing `?Trait` syntax, migration to a new edition may contain backward compatibility holes, supporting new traits in the compiler can be quite difficult and so forth. Anyway, it's hard to evaluate the complexity until we try the system on a practice.
In this PR we introduce new optional lang items for traits that are added to all bound lists by default, similarly to existing `Sized`. The examples of such traits could be `Leak`, `Move`, `SyncDrop` or something else, it doesn't matter much right now (further I will call them `DefaultAutoTrait`'s). We want to land this change into rustc under an option, so it becomes available in bootstrap compiler. Then we'll be able to do standard library experiments with the aforementioned traits without adding hundreds of `#[cfg(not(bootstrap))]`s. Based on the experiments, we can come up with some scheme for the next edition, in which such bounds are added in a more targeted way, and not just everywhere.
Most of the implementation is basically a refactoring that replaces hardcoded uses of `Sized` with iterating over a list of traits including both `Sized` and the new traits when `-Zexperimental-default-bounds` is enabled (or just `Sized` as before, if the option is not enabled).
### Default bounds for old editions
All existing types, including generic parameters, are considered `Leak`/`Move`/`SyncDrop` and can be forgotten, moved or destroyed in generic contexts without specifying any bounds. New types that cannot be, for example, forgotten and do not implement `Leak` can be added at some point, and they should not be usable in such generic contexts in existing code.
To both maintain this property and keep backward compatibility with existing code, the new traits should be added as default bounds _everywhere_ in previous editions. Besides the implicit `Sized` bound contexts that includes supertrait lists and trait lists in trait objects (`dyn Trait1 + ... + TraitN`). Compiler should also generate implicit `DefaultAutoTrait` implementations for foreign types (`extern { type Foo; }`) because they are also currently usable in generic contexts without any bounds.
#### Supertraits
Adding the new traits as supertraits to all existing traits is potentially necessary, because, for example, using a `Self` param in a trait's associated item may be a breaking change otherwise:
```rust
trait Foo: Sized {
fn new() -> Option<Self>; // ERROR: `Option` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
}
// desugared `Option`
enum Option<T: DefaultAutoTrait + Sized> {
Some(T),
None,
}
```
However, default supertraits can significantly affect compiler performance. For example, if we know that `T: Trait`, the compiler would deduce that `T: DefaultAutoTrait`. It also implies proving `F: DefaultAutoTrait` for each field `F` of type `T` until an explicit impl is be provided.
If the standard library is not modified, then even traits like `Copy` or `Send` would get these supertraits.
In this PR for optimization purposes instead of adding default supertraits, bounds are added to the associated items:
```rust
// Default bounds are generated in the following way:
trait Trait {
fn foo(&self) where Self: DefaultAutoTrait {}
}
// instead of this:
trait Trait: DefaultAutoTrait {
fn foo(&self) {}
}
```
It is not always possible to do this optimization because of backward compatibility:
```rust
pub trait Trait<Rhs = Self> {}
pub trait Trait1 : Trait {} // ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
```
or
```rust
trait Trait {
type Type where Self: Sized;
}
trait Trait2<T> : Trait<Type = T> {} // ERROR: `???` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
```
Therefore, `DefaultAutoTrait`'s are still being added to supertraits if the `Self` params or type bindings were found in the trait header.
#### Trait objects
Trait objects requires explicit `+ Trait` bound to implement corresponding trait which is not backward compatible:
```rust
fn use_trait_object(x: Box<dyn Trait>) {
foo(x) // ERROR: `foo` requires `DefaultAutoTrait`, but `dyn Trait` is not `DefaultAutoTrait`
}
// implicit T: DefaultAutoTrait here
fn foo<T>(_: T) {}
```
So, for a trait object `dyn Trait` we should add an implicit bound `dyn Trait + DefaultAutoTrait` to make it usable, and allow relaxing it with a question mark syntax `dyn Trait + ?DefaultAutoTrait` when it's not necessary.
#### Foreign types
If compiler doesn't generate auto trait implementations for a foreign type, then it's a breaking change if the default bounds are added everywhere else:
```rust
// implicit T: DefaultAutoTrait here
fn foo<T: ?Sized>(_: &T) {}
extern "C" {
type ExternTy;
}
fn forward_extern_ty(x: &ExternTy) {
foo(x); // ERROR: `foo` requires `DefaultAutoTrait`, but `ExternTy` is not `DefaultAutoTrait`
}
```
We'll have to enable implicit `DefaultAutoTrait` implementations for foreign types at least for previous editions:
```rust
// implicit T: DefaultAutoTrait here
fn foo<T: ?Sized>(_: &T) {}
extern "C" {
type ExternTy;
}
impl DefaultAutoTrait for ExternTy {} // implicit impl
fn forward_extern_ty(x: &ExternTy) {
foo(x); // OK
}
```
### Unresolved questions
New default bounds affect all existing Rust code complicating an already complex type system.
- Proving an auto trait predicate requires recursively traversing the type and proving the predicate for it's fields. This leads to a significant performance regression. Measurements for the stage 2 compiler build show up to 3x regression.
- We hope that fast path optimizations for well known traits could mitigate such regressions at least partially.
- New default bounds trigger some compiler bugs in both old and new trait solver.
- With new default bounds we encounter some trait solver cycle errors that break existing code.
- We hope that these cases are bugs that can be addressed in the new trait solver.
Also migration to a new edition could be quite ugly and enormous, but that's actually what we want to solve. For other issues there's a chance that they could be solved by a new solver.
Dedup `&mut *` reborrow suggestion in loops
#73534 added a reborrow suggestion in loops; #127579 generalized this to generic parameters, making the suggestion triggers twice:
```rs
use std::io::Read;
fn decode_scalar(_reader: impl Read) {}
fn decode_array(reader: &mut impl Read) {
for _ in 0.. {
decode_scalar(reader);
}
}
```
```
error[E0382]: use of moved value: `reader`
--> src/lib.rs:6:23
|
4 | fn decode_array(reader: &mut impl Read) {
| ------ move occurs because `reader` has type `&mut impl Read`, which does not implement the `Copy` trait
5 | for _ in 0.. {
| ------------ inside of this loop
6 | decode_scalar(reader);
| ^^^^^^ value moved here, in previous iteration of loop
|
help: consider creating a fresh reborrow of `reader` here
|
6 | decode_scalar(&mut *reader);
| ++++++
help: consider creating a fresh reborrow of `reader` here
|
6 | decode_scalar(&mut *reader);
| ++++++
```
This PR removes the suggestion in loops, as it requires generic parameters anyway (i.e., the reborrow is automatic if there is no generic params).
`@rustbot` label +A-borrow-checker +A-diagnostics +A-suggestion-diagnostics +D-papercut
gvn: Invalid dereferences for all non-local mutations
Fixes#132353.
This PR removes the computation value by traversing SSA locals through `for_each_assignment_mut`.
Because the `for_each_assignment_mut` traversal skips statements which have side effects, such as dereference assignments, the computation may be unsound. Instead of `for_each_assignment_mut`, we compute values by traversing in reverse postorder.
Because we compute and use the symbolic representation of values on the fly, I invalidate all old values when encountering a dereference assignment. The current approach does not prevent the optimization of a clone to a copy.
In the future, we may add an alias model, or dominance information for dereference assignments, or SSA form to help GVN.
r? cjgillot
cc `@jieyouxu` #132356
cc `@RalfJung` #133474
Fixes#139082.
Emits an error when `Self` is found in the projection bounds of a trait
object. In type aliases, `Self` has no meaning, so `type A = &'static
dyn B` where `trait B = Fn() -> Self` will expands to `type A = &'static
Fn() -> Self` which is illegal, causing the region solver to bail out
when hitting the uninferred Self.
Bug: #139082
Signed-off-by: xtex <xtexchooser@duck.com>
Experimental feature gate for `super let`
This adds an experimental feature gate, `#![feature(super_let)]`, for the `super let` experiment.
Tracking issue: https://github.com/rust-lang/rust/issues/139076
Liaison: ``@nikomatsakis``
## Description
There's a rough (inaccurate) description here: https://blog.m-ou.se/super-let/
In short, `super let` allows you to define something that lives long enough to be borrowed by the tail expression of the block. For example:
```rust
let a = {
super let b = temp();
&b
};
```
Here, `b` is extended to live as long as `a`, similar to how in `let a = &temp();`, the temporary will be extended to live as long as `a`.
## Properties
During the temporary lifetimes work we did last year, we explored the properties of "super let" and concluded that the fundamental property should be that these two are always equivalent in any context:
1. `& $expr`
2. `{ super let a = & $expr; a }`
And, additionally, that these are equivalent in any context when `$expr` is a temporary (aka rvalue):
1. `& $expr`
2. `{ super let a = $expr; & a }`
This makes it possible to give a name to a temporary without affecting how temporary lifetimes work, such that a macro can transparently use a block in its expansion, without that having any effect on the outside.
## Implementing pin!() correctly
With `super let`, we can properly implement the `pin!()` macro without hacks: ✨
```rust
pub macro pin($value:expr $(,)?) {
{
super let mut pinned = $value;
unsafe { $crate::pin::Pin::new_unchecked(&mut pinned) }
}
}
```
This is important, as there is currently no way to express it without hacks in Rust 2021 and before (see [hacky definition](2a06022951/library/core/src/pin.rs (L1947))), and no way to express it at all in Rust 2024 (see [issue](https://github.com/rust-lang/rust/issues/138718)).
## Fixing format_args!()
This will also allow us to express `format_args!()` in a way where one can assign the result to a variable, fixing a [long standing issue](https://github.com/rust-lang/rust/issues/92698):
```rust
let f = format_args!("Hello {name}!"); // error today, but accepted in the future! (after separate FCP)
```
## Experiment
The precise definition of `super let`, what happens for `super let x;` (without initializer), and whether to accept `super let _ = _ else { .. }` are still open questions, to be answered by the experiment.
Furthermore, once we have a more complete understanding of the feature, we might be able to come up with a better syntax. (Which could be just a different keywords, or an entirely different way of naming temporaries that doesn't involve a block and a (super) let statement.)
Misc query tweaks
Remove some redundant work around `cache_on_disk` and `ensure_ok`, since `Result<(), ErrorGuaranteed>` queries don't need to cache or recompute their "value" if they are only used for their result.
In the AST, currently we use `BinOpKind` within `ExprKind::AssignOp` and
`AssocOp::AssignOp`, even though this allows some nonsensical
combinations. E.g. there is no `&&=` operator. Likewise for HIR and
THIR.
This commit introduces `AssignOpKind` which only includes the ten
assignable operators, and uses it in `ExprKind::AssignOp` and
`AssocOp::AssignOp`. (And does similar things for `hir::ExprKind` and
`thir::ExprKind`.) This avoids the possibility of nonsensical
combinations, as seen by the removal of the `bug!` case in
`lang_item_for_binop`.
The commit is mostly plumbing, including:
- Adds an `impl From<AssignOpKind> for BinOpKind` (AST) and `impl
From<AssignOp> for BinOp` (MIR/THIR).
- `BinOpCategory` can now be created from both `BinOpKind` and
`AssignOpKind`.
- Replaces the `IsAssign` type with `Op`, which has more information and
a few methods.
- `suggest_swapping_lhs_and_rhs`: moves the condition to the call site,
it's easier that way.
- `check_expr_inner`: had to factor out some code into a separate
method.
I'm on the fence about whether avoiding the nonsensical combinations is
worth the extra code.
First, move the `lang_item_for_op` call from the top of
`lookup_op_method`'s body to its callsites. It makes those callsites a
little more verbose, but also means `lookup_op_method` no longer cares
whether it's handling a binop or unop. This lets us remove `Op` and
split `lang_item_for_op` into `lang_item_for_{bin,un}op`, which is a
little simpler.
This change is a prerequisite for adding the `ast::AssignOpKind` type in
a subsequent commit.
Rollup of 6 pull requests
Successful merges:
- #138992 (literal pattern lowering: use the pattern's type instead of the literal's in `const_to_pat`)
- #139211 (interpret: add a version of run_for_validation for &self)
- #139235 (`AstValidator` tweaks)
- #139237 (Add a dep kind for use of the anon node with zero dependencies)
- #139260 (Add dianqk to codegen reviewers)
- #139264 (Fix two incorrect turbofish suggestions)
r? `@ghost`
`@rustbot` modify labels: rollup
Fix two incorrect turbofish suggestions
This fixes#121901
This is my contribution to Rust, and my first contribution to a language parser that I didn't write myself.
I am a bit outside my depth here, so any constructive criticism is appreciated.
Add a dep kind for use of the anon node with zero dependencies
This adds a dep kind for use of the anon node with zero dependencies instead of making use of the null node. I don't think this matters, but it is nicer than random null nodes in the dep graph.
`AstValidator` tweaks
When I read through `AstValidator` there were several things that tripped me up, and made the code harder to understand than I would have liked. This PR addresses them. Best reviewed one commit at a time.
r? ``@davidtwco``
literal pattern lowering: use the pattern's type instead of the literal's in `const_to_pat`
This has two purposes:
- First, it enables removing the `treat_byte_string_as_slice` fields from `TypeckResults` and `ConstToPat`. A byte string pattern's type will be `&[u8]` when matching on a slice reference, so `const_to_pat` will lower it to a slice ref pattern. I believe this is tested by `tests/ui/match/pattern-deref-miscompile.rs`.
- Second, it will simplify the implementation of byte string literals in deref patterns. If byte string patterns can be given the type `[u8; N]` or `[u8]` during HIR typeck, then nothing needs to be changed in `const_to_pat` in order to lower the patterns `deref!(b"..."): Vec<u8>` and `deref!(b"..."): Box<[u8; 3]>`.
Implementation-wise, this uses `lit_to_const` to make a const with the pattern's type and the literal's valtree; that feels to me like the best way to make sure that the valtree representations of the pattern type and literal are the same. Though it may necessitate later changes to `lit_to_const` to accommodate giving byte string literal patterns non-reference types—would that be reasonable?
This unfortunately doesn't work for the `string_deref_patterns` feature (since that gives string literal patterns the `String` type), so I added a workaround for that. However, once `deref_patterns` supports string literals, it may be able to replace `string_deref_patterns`; the special case for `String` can removed at that point.
r? ``@oli-obk``
Move methods from `Map` to `TyCtxt`, part 5.
This eliminates all methods on `Map`. Actually removing `Map` will occur in a follow-up PR.
A follow-up to #137504.
r? `@Zalathar`
`for_each_assignment_mut` can skip assignment statements with side effects,
which can result in some assignment statements retrieving outdated value.
For example, it may skip a dereference assignment statement.
Various local trait item iteration cleanups
Adding a trait impl for `Foo` unconditionally affected all queries that are interested in a completely independent trait `Bar`. Perf has no effect on this. We probably don't have a good perf test for this tho.
r? `@compiler-errors`
I am unsure about 9d05efb66f as it doesn't improve anything wrt incremental, because we still do all the checks for valid `Drop` impls, which subsequently will still invoke many queries and basically keep the depgraph the same.
I want to do
9549077a47/compiler/rustc_middle/src/ty/trait_def.rs (L141)
but would leave that to a follow-up PR, this one changes enough things as it is
They are no longer needed.
This does slightly worsen the error message for a single test, but that
test contains code that is so badly broken that I'm not worried about
it.
`AstValidator` has several `with_*` methods, each one setting a field
that adjust how checking takes place for items within certain other
items. E.g. `with_in_trait_impl` is used to adjust the checking done on
items inside an `impl` item. Weirdly, the scopes used for most of the
`with_*` calls are very broad, and include things that aren't "inside"
the item, such as visibility, unsafety, and constness.
This commit minimizes the scope of these `with_*` calls so they only
apply to the things inside the item.
Rollup of 14 pull requests
Successful merges:
- #135295 (Check empty SIMD vector in inline asm)
- #138003 (Add the new `amx` target features and the `movrs` target feature)
- #138823 (rustc_target: RISC-V: add base `I`-related important extensions)
- #138913 (Remove even more instances of `@ts-expect-error` from search.js)
- #138941 (Do not mix normalized and unnormalized caller bounds when constructing param-env for `receiver_is_dispatchable`)
- #139060 (replace commit placeholder in vendor status with actual commit)
- #139102 (coverage: Avoid splitting spans during span extraction/refinement)
- #139191 (small opaque type/borrowck cleanup)
- #139200 (Skip suggest impl or dyn when poly trait is not a real trait)
- #139208 (fix dead link netbsd.md)
- #139210 (chore: remove redundant backtick)
- #139212 (Update mdbook to 0.4.48)
- #139214 (Tell rustfmt to use the 2024 edition in ./x.py fmt)
- #139225 (move autodiff from EnzymeAD/Enzyme to our rust-lang/Enzyme soft-fork)
r? `@ghost`
`@rustbot` modify labels: rollup
A bunch of span-related names in `AstValidator` don't end in `span`,
which goes against the usual naming conventions and makes the code
surprisingly hard to read. E.g. a name like `body` doesn't sound like
it's a span.
This commit adds `_span` suffixes.
Tell rustfmt to use the 2024 edition in ./x.py fmt
Most crates in this repo have been moved to the 2024 edition already. This also allows removing a rustfmt exclusion for a cg_clif test.
Skip suggest impl or dyn when poly trait is not a real trait
Fixes#139174
When `poly_trait_ref` is not a real trait, we should stop suggesting `impl` and `dyn` to avoid false positives. 3 cases were added to the ui test.
0b45675cfc/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs (L88-L93)
In the first commit, I submitted the test and passed it. In the second commit, I modified the code and we can see the changes in the test.
r? compiler
coverage: Avoid splitting spans during span extraction/refinement
This PR removes or simplifies some of the steps involved in extracting coverage-relevant spans from MIR, and preparing them for use in coverage instrumentation metadata.
A common theme is that we now try harder to avoid modifying or combining spans in non-trivial ways, because those modifications present the most risk for weird behaviour or ICEs.
The main changes are:
- When extracting spans from MIR call terminators, try to restrict them to just the function name.
- Instead of splitting spans around “holes”, just discard any span that overlaps with a hole.
- Instead of splitting macro-invocation spans into two parts, truncate them to just the macro name and subsequent `!`.
---
This results in a lot of tiny changes to the spans that end up in coverage metadata, and a few changes to coverage reports. Judging by test snapshots, these changes appear to be quite minor in practice.
Do not mix normalized and unnormalized caller bounds when constructing param-env for `receiver_is_dispatchable`
See comments in code and in test I added.
r? `@BoxyUwU` since you reviewed the last PR, or reassign
Fixes#138937
rustc_target: RISC-V: add base `I`-related important extensions
Of ratified RISC-V features defined, this commit adds extensions satisfying following criteria:
* Formerly a part of the `I` extension and splitted thereafter (now ratified as `I` + `Zifencei` + `Zicsr` + `Zicntr` + `Zihpm`) or
* Dicoverable from newer versions of the Linux kernel and implemented as a part of `std_detect`'s feature (`Zihintpause`) and
* Available on LLVM 18.
This is based on [the latest ratified ISA Manuals (version 20240411)](https://lf-riscv.atlassian.net/wiki/spaces/HOME/pages/16154769/RISC-V+Technical+Specifications).
LLVM Definitions:
* [`Zifencei`](https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0/llvm/lib/Target/RISCV/RISCVFeatures.td#L133-L137)
* [`Zicsr`](https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0/llvm/lib/Target/RISCV/RISCVFeatures.td#L116-L120)
* [`Zicntr`](https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0/llvm/lib/Target/RISCV/RISCVFeatures.td#L122-L124)
* [`Zihpm`](https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0/llvm/lib/Target/RISCV/RISCVFeatures.td#L153-L155)
* [`Zihintpause`](https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0/llvm/lib/Target/RISCV/RISCVFeatures.td#L139-L144)
Additional (1):
One of those, `Zicsr`, is a dependency of many other ISA extensions and this commit adds correct dependencies to `Zicsr`.
Additional (2):
In RISC-V, `G` is an abbreviation of following extensions:
* `I`
* `M`
* `A`
* `F`
* `D`
* `Zicsr` (although implied by `F`)
* `Zifencei`
and all RISC-V targets with the `G` abbreviation and targets for Android / VxWorks are updated accordingly.
Note:
Android will require RVA22 (likely RVA22U64) and some more extensions, which is a superset of RV64GC. For VxWorks, all BSPs currently distributed by Wind River are for boards with RV64GC (this commit also updates `riscv32-wrs-vxworks` though).
--------
This is the version 4.
`Ztso` in the original proposal is removed on the PR version 2 due to the minimum LLVM version (non-experimental `Ztso` requires LLVM 19 while minimum LLVM version of Rust is 18). This is not back in PR version 3 and 4 after noticing adding `Ztso` is possible by checking host LLVM version because PR version 3 introduces compiler target changes (and adding more extensions would complicate the problems; sorry `Zihintpause`).
Version 4:
* Fixed some commit messages,
* Added Android / VxWorks targets to imply `G` and
* Added an implication from `Zve32x` to `Zicsr` (which makes all vector extension subsets to imply `Zicsr`)
since #138742 is now merged.
Related:
* #44839
(`riscv_target_feature`)
* #114544
(This PR can be a prerequisite of resolving a part of that tracking issue)
* #138742
(Touches the same place and vector extensions depend on `Zicsr`)
NOT Related but linked:
* #132618
(This PR won't be blocked by this issue since none of those extensions do not change the ABI)
`@rustbot` r? `@Amanieu`
`@rustbot` label +T-compiler +O-riscv +A-target-feature
Add the new `amx` target features and the `movrs` target feature
Adds 5 new `amx` target features included in LLVM20. These are guarded under `x86_amx_intrinsics` (#126622)
- `amx-avx512`
- `amx-fp8`
- `amx-movrs`
- `amx-tf32`
- `amx-transpose`
Adds the `movrs` target feature (from #137976).
`@rustbot` label O-x86_64 O-x86_32 T-compiler A-target-feature
r? `@Amanieu`
Of ratified RISC-V features defined, this commit adds extensions
satisfying following criteria:
* Formerly a part of the "I" extension and splitted thereafter
(now ratified as "I" + "Zifencei" + "Zicsr" + "Zicntr" + "Zihpm") or
* Dicoverable from newer versions of the Linux kernel and implemented
as a part of std_detect's feature ("Zihintpause").
This is based on the latest ratified ISA Manuals (version 20240411).
Additional (1):
One of those, "Zicsr", is a dependency of many other ISA extensions and
this commit adds correct dependencies to "Zicsr".
Additional (2):
In RISC-V, "G" is an abbreviation of following extensions:
* "I"
* "M"
* "A"
* "F"
* "D"
* "Zicsr" (although implied by "F")
* "Zifencei"
and all RISC-V targets with the "G" abbreviation and targets for Android /
VxWorks are updated accordingly.
Note:
Android will require RVA22 (likely RVA22U64) and some more extensions,
which is a superset of RV64GC. For VxWorks, all BSPs currently distributed
by Wind River are for boards with RV64GC (this commit also updates
riscv32-wrs-vxworks though).
Currently it uses `walk_item` on some item kinds. For other item kinds
it visits the fields individually. For the latter group, this commit
adds `visit_attrs_vis` and `visit_attrs_vis_ident` which bundle up
visits to the fields that don't need special handling. This makes it
clearer that they haven't been forgotten about.
Also, it's better to do the attribute visits at the start because
attributes precede the items in the source code. Because of this, a
couple of tests have their output improved: errors appear in an order
that matches the source code order.
Currently some code paths return early, while others fall through to the
`visit::walk_item` call, which is easy to overlook (I did, at first),
even with the explanatory comments.
This commit removes the early returns and moves the `visit::walk_item`
calls up where necessary. This makes the function easier to read and
slightly shorter.
Notes about tests:
- tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs: some messages are
now duplicated due to repeated parsing.
- tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs: ditto.
- `tests/ui/proc-macro/macro-rules-derive-cfg.rs`: the diff looks large
but the only difference is the insertion of a single
invisible-delimited group around a metavar.
- `tests/ui/attributes/nonterminal-expansion.rs`: a slight span
degradation, somehow related to the recent massive attr parsing
rewrite (#135726). I couldn't work out exactly what is going wrong,
but I don't think it's worth holding things up for a single slightly
suboptimal error message.
Feed HIR for by-move coroutine body def, since the inliner tries to read its attrs
See the comments in the test.
I'm surprised that nobody found this[^1] (edit: nvm haha), but you have to go out of your way to construct the by-move body and then inline it w/ a poll call, so I guess the inliner just never really gets into this situation before.
Fixes#134335
r? oli-obk
[^1]: Well, ````@eholk```` found this when working on the `iter! {}` macro, since it more dramatically affects those.
PassWrapper: adapt for llvm/llvm-project@94122d58fc77079a291a3d008914…
…006cb509d9db
We also have to remove the LLVM argument in cast-target-abi.rs for LLVM
21. I'm not really sure what the best approach here is since that test already uses revisions. We could also fork the test into a copy for LLVM 19-20 and another for LLVM 21, but what I did for now was drop the lint-abort-on-error flag to LLVM figuring that some coverage was better than none, but I'm happy to change this if that was a bad direction.
r? dianqk
````@rustbot```` label llvm-main
increment depth of nested obligations
properly fixes the root cause of #109268. While we didn't get hangs here before, I ended up encountering its root cause again with #138785.
r? types
Note potential but private items in show_candidates
Closes#138626 .
We should add potential private items to give ample hints.
And for the other seemingly false positive ` pub use crate:1️⃣:Foo;` should be kept because we don't know if the user wants to import other module's items or not, and therefore should be given the full option to do so.
r? compiler
remove `feature(inline_const_pat)`
Summarizing https://rust-lang.zulipchat.com/#narrow/channel/144729-t-types/topic/remove.20feature.28inline_const_pat.29.20and.20shared.20borrowck.
With https://github.com/rust-lang/types-team/issues/129 we will start to borrowck items together with their typeck parent. This is necessary to correctly support opaque types, blocking the new solver and TAIT/ATPIT stabilization with the old one. This means that we cannot really support `inline_const_pat` as they are implemented right now:
- we want to typeck inline consts together with their parent body to allow inference to flow both ways and to allow the const to refer to local regions of its parent.This means we also need to borrowck the inline const together with its parent as that's necessary to properly support opaque types
- we want the inline const pattern to participate in exhaustiveness checking
- to participate in exhaustiveness checking we need to evaluate it, which requires borrowck, which now relies on borrowck of the typeck root, which ends up checking exhaustiveness again. **This is a query cycle**.
There are 4 possible ways to handle this:
- stop typechecking inline const patterns together with their parent
- causes inline const patterns to be different than inline const exprs
- prevents bidirectional inference, we need to either fail to compile `if let const { 1 } = 1u32` or `if let const { 1u32 } = 1`
- region inference for inline consts will be harder, it feels non-trivial to support inline consts referencing local regions from the parent fn
- inline consts no longer participate in exhaustiveness checking. Treat them like `pat if pat == const { .. }` instead. We then only evaluate them after borrowck
- difference between `const { 1 }` and `const FOO: usize = 1; match x { FOO => () }`. This is confusing
- do they carry their weight if they are now just equivalent to using an if-guard
- delay exhaustiveness checking until after borrowck
- should be possible in theory, but is a quite involved change and may have some unexpected challenges
- remove this feature for now
I believe we should either delay exhaustiveness checking or remove the feature entirely. As moving exhaustiveness checking to after borrow checking is quite complex I think the right course of action is to fully remove the feature for now and to add it again once/if we've got that implementation figured out.
`const { .. }`-expressions remain stable. These seem to have been the main motivation for https://github.com/rust-lang/rfcs/issues/2920.
r? types
cc `@rust-lang/types` `@rust-lang/lang` #76001
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
`expand_test_case` looks for any item with a `#[test_case]` attribute
and adds a `test_path_symbol` attribute to it while also fiddling with
the item's ident's span.
This is pretty weird, because `#[test_case]` is only valid on
`fn`/`const`/`static` items, as far as I can tell. But you don't
currently get an error or warning if you use it on other kinds of items.
This commit changes things so that a `#[test_case]` item is modified
only if it is `fn`/`const`/`static`. This is relevant for moving idents
from `Item` to `ItemKind`, because some item kinds don't have an ident,
e.g. `impl` blocks.
The commit also does the following.
- Renames a local variable `test_id` as `test_ident`.
- Changes a `const` to `static` in
`tests/ui/custom_test_frameworks/full.rs` to give the `static` case
some test coverage.
- Adds a `struct` and `impl` to the same test to give some test coverage
to the non-affected item kinds. These have a `FIXME` comment
identifying the weirdness here. Hopefully this will be useful
breadcrumbs for somebody else in the future.
This is a way to shrink call spans that doesn't involve mixing different spans,
and avoids overlap with argument spans.
This patch also removes some low-value comments that were causing rustfmt to
ignore the match arms.
Fix `armv7-sony-vita-newlibeabihf` LLVM target triple
It was previously normalized by LLVM to `thumbv7a-vita-unknown-eabihf` (can be seen with `clang -target thumbv7a-vita-eabihf -v`), which seems wrong, as Vita is the OS name.
Motivation: To make it easier to verify that [`cc-rs`' conversion from `rustc` to Clang/LLVM triples](https://github.com/rust-lang/cc-rs/issues/1431) is correct.
CC target maintainers ``@nikarh,`` ``@pheki`` and ``@ZetaNumbers.``
r? jieyouxu
This is part of the implementation of `#[doc(keyword = "match")]`
attributes used by `std` to provide documentation for keywords.
`is_doc_keyword` currently does a crude keyword range test that's
intended to catch all keywords but misses `kw::Yeet`. This commit
changes it to use `Symbol` methods, including the new `is_weak` method
(required for `union`). `Symbol` methods are much less prone to falling
out of date if new keywords are added.
We also have to remove the LLVM argument in cast-target-abi.rs for LLVM
21. I'm not really sure what the best approach here is since that test
already uses revisions. We could also fork the test into a copy for LLVM
19-20 and another for LLVM 21, but what I did for now was drop the
lint-abort-on-error flag to LLVM figuring that some coverage was better
than none, but I'm happy to change this if that was a bad direction.
The above also applies for ffi-out-of-bounds-loads.rs.
r? dianqk
@rustbot label llvm-main
Rollup of 6 pull requests
Successful merges:
- #138176 (Prefer built-in sized impls (and only sized impls) for rigid types always)
- #138749 (Fix closure recovery for missing block when return type is specified)
- #138842 (Emit `unused_attributes` for `#[inline]` on exported functions)
- #139153 (Encode synthetic by-move coroutine body with a different `DefPathData`)
- #139157 (Remove mention of `exhaustive_patterns` from `never` docs)
- #139167 (Remove Amanieu from the libs review rotation)
r? `@ghost`
`@rustbot` modify labels: rollup
Encode synthetic by-move coroutine body with a different `DefPathData`
See the included test. In the first revision rpass1, we have an async closure `{closure#0}` which has a coroutine as a child `{closure#0}::{closure#0}`. We synthesize a by-move coroutine body, which is `{closure#0}::{closure#1}` which depends on the mir_built query, which depends on the typeck query.
In the second revision rpass2, we've replaced the coroutine-closure by a closure with two children closure. Notably, the def path of the second child closure is the same as the synthetic def id from the last revision: `{closure#0}::{closure#1}`. When type-checking this closure, we end up trying to compute its def_span, which tries to fetch it from the incremental cache; this will try to force the dependencies from the last run, which ends up forcing the mir_built query, which ends up forcing the typeck query, which ends up with a query cycle.
The problem here is that we really should never have used the same `DefPathData` for the synthetic by-move coroutine body, since it's not a closure. Changing the `DefPathData` will mean that we can see that the def ids are distinct, which means we won't try to look up the closure's def span from the incremental cache, which will properly skip replaying the node's dependencies and avoid a query cycle.
Fixes#139142
Emit `unused_attributes` for `#[inline]` on exported functions
I saw someone post a code sample that contained these two attributes, which immediately made me suspicious.
My suspicions were confirmed when I did a small test and checked the compiler source code to confirm that in these cases, `#[inline]` is indeed ignored (because you can't exactly `LocalCopy`an unmangled symbol since that would lead to duplicate symbols, and doing a mix of an unmangled `GloballyShared` and mangled `LocalCopy` instantiation is too complicated for our current instatiation mode logic, which I don't want to change right now).
So instead, emit the usual unused attribute lint with a message saying that the attribute is ignored in this position.
I think this is not 100% true, since I expect LLVM `inlinehint` to still be applied to such a function, but that's not why people use this attribute, they use it for the `LocalCopy` instantiation mode, where it doesn't work.
r? saethlin as the instantiation guy
Procedurally, I think this should be fine to merge without any lang involvement, as this only does a very minor extension to an existing lint.
Fix closure recovery for missing block when return type is specified
Firstly, fix the `is_array_like_block` condition to make sure we're actually recovering a mistyped *block* rather than some other delimited expression. This fixes#138748.
Secondly, split out the recovery of missing braces on a closure body into a separate recovery. Right now, the suggestion `"you might have meant to write this as part of a block"` originates from `suggest_fixes_misparsed_for_loop_head`, which feels kinda brittle and coincidental since AFAICT that recovery wasn't ever really intended to fix this.
We also can make this `MachineApplicable` in this case.
Fixes#138748
r? `@fmease` or reassign if you're busy/don't wanna review this
Prefer built-in sized impls (and only sized impls) for rigid types always
This PR changes the confirmation of `Sized` obligations to unconditionally prefer the built-in impl, even if it has nested obligations. This also changes all other built-in impls (namely, `Copy`/`Clone`/`DiscriminantKind`/`Pointee`) to *not* prefer built-in impls over param-env impls. This aligns the old solver with the behavior of the new solver.
---
In the old solver, we register many builtin candidates with the `BuiltinCandidate { has_nested: bool }` candidate kind. The precedence this candidate takes over other candidates is based on the `has_nested` field. We only prefer builtin impls over param-env candidates if `has_nested` is `false`
2b4694a698/compiler/rustc_trait_selection/src/traits/select/mod.rs (L1804-L1866)
Preferring param-env candidates when the builtin candidate has nested obligations *still* ends up leading to detrimental inference guidance, like:
```rust
fn hello<T>() where (T,): Sized {
let x: (_,) = Default::default();
// ^^ The `Sized` obligation on the variable infers `_ = T`.
let x: (i32,) = x;
// We error here, both a type mismatch and also b/c `T: Default` doesn't hold.
}
```
Therefore this PR adjusts the candidate precedence of `Sized` obligations by making them a distinct candidate kind and unconditionally preferring them over all other candidate kinds.
Special-casing `Sized` this way is necessary as there are a lot of traits with a `Sized` super-trait bound, so a `&'a str: From<T>` where-bound results in an elaborated `&'a str: Sized` bound. People tend to not add explicit where-clauses which overlap with builtin impls, so this tends to not be an issue for other traits.
We don't know of any tests/crates which need preference for other builtin traits. As this causes builtin impls to diverge from user-written impls we would like to minimize the affected traits. Otherwise e.g. moving impls for tuples to std by using variadic generics would be a breaking change. For other builtin impls it's also easier for the preference of builtin impls over where-bounds to result in issues.
---
There are two ways preferring builtin impls over where-bounds can be incorrect and undesirable:
- applying the builtin impl results in undesirable region constraints. E.g. if only `MyType<'static>` implements `Copy` then a goal like `(MyType<'a>,): Copy` would require `'a == 'static` so we must not prefer it over a `(MyType<'a>,): Copy` where-bound
- this is mostly not an issue for `Sized` as all `Sized` impls are builtin and don't add any region constraints not already required for the type to be well-formed
- however, even with `Sized` this is still an issue if a nested goal also gets proven via a where-bound: [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=30377da5b8a88f654884ab4ebc72f52b)
- if the builtin impl has associated types, we should not prefer it over where-bounds when normalizing that associated type. This can result in normalization adding more region constraints than just proving trait bounds. https://github.com/rust-lang/rust/issues/133044
- not an issue for `Sized` as it doesn't have associated types.
r? lcnr
Revert "Rollup merge of #136127 - WaffleLapkin:dyn_ptr_unwrap_cast, r=compiler-errors"
...not permanently tho. Just until we can land something like #138542, which will fix the underlying perf issues (https://github.com/rust-lang/rust/pull/136127#issuecomment-2743891744). I just don't want this to land on beta and have people rely on this behavior if it'll need some reworking for it to be implemented performantly.
r? `@WaffleLapkin` or reassign -- sorry for reverting ur pr! i'm working on getting it re-landed soon :>
hygiene: Rewrite `apply_mark_internal` to be more understandable
The previous implementation allocated new `SyntaxContext`s in the inverted order, and it was generally very hard to understand why its result matches what the `opaque` and `opaque_and_semitransparent` field docs promise.
```rust
/// This context, but with all transparent and semi-transparent expansions filtered away.
opaque: SyntaxContext,
/// This context, but with all transparent expansions filtered away.
opaque_and_semitransparent: SyntaxContext,
```
It also couldn't be easily reused for the case where the context id is pre-reserved like in #129827.
The new implementation tries to follow the docs in a more straightforward way.
I did the transformation in small steps, so it indeed matches the old implementation, not just the docs.
So I suggest reading only the new version.
Improve hir_pretty for struct expressions.
While working on https://github.com/rust-lang/rust/pull/139131 I noticed the hir pretty printer outputs an empty line between each field, and is also missing a space before the `{` and the `}`:
```rust
let a =
StructWithSomeFields{
field_1: 1,
field_2: 2,
field_3: 3,
field_4: 4,
field_5: 5,
field_6: 6,};
let a = StructWithSomeFields{ field_1: 1, field_2: 2, ..a};
```
This changes it to:
```rust
let a =
StructWithSomeFields {
field_1: 1,
field_2: 2,
field_3: 3,
field_4: 4,
field_5: 5,
field_6: 6 };
let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a };
```
Remove attribute `#[rustc_error]`
It was an ancient way to write `check-pass` tests, but now it's no longer necessary (except for the `delayed_bug_from_inside_query` flavor, which is retained).
Simplify expansion for format_args!().
Instead of calling `Placeholder::new()`, we can just use a struct expression directly.
Before:
```rust
Placeholder::new(…, …, …, …)
```
After:
```rust
Placeholder {
position: …,
flags: …,
width: …,
precision: …,
}
```
(I originally avoided the struct expression, because `Placeholder` had a lot of fields. But now that https://github.com/rust-lang/rust/pull/136974 is merged, it only has four fields left.)
This will make the `fmt` argument to `fmt::Arguments::new_v1_formatted()` a candidate for const promotion, which is important if we ever hope to tackle https://github.com/rust-lang/rust/issues/92698 (It doesn't change anything yet though, because the `args` argument to `fmt::Arguments::new_v1_formatted()` is not const-promotable.)
Subtree sync for rustc_codegen_cranelift
The main highlights this time are a Cranelift update, support for `#[target_feature]` for inline asm on arm64 and some vendor intrinsic fixes for arm64.
[AIX] Ignore linting on repr(C) structs with repr(packed) or repr(align(n))
This PR updates the lint added in 9b40bd7 to ignore repr(C) structs that also have repr(packed) or repr(align(n)).
As these representations can be modifiers on repr(C), it is assumed that users that add these should know what they are doing, and thus the the lint should not warn on the respective structs. For example, for the time being, using repr(packed) and manually padding a repr(C) struct can be done to correctly align struct members on AIX.
Instead of calling new(), we can just use a struct expression directly.
Before:
Placeholder::new(…, …, …, …)
After:
Placeholder {
position: …,
flags: …,
width: …,
precision: …,
}
Set `target_vendor = "openwrt"` on `mips64-openwrt-linux-musl`
OpenWRT is a Linux distribution for embedded network devices. The target name contains `openwrt`, so we should set `cfg(target_vendor = "openwrt")`.
This is similar to what other Linux distributions do (the only one in-tree is `x86_64-unikraft-linux-musl`, but that sets `target_vendor = "unikraft"`).
Motivation: To make correctly [parsing target names](https://github.com/rust-lang/cc-rs/pull/1413) simpler.
Fixes https://github.com/rust-lang/rust/issues/131165.
CC target maintainer `@Itus-Shield`
Fix `uclibc` LLVM target triples
`uclibc` is not an environment understood by LLVM, it is only a concept in Clang that can be selected with `-muclibc` (it affects which dynamic linker is passed to the static linker's `-dynamic-linker` flag).
In fact, using `uclibcgnueabi`/`uclibc` is actively harmful, as it prevents LLVM from seeing that the target is gnu-like; we should use `gnueabi`/`gnu` directly instead.
Motivation: To make it easier to verify that [`cc-rs`' conversion from `rustc` to Clang/LLVM triples](https://github.com/rust-lang/cc-rs/issues/1431) is correct.
**There are no target maintainers for these targets.** So I'll CC ``@lancethepants`` and ``@skrap`` who maintain the related `armv7-unknown-linux-uclibceabi` and `armv7-unknown-linux-uclibceabihf` (both of which already pass `-gnu` instead of `-uclibc`) in case they have any insights.
r? jieyouxu
Remove `terminating_scopes` hash set.
Instead of inserting and checking ids in a hashset, we can just pass a boolean as argument.
For example:
```diff
- visitor.terminating_scopes.insert(arm.hir_id.local_id);
- visitor.enter_node_scope_with_dtor(arm.hir_id.local_id);
+ visitor.enter_node_scope_with_dtor(arm.hir_id.local_id, true);
```
Do not treat lifetimes from parent items as influencing child items
```rust
struct A;
impl Bar<'static> for A {
const STATIC: &str = "";
// ^ no future incompat warning
}
```
has no future incompat warning, because there is no ambiguity. But
```rust
struct C;
impl Bar<'_> for C {
// ^^ this lifeimte
const STATIC: &'static str = {
struct B;
impl Bar<'static> for B {
const STATIC: &str = "";
// causes ^ to emit a future incompat warning
}
""
};
}
```
had one before this PR, because the impl for `B` (which is just a copy of `A`) thought it was influenced by a lifetime on the impl for `C`.
I double checked all other `lifetime_ribs` iterations and all of them do check for `Item` boundaries. This feels very fragile tho, and ~~I think we should do not even be able to see ribs from parent items, but that's a different refactoring that I'd rather not do at the same time as a bugfix~~. EDIT: ah nevermind, this is needed for improving diagnostics like "use of undeclared lifetime" being "can't use generic parameters from outer item" instead.
r? `@compiler-errors`
Remove ScopeDepth
The scope depth was tracked, but never seemed to be used for anything.
Every single place that used `(Scope, ScopeDepth)`, matched it on `(p, _)`.
rustc_resolve: fix instability in lib.rmeta contents
rust-lang/rust@23032f31c9 accidentally introduced some nondeterminism in the ordering of lib.rmeta files, which we caught in our bazel-based builds only recently due to being further behind than normal. In my testing, this fixes the issue.
Avoid wrapping constant allocations in packed structs when not necessary
This way LLVM will set the string merging flag if the alloc is a nul terminated string, reducing binary sizes.
try-job: armhf-gnu