-
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
[WIP] explicit_auto_deref #6837
Conversation
Fix suggestion for `explicit_deref_methods`. Sometimes `&**` is needed, sometimes nothing is needed. Allow `explicit_deref_methods` to trigger in a few new contexts. `explicit_deref_methods` will now consider ufcs calls
`needless_borrow` will now check for multiple borrows `needless_borrow` will now consider mutable references
…was fixed over two years ago in d4370f8.
r? @flip1995 (rust-highfive has picked a reviewer for you, use r? to override) |
ad46c1e
to
31e2918
Compare
31e2918
to
7c2020b
Compare
Yes I think that is generally always better if possible. |
// foo!(&*String::new()); | ||
// fn foo<T>(_: &T) {} | ||
// foo(&*String::new()) | ||
fn is_stable_auto_deref_position(tcx: TyCtxt<'tcx>, typeck: &'tcx TypeckResults<'_>, id: HirId) -> bool { |
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.
Hmm. I think it would be better to do this the other way around. That is, in check_expr
, look for a "stable auto deref position", and then proceed inward to check for explicit deref. This way you don't have to climb the HIR with parent_iter
.
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.
Walking down would require implementing check_local
, check_item
, check_impl_item
and check_trait_item
in addition to check_expr
. It also requires walking from a block to all the break
expressions that target it, which I'm not sure how to do other than visiting everything.
Then there's the interaction with explicit_deref_methods
which can occur in other positions. explicit_auto_deref
should lint instead when possible, rather than both lints triggering.
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.
Okay I'm convinced. :)
One other idea. Use tcx.hir().opt_span()
to check in_macro
in one place, perhaps after match parent {}
.
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.
Actually I think it's good for both lints to trigger. The user may disagree with one of the lints but agree with the other.
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.
If they disagree with a lint they can just #[allow]
it. Then the other lint can trigger instead.
In this case both lints would trigger on the same code with conflicting suggestions, which breaks rustfix.
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.
It is valid to use Clippy without adding #[allow]
on undesired lint cases. I don't think it would break rustfix as of rust-lang/cargo#5842.
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.
In this case both the code and the suggestion for explicit_deref_methods
(x.deref()
-> &*x
) trigger explicit_auto_deref
(would change both to &x
), and this will always be the case. If someone doesn't want to apply explicit_auto_deref
they would have to allow it anyways. If they do want to apply it, it's the one that would take priority.
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.
they would have to allow it anyways
not if they are not using rustfix.
I see your point that the suggestions are redundant. But there is a risk that the user will ignore explicit_auto_deref
because they want the deref to be explicit, and at the same time, they would be willing to change to *
, but that suggestion is suppressed. This risk outweighs the redundancy IMO. You can display the preferred lint first so that the user won't fix it twice. Also displaying both lints is more informative for someone learning Rust since there are two learning opportunities from the same code.
Anyways, that's just my opinion and this is a small corner case.
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.
I guess they could just leave clippy forever triggering explicit_auto_deref
. If that's a real use case then both being suggested is reasonable.
That's really the only reason I would push for hiding it (since it doesn't break rustfix, just checked).
☔ The latest upstream changes (presumably #6823) made this pull request unmergeable. Please resolve the merge conflicts. |
`explicit_deref_methods` improvements Breaking up #6837 changelog: `explicit_deref_methods` will lint chained `deref` calls and ufcs style calls
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.
Only a quick review. Not sure what the state of this PR is (-> WIP?). I think you can leave everything in one PR, but please avoid squashing commits until the PR is approved.
use if_chain::if_chain; | ||
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX, PREC_PREFIX}; | ||
use crate::{ | ||
needless_borrow::NEEDLESS_BORROW, |
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.
I don't think we should trigger lints in two different passes/modules. Why isn't it possible to move the lint completely in this module/pass?
@@ -0,0 +1,63 @@ | |||
// use crate::utils::{get_parent_expr, snippet_with_applicability, span_lint_and_sugg}; |
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.
Why commented out, not removed? Just WIP I guess?
|
||
ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Err => false, | ||
|
||
ExprKind::Box(..) |
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.
Even though most of the time, I think being explicit in matches is good, I would just write _ => true
here, since this function is more about which expr types are special, that expression types in general.
Part of it has already been split out in #6865. |
Ah nice, thanks for the update! Do you plan to split out more PRs from this or do you want to rebase and continue working on this PR? |
I'll be splitting them out as I finish parts. |
SGTM. Is there a reason to keep this PR open then? |
I suppose not. |
fixes: #234
fixes: #1726
A few different things here. I can split this into multiple PR's if that would be better.
needless_borrow
was move to the nursery in d4370f8 due to #2740 which was fixed in #3400, so I've moved it back out of the nursery.All three lints are placed into the same pass so they don't trigger at the same time.
changelog:
explicit_deref_methods
will lint chainedderef
callschangelog:
explicit_deref_methods
will lint ufcs style callschangelog:
needless_borrow
will lint multiple borrowschangelog:
needless_borrow
moved out of the nurserychangelog:
needless_borrow
now lints the final expression in a match arm if that expression is in a blockchangelog: new lint
explicit_auto_deref