Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix false-positive in expr_or_init and in the invalid_from_utf8 lint #138360

Merged
merged 1 commit into from
Mar 12, 2025

Conversation

Urgau
Copy link
Member

@Urgau Urgau commented Mar 11, 2025

This PR fixes the logic for finding initializer in the expr_or_init and expr_or_init_with_outside_body functions.

If the binding were to be mutable (let mut), the logic wouldn't consider that the initializer expression could have been modified and would return the init expression even-trough multiple subsequent assignments could have been done.

Example:

let mut a = [99, 108, 130, 105, 112, 112]; // invalid, not UTF-8
loop {
    a = *b"clippy"; // valid
    break;
}
std::str::from_utf8_mut(&mut a); // currently warns, with this PR it doesn't

This PR modifies the logic to excludes mutable let bindings.

Found when using expr_or_init in #119220.

r? compiler

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 11, 2025
Copy link
Member

@wesleywiser wesleywiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=me with nits addressed 🙂

Comment on lines +134 to +135
// false-positive, so until we can reliably avoid those false
// postive we don't lint on them. Example of FP below.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously, this is out of scope for this PR, but I'm curious why this PR is implemented as a HIR analysis instead of a MIR analysis? We have a dataflow framework for MIR that can answer these kinds of questions ("do we definitely know the value of this variable at this point in the program?") and it seems like it would be much simpler to write this as a MIR pass.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expr_or_init method came from clippy, same for invalid_from_utf8 which also came from clippy and both of them were using the HIR, so there is a bit a historical precedent.

As for implementing the lint as a MIR lint, it could probably be done, but I also remember MIR lints being more tricky to do, in part because MIR is much less like surface Rust than MIR is but also because the cargo check/build difference of MIR lints makes MIR lints less attractive; I don't know if it would apply here. I will have to check it.

@Urgau Urgau force-pushed the fix-fp-expr_or_init branch from 0c6e9ad to faa5b3f Compare March 11, 2025 20:57
@Urgau
Copy link
Member Author

Urgau commented Mar 11, 2025

@bors r=wesleywiser rollup

@bors
Copy link
Contributor

bors commented Mar 11, 2025

📌 Commit faa5b3f has been approved by wesleywiser

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 11, 2025
jieyouxu added a commit to jieyouxu/rust that referenced this pull request Mar 12, 2025
…ywiser

Fix false-positive in `expr_or_init` and in the `invalid_from_utf8` lint

This PR fixes the logic for finding initializer in the `expr_or_init` and `expr_or_init_with_outside_body` functions.

If the binding were to be mutable (`let mut`), the logic wouldn't consider that the initializer expression could have been modified and would return the init expression even-trough multiple subsequent assignments could have been done.

Example:
```rust
let mut a = [99, 108, 130, 105, 112, 112]; // invalid, not UTF-8
loop {
    a = *b"clippy"; // valid
    break;
}
std::str::from_utf8_mut(&mut a); // currently warns, with this PR it doesn't
```

This PR modifies the logic to excludes mutable let bindings.

Found when using `expr_or_init` in rust-lang#119220.

r? compiler
jieyouxu added a commit to jieyouxu/rust that referenced this pull request Mar 12, 2025
…ywiser

Fix false-positive in `expr_or_init` and in the `invalid_from_utf8` lint

This PR fixes the logic for finding initializer in the `expr_or_init` and `expr_or_init_with_outside_body` functions.

If the binding were to be mutable (`let mut`), the logic wouldn't consider that the initializer expression could have been modified and would return the init expression even-trough multiple subsequent assignments could have been done.

Example:
```rust
let mut a = [99, 108, 130, 105, 112, 112]; // invalid, not UTF-8
loop {
    a = *b"clippy"; // valid
    break;
}
std::str::from_utf8_mut(&mut a); // currently warns, with this PR it doesn't
```

This PR modifies the logic to excludes mutable let bindings.

Found when using `expr_or_init` in rust-lang#119220.

r? compiler
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 12, 2025
Rollup of 25 pull requests

