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

new lint: and_then_then_some #12981

Open
wants to merge 28 commits into
base: master
Choose a base branch
from

Conversation

lolbinarycat
Copy link

fixes #12978

changelog: [and_then_then_some]: added

@rustbot
Copy link
Collaborator

rustbot commented Jun 23, 2024

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @Centri3 (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Jun 23, 2024
@lolbinarycat
Copy link
Author

unable to reproduce formatting errors locally, cargo dev fmt --check runs fine

@lolbinarycat
Copy link
Author

ok apparently it just started working again, no idea why that happened.

Copy link
Member

@J-ZhengLi J-ZhengLi left a comment

Choose a reason for hiding this comment

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

Maybe this could be merge to the existing lint clippy::manual_filter?

Comment on lines +104 to +149
match local.kind {
ExprKind::Path(QPath::Resolved(
_,
Path {
res: Res::Local(local_hid),
..
},
)) => {
Copy link
Member

Choose a reason for hiding this comment

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

looks like clippy_utils::path_to_local, but I'm not sure if this can be replaced

Copy link
Author

Choose a reason for hiding this comment

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

i'm much more familiar with the hir and mir types than all the clippy utils, and yeah, you can't use function calls in patterns.

Copy link
Member

Choose a reason for hiding this comment

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

It could be extracted from the match expression then in the _ case you put that in the other branch. It'd be cleaner imo too

Copy link
Member

Choose a reason for hiding this comment

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

Actually, one step further, rather than doing an if let as I suggested above, do smth with Option::map_or_else then is_some_and(identity) since the true case is only when path_to_local would return Some.

@lolbinarycat
Copy link
Author

lolbinarycat commented Jun 27, 2024

Maybe this could be merge to the existing lint clippy::manual_filter?

that lint isn't machine applicable. additionally, it's not a nursury lint.

@lolbinarycat
Copy link
Author

@rustbot review

Copy link
Member

@Centri3 Centri3 left a comment

Choose a reason for hiding this comment

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

There's a few things I don't fully get, other than that just nits and lack of tests. Thanks! :3

fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
match expr.kind {
ExprKind::MethodCall(_, selfarg, [arg], _) | ExprKind::Call(_, [selfarg, arg]) => {
// TODO: check if type of reciever is diagnostic item Option?
Copy link
Member

Choose a reason for hiding this comment

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

Yeah this should check if the type is Option then check the name of the call

Copy link
Author

Choose a reason for hiding this comment

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

we're comparing the path later on, and the only way it could be a method call of one of Option's methods is if the receiver is Option, or if it's a function call that will fail typecheck, so checking the reciever type feels redundant.

originally i wanted it to still work even if the method was imported under a different name, but it doesn't seem like you can do that anyways.

Copy link
Member

Choose a reason for hiding this comment

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

It's not redundant. The reason why paths are discouraged more often than not is because they aren't as stable as diagnostic items, reexports are essentially stripped after the resolver so if Option is moved to, say, std::option_private::Option and reexported in Option, it'll no longer work.

Copy link
Member

Choose a reason for hiding this comment

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

Diagnostic item check + method name is the preferred way to do this

}
}

fn show_sugg(cx: &LateContext<'_>, span: Span, selfarg: &Expr<'_>, closure_args: Span, predicate: &Expr<'_>) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
fn show_sugg(cx: &LateContext<'_>, span: Span, selfarg: &Expr<'_>, closure_args: Span, predicate: &Expr<'_>) {
fn show_sugg(cx: &LateContext<'_>, span: Span, recv_or_self: &Expr<'_>, closure_args: Span, predicate: &Expr<'_>) {


fn is_then_some(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
if let Some(def_id) = fn_def_id(cx, expr) {
match_def_path(cx, def_id, &["core", "bool", "<impl bool>", "then_some"])
Copy link
Member

Choose a reason for hiding this comment

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

Same here. Let's match the type's diagnostic item to bool then check the method name

Copy link
Member

Choose a reason for hiding this comment

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

Would like some tests with external and procedural macros

Copy link
Member

Choose a reason for hiding this comment

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

This also needs to call in_external_macro and is_from_proc_macro. Make sure is_from_proc_macro is called last before linting

Copy link
Member

Choose a reason for hiding this comment

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

Also could do with some tests regarding your blocks handling, also if it's an explicit return instead

Copy link
Author

Choose a reason for hiding this comment

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

do you mean returning early if those functions are true? it seems like order wouldn't matter in that case, so obviously i'm missing something.

Copy link
Member

Choose a reason for hiding this comment

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

Early returning from in_external_macro. The reasoning behind calling is_from_proc_macro is because it's quite costly. We tend to call it last

Comment on lines 112 to 116
// FIXME: this is the best way i could find to compare if
// a local refers to a specific closure argument.
//
// it breaks if the closure argument has an explicitly declared type,
// since the spans only align for TyKind::Infer
Copy link
Member

Choose a reason for hiding this comment

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

Issue: You shouldn't use the FnDecl for this. The Body contains more parameter info, mostly importantly the HirId

See Map::body, instead of getting the span of the body get the body itself :P

Copy link
Author

Choose a reason for hiding this comment

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

the documentation on hir::Body seems to suggest it only contains argument patterns when used with a function, not a closure?

Copy link
Member

@Centri3 Centri3 Jun 27, 2024

Choose a reason for hiding this comment

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

It does for both cases. That documentation seems misleading tbh, I think they meant function as in a method call, function, or closure, since constant values wouldn't be included

@Centri3
Copy link
Member

Centri3 commented Jun 27, 2024

Maybe this could be merge to the existing lint clippy::manual_filter?

that lint isn't machine applicable. additionally, it's not a nursury lint.

Two suggestions can have differing applicability. Also imo this shouldn't be nursery, it seems completely fine once the issue regarding FnDecl is resolved

@J-ZhengLi
Copy link
Member

ah just got back from work, looks like a lot discussion has happened so I'm gonna clear something really quick then throw myself out :D

that lint isn't machine applicable.

I think it is? The applicability was initialized as MachineApplicable in manual_utils.rs, later passed to manual_filter via SuggInfo. You may keep this lint as a separated one consider how complicated the other one looks, plus this one checks different thing anyway.

But just keep in mind about putting lints in 'nursery', they would receive less testing and not being as useful as the other lints.

I've ran lintcheck on top 200 popular crate with this lint, unfortunately I didn't see any thing related, putting it in 'nursery' is just further limiting it's useages, so agree with Centri3 that this shouldn't be a 'nursery' lint, at least for now

@lolbinarycat
Copy link
Author

I've ran lintcheck on top 200 popular crate with this lint, unfortunately I didn't see any thing related, putting it in 'nursery' is just further limiting it's useages, so agree with Centri3 that this shouldn't be a 'nursery' lint, at least for now

the problem is false positives, since the pre and post transformation code actually has different signatures (goes from by value to by reference).

@Centri3
Copy link
Member

Centri3 commented Jun 28, 2024

Hmm I see. we can fix that by adding a & to filter's signature if it's Copy, check clippy_utils::ty::is_copy. Otherwise it should be non-applicable if it's !Copy yet warn-by-default

Also, if the original type is a reference then it's Copy automatically so that's another case that's very nicely handled.

@lolbinarycat
Copy link
Author

also, if the argument variable only appears in autoreferencing method calls (like in the current tests) it should be possible.

@bors
Copy link
Contributor

bors commented Jul 4, 2024

☔ The latest upstream changes (presumably #12873) made this pull request unmergeable. Please resolve the merge conflicts.

@lolbinarycat
Copy link
Author

Hmm I see. we can fix that by adding a & to filter's signature if it's Copy, check clippy_utils::ty::is_copy. Otherwise it should be non-applicable if it's !Copy yet warn-by-default

Also, if the original type is a reference then it's Copy automatically so that's another case that's very nicely handled.

I think this false positive I'm worried about might actually be mathematically impossible, since it requires a non-copy value to be moved in the predicate, then moved into the argument of then_some, which would fail borrow checking.

@xFrednet
Copy link
Member

xFrednet commented Aug 3, 2024

Hey, this is triage. It looks like @Centri3 is currently busy. Let's pick another reviewer:

r? clippy

@rustbot rustbot assigned blyxyas and unassigned Centri3 Aug 3, 2024
@blyxyas
Copy link
Member

blyxyas commented Aug 5, 2024

Rerolling these, I'm currently focused on our project's goal, see #13154

r? clippy

@rustbot rustbot assigned Manishearth and unassigned blyxyas Aug 5, 2024
@Manishearth
Copy link
Member

r? clippy

rerolling again, I'm wrapping up vacation and will be on airplanes for a while

@rustbot rustbot assigned flip1995 and unassigned Manishearth Aug 5, 2024
@bors
Copy link
Contributor

bors commented Aug 28, 2024

☔ The latest upstream changes (presumably #11476) made this pull request unmergeable. Please resolve the merge conflicts.

@blyxyas
Copy link
Member

blyxyas commented Sep 9, 2024

I'll get to review this, seems that it's been kinda forgotten by the team. We should have a review soon.

@lolbinarycat
Copy link
Author

i've kinda abandoned it since it seems like there might already be a lint for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Option::and_then(|v| ...(&v).then_some(v)) to Option::filter(|v| ...(v))
10 participants