-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Introduce needless_option_take lint #8665
Conversation
r? @llogiq (rust-highfive has picked a reviewer for you, use r? to override) |
Hi there! Thank you for making clippy better. If you need anything, let me know. |
6e245a8
to
68d61fb
Compare
68d61fb
to
0c2f4ef
Compare
I think this is ready |
Is it normal for these to fail? |
The test output can be pretty large but you want to look out for the diffs in them, e.g. https://github.com/rust-lang/rust-clippy/runs/5955895411?check_suite_focus=true#step:7:939 |
I see, |
Since the lint is enabled by default it's also run on all the existing test files. The diff there is between the expected stderr in the .stderr file and the result of running clippy on it |
Right!
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The redundant closure errors are part of the existing tests, you can see them in https://github.com/rust-lang/rust-clippy/blob/c7e68638431b2a6639fcbeb44de790619de3b9b1/tests/ui/eta.stderr
The diff shown is between that file and the result of running clippy with your additions on https://github.com/rust-lang/rust-clippy/blob/c7e68638431b2a6639fcbeb44de790619de3b9b1/tests/ui/eta.rs. It shows a new error pointing at
Line 118 in c7e6863
Thunk(Box::new(move || option.take().unwrap()())) |
This is a false positive though, rather than updating the tests the lint should be changed so it doesn't fire, we don't want to be linting things of the form option.take()
e1830d0
to
e9c5e50
Compare
From the failed CI, the lint message should start with a lowercase - Called `Option::take()` on a temporary value
+ called `Option::take()` on a temporary value |
I know, just didn't have time to apply it yet. |
☔ The latest upstream changes (presumably #8624) made this pull request unmergeable. Please resolve the merge conflicts. |
Can I get some reviews again ? Meanwhile I rebase the branch |
1c3f544
to
cf28136
Compare
Do we need an MSRV for rust features from rust 1.0.0 ? https://doc.rust-lang.org/src/core/option.rs.html#1550 |
I don't think so, we don't support pre-1.0.0 Rust versions. |
This lint checks if Option::take() is used on a temporary value (a value that is not of type &mut Option and that is not a Place expression) to suggest omitting take()
eb9a327
to
fe4299f
Compare
The implemented checks are for checking if the expression is either of type `Option` and isn't a syntactical place
This implements a machine applicable suggestion to any matched usage of `.as_ref().take()``
This changes the lint from the suspicious category to the complexity category
This fixes the errors occuring while running the ui tests
Instead of type checking the entire expression (causing a false positive), only type check for a subset of the expression (the receiver of the matched function: `take()`)
This checks if the expression has one of `core`, `option`, `Option` or `as_ref` in its path, this avoids false positives
This adds test to make sure correct behavior of lint - The first test's option variable is not a temporary variable - The second test does not make usage of `take()` - The third test makes usage of `take()` and uses a temporary variable
fe4299f
to
2903b56
Compare
So wait, my code now currently does not check for temporaries, just as_ref, that's not what I had in mind at first |
That's ok. Checking for temporaries is a bit harder, as you'll have to check if the bindings are used later on (which |
Ok then let's do this, I will try to tackle the next step. |
Thank you! @bors r+ |
📌 Commit 2903b56 has been approved by |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
@llogiq do you mind pointing me to where I need to look at to get started on the followup ? I briefly tried searching for functions related to temporaries in the docs but didn't find anything |
Sorry for letting you wait so long, but I'm on vacation and have only spotty network. I'll try to get back to you within two days. |
Ok, so currently we only catch In the |
I'm confused about how to achieve the second part, the one just up there : struct TakeVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
identifiers: HashSet<HirId>,
}
impl<'a, 'tcx> Visitor<'tcx> for TakeVisitor<'a, 'tcx> {
fn visit_id(&mut self, hir_id: HirId) {
self.identifiers.insert(hir_id);
// walk_id()
}
}
fn recurse_over_methods(cx: &LateContext<'_>, expr: &Expr<'_>) -> OptionCallChain {
//dbg!(expr);
match expr.kind {
rustc_hir::ExprKind::MethodCall(method_path, [value], _) => {
match method_path.ident.as_str() {
// Checks if last function in line == "take"
"take" => match value.kind {
rustc_hir::ExprKind::MethodCall(value_method_path, [_], _) => {
dbg!(method_path, value);
if value_method_path.ident.as_str() == "as_ref" {
return OptionCallChain::FoundAsRef;
}
},
_ => {},
},
_ => {},
}
},
_ => {
println!("not a method call");
},
};
OptionCallChain::FoundAsRef
} I hope I've understanded the part correctly, in which, I need to use walk_id to walk over the IDs, and insert each one of those into a HashSet if it does not match any previous entry |
There is nothing in an id we would have to walk. We need to visit the parent item, not the method call. However, the visitor should only count uses of the local after encountering the take expr (which you can check by storing and comparing the expr.id). So you need to a) walk the method chain until finding an |
Oh, right, |
.stderr
file)cargo test
passes locallycargo dev update_lints
cargo dev fmt
Fixes #8618
changelog: Introduce [
needless_option_take
] lint