Successful merges:

 - rust-lang#134076 (Stabilize `std::io::ErrorKind::InvalidFilename`)
 - rust-lang#136842 (Add libstd support for Trusty targets)
 - rust-lang#137314 (change definitely unproductive cycles to error)
 - rust-lang#137504 (Move methods from Map to TyCtxt, part 4.)
 - rust-lang#137621 (Add std support to cygwin target)
 - rust-lang#137701 (Convert `ShardedHashMap` to use `hashbrown::HashTable`)
 - rust-lang#138109 (make precise capturing args in rustdoc Json typed)
 - rust-lang#138161 (Add PeekMut::refresh)
 - rust-lang#138162 (Update the standard library to Rust 2024)
 - rust-lang#138174 (Elaborate trait assumption in `receiver_is_dispatchable`)
 - rust-lang#138175 (Support rmeta inputs for --crate-type=bin --emit=obj)
 - rust-lang#138269 (uefi: fs: Implement FileType, FilePermissions and FileAttr)
 - rust-lang#138313 (Update books)
 - rust-lang#138318 (Rustdoc: remove a bunch of `@ts-expect-error` from main.js)
 - rust-lang#138331 (Use `RUSTC_LINT_FLAGS` more)
 - rust-lang#138333 (Rebuild llvm spuriously less frequently)
 - rust-lang#138343 (Enable `f16` tests for `powf`)
 - rust-lang#138345 (Some autodiff cleanups)
 - rust-lang#138346 (naked functions: on windows emit `.endef` without the symbol name)
 - rust-lang#138347 (Reduce `kw::Empty` usage, part 2)
 - rust-lang#138360 (Fix false-positive in `expr_or_init` and in the `invalid_from_utf8` lint)
 - rust-lang#138371 (Update compiletest's `has_asm_support` to match rustc)
 - rust-lang#138372 (Refactor `pick2_mut` & `pick3_mut` to use `get_disjoint_mut`)
 - rust-lang#138376 (Item-related cleanups)
 - rust-lang#138377 (Remove unnecessary lifetime from `PatInfo`.)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 12, 2025
…iaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#138161 (Add PeekMut::refresh)
 - rust-lang#138174 (Elaborate trait assumption in `receiver_is_dispatchable`)
 - rust-lang#138313 (Update books)
 - rust-lang#138347 (Reduce `kw::Empty` usage, part 2)
 - rust-lang#138360 (Fix false-positive in `expr_or_init` and in the `invalid_from_utf8` lint)
 - rust-lang#138372 (Refactor `pick2_mut` & `pick3_mut` to use `get_disjoint_mut`)
 - rust-lang#138376 (Item-related cleanups)
 - rust-lang#138377 (Remove unnecessary lifetime from `PatInfo`.)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 12, 2025
…iaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#138161 (Add PeekMut::refresh)
 - rust-lang#138174 (Elaborate trait assumption in `receiver_is_dispatchable`)
 - rust-lang#138313 (Update books)
 - rust-lang#138347 (Reduce `kw::Empty` usage, part 2)
 - rust-lang#138360 (Fix false-positive in `expr_or_init` and in the `invalid_from_utf8` lint)
 - rust-lang#138372 (Refactor `pick2_mut` & `pick3_mut` to use `get_disjoint_mut`)
 - rust-lang#138376 (Item-related cleanups)
 - rust-lang#138377 (Remove unnecessary lifetime from `PatInfo`.)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit b849aa9 into rust-lang:master Mar 12, 2025
6 checks passed
@rustbot rustbot added this to the 1.87.0 milestone Mar 12, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Mar 12, 2025
Rollup merge of rust-lang#138360 - Urgau:fix-fp-expr_or_init, r=wesleywiser

Fix false-positive in `expr_or_init` and in the `invalid_from_utf8` lint

This PR fixes the logic for finding initializer in the `expr_or_init` and `expr_or_init_with_outside_body` functions.

If the binding were to be mutable (`let mut`), the logic wouldn't consider that the initializer expression could have been modified and would return the init expression even-trough multiple subsequent assignments could have been done.

Example:
```rust
let mut a = [99, 108, 130, 105, 112, 112]; // invalid, not UTF-8
loop {
    a = *b"clippy"; // valid
    break;
}
std::str::from_utf8_mut(&mut a); // currently warns, with this PR it doesn't
```

This PR modifies the logic to excludes mutable let bindings.

Found when using `expr_or_init` in rust-lang#119220.

r? compiler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants