simplify_cfg: rename some passes so that they make more sense
I was extremely confused by `SimplifyCfg::ElaborateDrops`, since it runs way later than drop elaboration. It is used e.g. in `mir-opt/retag.rs` even though that pass doesn't care about drop elaboration at all.
"Early opt" is also very confusing since that makes it sounds like it runs early during optimizations, i.e. on runtime MIR, but actually it runs way before that.
So I decided to rename
- early-opt -> post-analysis
- elaborate-drops -> pre-optimizations
I am open to other suggestions.
Detect when move of !Copy value occurs within loop and should likely not be cloned
When encountering a move error on a value within a loop of any kind,
identify if the moved value belongs to a call expression that should not
be cloned and avoid the semantically incorrect suggestion. Also try to
suggest moving the call expression outside of the loop instead.
```
error[E0382]: use of moved value: `vec`
--> $DIR/recreating-value-in-loop-condition.rs:6:33
|
LL | let vec = vec!["one", "two", "three"];
| --- move occurs because `vec` has type `Vec<&str>`, which does not implement the `Copy` trait
LL | while let Some(item) = iter(vec).next() {
| ----------------------------^^^--------
| | |
| | value moved here, in previous iteration of loop
| inside of this loop
|
note: consider changing this parameter type in function `iter` to borrow instead if owning the value isn't necessary
--> $DIR/recreating-value-in-loop-condition.rs:1:17
|
LL | fn iter<T>(vec: Vec<T>) -> impl Iterator<Item = T> {
| ---- ^^^^^^ this parameter takes ownership of the value
| |
| in this function
help: consider moving the expression out of the loop so it is only moved once
|
LL ~ let mut value = iter(vec);
LL ~ while let Some(item) = value.next() {
|
```
We use the presence of a `break` in the loop that would be affected by
the moved value as a heuristic for "shouldn't be cloned".
Fix https://github.com/rust-lang/rust/issues/121466.
---
*Point at continue and break that might be in the wrong place*
Sometimes move errors are because of a misplaced `continue`, but we didn't
surface that anywhere. Now when there are more than one set of nested loops
we show them out and point at the `continue` and `break` expressions within
that might need to go elsewhere.
```
error[E0382]: use of moved value: `foo`
--> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18
|
LL | for foo in foos {
| ---
| |
| this reinitialization might get skipped
| move occurs because `foo` has type `String`, which does not implement the `Copy` trait
...
LL | for bar in &bars {
| ---------------- inside of this loop
...
LL | baz.push(foo);
| --- value moved here, in previous iteration of loop
...
LL | qux.push(foo);
| ^^^ value used here after move
|
note: verify that your loop breaking logic is correct
--> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17
|
LL | for foo in foos {
| ---------------
...
LL | for bar in &bars {
| ----------------
...
LL | continue;
| ^^^^^^^^ this `continue` advances the loop at line 33
help: consider moving the expression out of the loop so it is only moved once
|
LL ~ let mut value = baz.push(foo);
LL ~ for bar in &bars {
LL |
...
LL | if foo == *bar {
LL ~ value;
|
help: consider cloning the value if the performance cost is acceptable
|
LL | baz.push(foo.clone());
| ++++++++
```
Fix https://github.com/rust-lang/rust/issues/92531.
collector: move ensure_sufficient_stack out of the loop
According to the docs this call has some overhead to putting it inside the loop doesn't seem like a good idea.
r? `@oli-obk`
Sometimes move errors are because of a misplaced `continue`, but we didn't
surface that anywhere. Now when there are more than one set of nested loops
we show them out and point at the `continue` and `break` expressions within
that might need to go elsewhere.
```
error[E0382]: use of moved value: `foo`
--> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18
|
LL | for foo in foos {
| ---
| |
| this reinitialization might get skipped
| move occurs because `foo` has type `String`, which does not implement the `Copy` trait
...
LL | for bar in &bars {
| ---------------- inside of this loop
...
LL | baz.push(foo);
| --- value moved here, in previous iteration of loop
...
LL | qux.push(foo);
| ^^^ value used here after move
|
note: verify that your loop breaking logic is correct
--> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17
|
LL | for foo in foos {
| ---------------
...
LL | for bar in &bars {
| ----------------
...
LL | continue;
| ^^^^^^^^ this `continue` advances the loop at line 33
help: consider moving the expression out of the loop so it is only moved once
|
LL ~ let mut value = baz.push(foo);
LL ~ for bar in &bars {
LL |
...
LL | if foo == *bar {
LL ~ value;
|
help: consider cloning the value if the performance cost is acceptable
|
LL | baz.push(foo.clone());
| ++++++++
```
Fix#92531.
When encountering a move error on a value within a loop of any kind,
identify if the moved value belongs to a call expression that should not
be cloned and avoid the semantically incorrect suggestion. Also try to
suggest moving the call expression outside of the loop instead.
```
error[E0382]: use of moved value: `vec`
--> $DIR/recreating-value-in-loop-condition.rs:6:33
|
LL | let vec = vec!["one", "two", "three"];
| --- move occurs because `vec` has type `Vec<&str>`, which does not implement the `Copy` trait
LL | while let Some(item) = iter(vec).next() {
| ----------------------------^^^--------
| | |
| | value moved here, in previous iteration of loop
| inside of this loop
|
note: consider changing this parameter type in function `iter` to borrow instead if owning the value isn't necessary
--> $DIR/recreating-value-in-loop-condition.rs:1:17
|
LL | fn iter<T>(vec: Vec<T>) -> impl Iterator<Item = T> {
| ---- ^^^^^^ this parameter takes ownership of the value
| |
| in this function
help: consider moving the expression out of the loop so it is only moved once
|
LL ~ let mut value = iter(vec);
LL ~ while let Some(item) = value.next() {
|
```
We use the presence of a `break` in the loop that would be affected by
the moved value as a heuristic for "shouldn't be cloned".
Fix#121466.
Don't show suggestion if slice pattern is not top-level
Close#120605
Don't show suggestion to add slicing (`[..]`) if the slice pattern is enclosed by struct like `Struct { a: [] }`.
For example, current rustc makes a suggestion as a comment. However, the pattern `a: []` is wrong, not scrutinee `&self.a`.
In this case, the structure type `a: Vec<Struct>` and the pattern `a: []` are different so I think the pattern should be fixed, not the scrutinee.
If the parent of the pattern that was the target of the error is a structure, I made the compiler not show a suggestion.
```rs
pub struct Struct {
a: Vec<Struct>,
}
impl Struct {
pub fn test(&self) {
if let [Struct { a: [] }] = &self.a {
// ^^^^^^^^^^^^^^^^^^ ------- help: consider slicing here: `&self.a[..]`
println!("matches!")
}
}
}
```
Note:
* ~~I created `PatInfo.history` to store parent-child relationships for patterns, but this may be inefficient.~~
* I use two fields `parent_kind` and `current_kind` instead of vec. It may not performance issue.
* Currently only looking at direct parents, but may need to look at deeper ancestry.
Move check-cfg diagnostic logic into a separate file
as well as adding some triagebot mentions (for me) for check-cfg related files.
``@rustbot`` label +F-check-cfg
Register LLVM handlers for bad-alloc / OOM
LLVM's default bad-alloc handler may throw if exceptions are enabled,
and `operator new` isn't hooked at all by default. Now we register our
own handler that prints a message similar to fatal errors, then aborts.
We also call the function that registers the C++ `std::new_handler`.
Fixes#121305
Cc llvm/llvm-project#85281
r? ``@nikic``
rustc-metadata: Store crate name in self-profile of metadata_register_crate
When profiling a build of Zed, I found myself in need of names of crates that take the longest to register in downstream crates.
Remove obsolete parameter `speculative` from `instantiate_poly_trait_ref`
In #122527 I totally missed that `speculative` has become obsolete with the removal of `hir_trait_to_predicates` / due to #113671.
Fixes#114635.
r? `@compiler-errors`
Delegation: fix ICE on duplicated associative items
Currently, functions delegation is only supported for delegation items with early resolved paths e.g. free functions and trait methods. During name resolution, information about function signatures is collected, including the number of parameters and whether there are self arguments. This information is then used when lowering from a delegation item into a regular function(`rustc_ast_lowering/src/delegation.rs`). The signature is usually inherited from path resolution id(`path_id`). However, in the case of trait impls `path_id` and `item_id` may be different:
```rust
trait Trait {
fn foo(&self) -> u32 { 0 }
}
struct S;
mod to_reuse {
use crate::S;
pub fn foo(_: &S) -> u32 { 0 }
}
impl Trait for S {
reuse to_reuse::foo { self }
//~^ The signature should be inherited from item id instead of resolution id
}
```
Let's now consider an example from [issue](https://github.com/rust-lang/rust/issues/119920). Due to duplicated associative elements partial resolution for one of them will not be recorded:
9023f908cf/compiler/rustc_resolve/src/late.rs (L3153-L3162)
Which leads to an incorrect `is_in_trait_impl`
9023f908cf/compiler/rustc_ast_lowering/src/item.rs (L981-L986)
Which leads to an incorrect id for signature inheritance
9023f908cf/compiler/rustc_ast_lowering/src/delegation.rs (L99-L105)
Which lead to an ICE from original issue.
This patch fixes wrong `is_in_trait_impl` calculation.
fixes https://github.com/rust-lang/rust/issues/119920
Split refining_impl_trait lint into _reachable, _internal variants
As discussed in https://github.com/rust-lang/rust/issues/119535#issuecomment-1909352040:
> We discussed this today in triage and developed a consensus to:
>
> * Add a separate lint against impls that refine a return type defined with RPITIT even when the trait is not crate public.
> * Place that in a lint group along with the analogous crate public lint.
> * Create an issue to solicit feedback on these lints (or perhaps two separate ones).
> * Have the warnings displayed with each lint reference this issue in a similar manner to how we do that today with the required `Self: '0'` bound on GATs.
> * Make a note to review this feedback on 2-3 release cycles.
This points users to https://github.com/rust-lang/rust/issues/121718 to leave feedback.
Add `wasm_c_abi` `future-incompat` lint
This is a warning that will tell users to update to `wasm-bindgen` v0.2.88, which supports spec-compliant C ABI.
The idea is to prepare for a future where Rust will switch to the spec-compliant C ABI by default; so not to break everyone's world, this warning is introduced.
Addresses #71871.
Stop walking the bodies of statics for reachability, and evaluate them instead
cc `@saethlin` `@RalfJung`
cc #119214
This reuses the `DefIdVisitor` from `rustc_privacy`, because they basically try to do the same thing.
This PR's changes can probably be extended to constants, too, but let's tackle that separately, it's likely more involved.
`f16` and `f128` step 3: compiler support & feature gate
Continuation of https://github.com/rust-lang/rust/pull/121841, another portion of https://github.com/rust-lang/rust/pull/114607
This PR exposes the new types to the world and adds a feature gate. Marking this as a draft because I need some feedback on where I did the feature gate check. It also does not yet catch type via suffixed literals (so the feature gate test will fail, probably some others too because I haven't belssed).
If there is a better place to check all types after resolution, I can do that. If not, I figure maybe I can add a second gate location in AST when it checks numeric suffixes.
Unfortunately I still don't think there is much testing to be done for correctness (codegen tests or parsed value checks) until we have basic library support. I think that will be the next step.
Tracking issue: https://github.com/rust-lang/rust/issues/116909
r? `@compiler-errors`
cc `@Nilstrieb`
`@rustbot` label +F-f16_and_f128
The bad-alloc installer was incorrectly asserting that the other handler
isn't set yet, instead of checking its own, but we can avoid that by
changing the order we install them.
Ref: https://github.com/llvm/llvm-project/issues/83040
LLVM's default bad-alloc handler may throw if exceptions are enabled,
and `operator new` isn't hooked at all by default. Now we register our
own handler that prints a message similar to fatal errors, then aborts.
We also call the function that registers the C++ `std::new_handler`.
Adding support of quirky filesystems occuring in virtualised settings not
having full POSIX support for memory mapped files. Example: current virtiofs
with cache disabled, occuring in Incus/LXD or Kata Containers. Has been
hitting various virtualised filesystems since 2016, depending on their levels
of maturity at the time. The situation will perhaps improve when virtiofs DAX
support patches will have made it into the qemu mainline.
On a reliability level, using the MAP_PRIVATE sycall flag instead of the
MAP_SHARED syscall flag for the mmap() system call does have some undefined
behaviour when the caller update the memory mapping of the mmap()ed file, but
MAP_SHARED does allow not only the calling process but other processes to
modify the memory mapping. Thus, in the current context, using MAP_PRIVATE
copy-on-write is marginally more reliable than MAP_SHARED.
This discussion of reliability is orthogonal to the type system enforced safety
policy of rust, which does not claim to handle memory modification of memory
mapped files triggered through the operating system and not the running rust
process.
Safe Transmute: Use 'not yet supported', not 'unspecified' in errors
We can (and will) support analyzing the transmutability of types whose layouts aren't completely specified by its repr. This change ensures that the error messages remain sensible after this support lands.
r? ``@compiler-errors``
Add `#![rustc_never_type_mode = "..."]` crate-level attribute to allow experimenting
Demonstrating how different approaches with the never type work is somewhat hard when you can't actually provide a runnable example. Let's add features that change the fallback behavior.
This adds `#![rustc_never_type_mode = "no_fallback"]` and `#![rustc_never_type_mode = "fallback_to_never"]`, but I also plan to add others (in future PRs).
cc ``@traviscross``
r? ``@compiler-errors``