Skip to content

Conversation

qmwrygdxpzc
Copy link

@qmwrygdxpzc qmwrygdxpzc commented Sep 23, 2025

Add a check for some followed by filter.

The program will suggest using the then_some method.

changelog: [filter_some]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_some

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Sep 23, 2025
@rustbot
Copy link
Collaborator

rustbot commented Sep 23, 2025

r? @llogiq

rustbot has assigned @llogiq.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Copy link

github-actions bot commented Sep 23, 2025

No changes for 6f173cd

Copy link
Member

@samueltardieu samueltardieu left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution. However, the lint cannot be considered for merging as-is:

  • It should include autofixes suggestions when possible.
  • It should cover more complex cases.

For example, with the following code

fn with_side_effect(x: u32) -> u32 {
    println!("In `with_side_effect()`");
    x * 10 + 30
}

fn f(x: u32) -> Option<u32> {
    Some(with_side_effect(x)).filter(|&x| x > 40)
}

the lint suggests using then_some() inside f(). However, I don't see what would be the replacement code here.

You should include tests for the most complicated situations you can think of, as the lint should not fail, don't just cover the simplest case where it is obvious it will work. For example, what is part of the expression comes from a macro? Also, bool::then_some() has been introduced in Rust 1.62.0, so the MSRV must be checked as well.

Hope this review will help you go forward.

View changes since this review

@qmwrygdxpzc
Copy link
Author

In the example with the 2 functions, what should the linter do?

@samueltardieu
Copy link
Member

In the example with the 2 functions, what should the linter do?

Probably nothing.

@qmwrygdxpzc
Copy link
Author

It has been about 2 weeks. Can someone take a look?

@qmwrygdxpzc
Copy link
Author

@samueltardieu Now there are some less trivial tests involving macros. Please take another look.

@rustbot

This comment has been minimized.

@rustbot
Copy link
Collaborator

rustbot commented Oct 13, 2025

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rustbot

This comment has been minimized.

@rustbot rustbot added has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Oct 13, 2025
The program will suggest using the `then_some` method.

changelog: [`filter_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_some
@rustbot rustbot removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) has-merge-commits PR has merge commits, merge with caution. labels Oct 13, 2025
Comment on lines +40 to +48
let (condition_text, condition_is_macro) =
snippet_with_context(cx, condition.span, arg.span.ctxt(), "..", &mut applicability);
let parentheses = !condition_is_macro && cx.precedence(condition) < ExprPrecedence::Unambiguous;
let value_text = snippet_with_applicability(cx, value.span, "..", &mut applicability);
let sugg = format!(
"{}{condition_text}{}.then_some({value_text})",
if parentheses { "(" } else { "" },
if parentheses { ")" } else { "" },
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Sugg::maybe_paren has some logic to add parentheses, but only when needed -- I think that should be enough to deal with this case.

Suggested change
let (condition_text, condition_is_macro) =
snippet_with_context(cx, condition.span, arg.span.ctxt(), "..", &mut applicability);
let parentheses = !condition_is_macro && cx.precedence(condition) < ExprPrecedence::Unambiguous;
let value_text = snippet_with_applicability(cx, value.span, "..", &mut applicability);
let sugg = format!(
"{}{condition_text}{}.then_some({value_text})",
if parentheses { "(" } else { "" },
if parentheses { ")" } else { "" },
);
let condition_text =
Sugg::hir_with_context(cx, condition.span, arg.span.ctxt(), "..", &mut applicability).maybe_paren();
let value_text = snippet_with_applicability(cx, value.span, "..", &mut applicability);
let sugg = format!("{condition_text}.then_some({value_text})");

(Sugg::hir_with_context is pretty much the same as snippet_with_context)

Copy link
Author

Choose a reason for hiding this comment

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

With this change applied, the program adds parentheses here. Is it intended?

diff --git a/tests/ui/filter_some.fixed b/tests/ui/filter_some.fixed
index fbfdfd177..386a0264c 100644
--- a/tests/ui/filter_some.fixed
+++ b/tests/ui/filter_some.fixed
@@ -18,12 +18,12 @@ fn main() {
     // The condition contains an operator.  The program should add parentheses.
     let _ = (1 == 0).then_some(0);
     //~^ filter_some
-    let _ = match 0 {
+    let _ = (match 0 {
         //~^ filter_some
         0 => false,
         1 => true,
         _ => true,
-    }.then_some(0);
+    }).then_some(0);
     // The argument to filter requires the value in the option.  The program
     // can't figure out how to change it.  It should leave it alone for now.
     let _ = Some(0).filter(|x| *x == 0);

Copy link
Contributor

@ada4a ada4a Oct 13, 2025

Choose a reason for hiding this comment

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

I assume that the previous version compiled just fine, and so the parentheses are indeed unnecessary. It could be that there are expressions for which your approach and Sugg would yield different results, and I must admit I don't which of those will actually have more correct ones, so I guess let's go with yours

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-fcp 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.

5 participants