diff --git a/CHANGELOG.md b/CHANGELOG.md index 24b91932567a..3459dae23094 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7238,6 +7238,7 @@ Released 2018-09-13 [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next [`sliced_string_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#sliced_string_as_bytes [`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization +[`some_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#some_filter [`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive [`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc [`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_core diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 79ed199147f1..2afcbd60e9ea 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -474,6 +474,7 @@ crate::methods::SINGLE_CHAR_ADD_STR_INFO, crate::methods::SKIP_WHILE_NEXT_INFO, crate::methods::SLICED_STRING_AS_BYTES_INFO, + crate::methods::SOME_FILTER_INFO, crate::methods::STABLE_SORT_PRIMITIVE_INFO, crate::methods::STR_SPLIT_AT_NEWLINE_INFO, crate::methods::STRING_EXTEND_CHARS_INFO, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 4fdde52c327e..4bf7b77a2b0f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -111,6 +111,7 @@ mod single_char_add_str; mod skip_while_next; mod sliced_string_as_bytes; +mod some_filter; mod stable_sort_primitive; mod str_split; mod str_splitn; @@ -3577,6 +3578,29 @@ "slicing a string and immediately calling as_bytes is less efficient and can lead to panics" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `Some(x).filter(|_| predicate)`. + /// + /// ### Why is this bad? + /// Readability, this can be written more concisely as `predicate.then_some(x)`. + /// + /// ### Example + /// ```no_run + /// let x = false; + /// Some(0).filter(|_| x); + /// ``` + /// Use instead: + /// ```no_run + /// let x = false; + /// x.then_some(0); + /// ``` + #[clippy::version = "1.97.0"] + pub SOME_FILTER, + complexity, + "using `Some(x).filter(|_| predicate)`, which is more succinctly expressed as `predicate.then(x)`" +} + declare_clippy_lint! { /// ### What it does /// When sorting primitive values (integers, bools, chars, as well @@ -4900,6 +4924,7 @@ SINGLE_CHAR_ADD_STR, SKIP_WHILE_NEXT, SLICED_STRING_AS_BYTES, + SOME_FILTER, STABLE_SORT_PRIMITIVE, STRING_EXTEND_CHARS, STRING_LIT_CHARS_ANY, @@ -5307,6 +5332,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // use the sourcemap to get the span of the closure iter_filter::check(cx, expr, arg, span); } + some_filter::check(cx, expr, recv, arg, self.msrv); }, (sym::find, [arg]) => { if let Some((sym::cloned, recv2, [], _span2, _)) = method_call(recv) { diff --git a/clippy_lints/src/methods/some_filter.rs b/clippy_lints/src/methods/some_filter.rs new file mode 100644 index 000000000000..f3db0fa165af --- /dev/null +++ b/clippy_lints/src/methods/some_filter.rs @@ -0,0 +1,65 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; +use clippy_utils::{as_some_expr, pat_is_wild, peel_blocks, span_contains_comment}; +use rustc_ast::util::parser::ExprPrecedence; +use rustc_errors::Applicability; +use rustc_hir::{Body, Expr, ExprKind}; +use rustc_lint::LateContext; + +use super::SOME_FILTER; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + recv: &'tcx Expr<'tcx>, + arg: &'tcx Expr<'tcx>, + msrv: Msrv, +) { + let (condition, value) = if let Some(value) = as_some_expr(cx, recv) + && let ExprKind::Closure(c) = arg.kind + && let Body { + params: [p], + value: condition, + } = cx.tcx.hir_body(c.body) + && pat_is_wild(cx, &p.pat.kind, arg) + && msrv.meets(cx, msrvs::BOOL_THEN_SOME) + { + (condition, value) + } else { + return; + }; + span_lint_and_then( + cx, + SOME_FILTER, + expr.span, + "use of `Some(x).filter(|_| predicate)`", + |diag| { + let condition = if span_contains_comment(cx, condition.span) { + condition + } else { + peel_blocks(condition) + }; + let mut applicability = Applicability::MaybeIncorrect; + 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 { "" }, + ); + diag.span_suggestion_verbose( + expr.span, + "consider using `bool::then_some` instead", + sugg, + applicability, + ); + diag.note( + "this change will alter the order in which the condition and \ + the value are evaluated", + ); + }, + ); +} diff --git a/tests/ui/manual_filter.fixed b/tests/ui/manual_filter.fixed index 3e2cebee40fe..7d7f987ca362 100644 --- a/tests/ui/manual_filter.fixed +++ b/tests/ui/manual_filter.fixed @@ -2,6 +2,7 @@ #![allow( unused_variables, clippy::question_mark, + clippy::some_filter, clippy::useless_vec, clippy::nonminimal_bool )] diff --git a/tests/ui/manual_filter.rs b/tests/ui/manual_filter.rs index 2b80cb450e05..b15008173e18 100644 --- a/tests/ui/manual_filter.rs +++ b/tests/ui/manual_filter.rs @@ -2,6 +2,7 @@ #![allow( unused_variables, clippy::question_mark, + clippy::some_filter, clippy::useless_vec, clippy::nonminimal_bool )] diff --git a/tests/ui/manual_filter.stderr b/tests/ui/manual_filter.stderr index c5fdf14a9b43..772401a5f6a5 100644 --- a/tests/ui/manual_filter.stderr +++ b/tests/ui/manual_filter.stderr @@ -1,5 +1,5 @@ error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:10:5 + --> tests/ui/manual_filter.rs:11:5 | LL | / match Some(0) { LL | | @@ -14,7 +14,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::manual_filter)]` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:22:5 + --> tests/ui/manual_filter.rs:23:5 | LL | / match Some(1) { LL | | @@ -26,7 +26,7 @@ LL | | }; | |_____^ help: try: `Some(1).filter(|&x| x <= 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:34:5 + --> tests/ui/manual_filter.rs:35:5 | LL | / match Some(2) { LL | | @@ -38,7 +38,7 @@ LL | | }; | |_____^ help: try: `Some(2).filter(|&x| x <= 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:46:5 + --> tests/ui/manual_filter.rs:47:5 | LL | / match Some(3) { LL | | @@ -50,7 +50,7 @@ LL | | }; | |_____^ help: try: `Some(3).filter(|&x| x > 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:59:5 + --> tests/ui/manual_filter.rs:60:5 | LL | / match y { LL | | @@ -62,7 +62,7 @@ LL | | }; | |_____^ help: try: `y.filter(|&x| x <= 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:72:5 + --> tests/ui/manual_filter.rs:73:5 | LL | / match Some(5) { LL | | @@ -74,7 +74,7 @@ LL | | }; | |_____^ help: try: `Some(5).filter(|&x| x > 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:84:5 + --> tests/ui/manual_filter.rs:85:5 | LL | / match Some(6) { LL | | @@ -86,7 +86,7 @@ LL | | }; | |_____^ help: try: `Some(6).as_ref().filter(|&x| x > &0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:97:5 + --> tests/ui/manual_filter.rs:98:5 | LL | / match Some(String::new()) { LL | | @@ -98,7 +98,7 @@ LL | | }; | |_____^ help: try: `Some(String::new()).filter(|x| external_cond)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:109:5 + --> tests/ui/manual_filter.rs:110:5 | LL | / if let Some(x) = Some(7) { LL | | @@ -109,7 +109,7 @@ LL | | }; | |_____^ help: try: `Some(7).filter(|&x| external_cond)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:116:5 + --> tests/ui/manual_filter.rs:117:5 | LL | / match &Some(8) { LL | | @@ -121,7 +121,7 @@ LL | | }; | |_____^ help: try: `Some(8).filter(|&x| x != 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:128:5 + --> tests/ui/manual_filter.rs:129:5 | LL | / match Some(9) { LL | | @@ -133,7 +133,7 @@ LL | | }; | |_____^ help: try: `Some(9).filter(|&x| x > 10 && x < 100)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:155:5 + --> tests/ui/manual_filter.rs:156:5 | LL | / match Some(11) { LL | | @@ -153,7 +153,7 @@ LL ~ }); | error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:200:13 + --> tests/ui/manual_filter.rs:201:13 | LL | let _ = match Some(14) { | _____________^ @@ -166,7 +166,7 @@ LL | | }; | |_____^ help: try: `Some(14).filter(|&x| unsafe { f(x) })` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:211:13 + --> tests/ui/manual_filter.rs:212:13 | LL | let _ = match Some(15) { | _____________^ @@ -177,7 +177,7 @@ LL | | }; | |_____^ help: try: `Some(15).filter(|&x| unsafe { f(x) })` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:220:12 + --> tests/ui/manual_filter.rs:221:12 | LL | } else if let Some(x) = Some(16) { | ____________^ @@ -190,31 +190,31 @@ LL | | }; | |_____^ help: try: `{ Some(16).filter(|&x| x % 2 == 0) }` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:303:9 + --> tests/ui/manual_filter.rs:304:9 | LL | opt.and_then(|x| if x == 0 { None } else { Some(x) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter(|&x| x != 0)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:307:9 + --> tests/ui/manual_filter.rs:308:9 | LL | opt.and_then(move |x| if x == y { Some(x) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter(move |&x| x == y)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:311:10 + --> tests/ui/manual_filter.rs:312:10 | LL | opt1.and_then(|s| if s.len() > 2 { Some(s) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter(|s| s.len() > 2)` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:317:9 + --> tests/ui/manual_filter.rs:318:9 | LL | opt.and_then(|x| if unsafe { f(x as u32) } { Some(x) } else { None }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter(|&x| unsafe { f(x as u32) })` error: manual implementation of `Option::filter` - --> tests/ui/manual_filter.rs:319:9 + --> tests/ui/manual_filter.rs:320:9 | LL | opt.and_then(|x| unsafe { if f(x as u32) { Some(x) } else { None } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter(|&x| unsafe { f(x as u32) })` diff --git a/tests/ui/option_filter_map.fixed b/tests/ui/option_filter_map.fixed index d390c41af53c..b3191c6c1d46 100644 --- a/tests/ui/option_filter_map.fixed +++ b/tests/ui/option_filter_map.fixed @@ -1,5 +1,5 @@ #![warn(clippy::option_filter_map)] -#![allow(clippy::map_flatten, clippy::unnecessary_map_on_constructor)] +#![allow(clippy::map_flatten, clippy::some_filter, clippy::unnecessary_map_on_constructor)] fn main() { let _ = Some(Some(1)).flatten(); diff --git a/tests/ui/option_filter_map.rs b/tests/ui/option_filter_map.rs index 2d3b983a7670..7d373f353688 100644 --- a/tests/ui/option_filter_map.rs +++ b/tests/ui/option_filter_map.rs @@ -1,5 +1,5 @@ #![warn(clippy::option_filter_map)] -#![allow(clippy::map_flatten, clippy::unnecessary_map_on_constructor)] +#![allow(clippy::map_flatten, clippy::some_filter, clippy::unnecessary_map_on_constructor)] fn main() { let _ = Some(Some(1)).filter(Option::is_some).map(Option::unwrap); diff --git a/tests/ui/some_filter.fixed b/tests/ui/some_filter.fixed new file mode 100644 index 000000000000..a214dec920d4 --- /dev/null +++ b/tests/ui/some_filter.fixed @@ -0,0 +1,70 @@ +#![warn(clippy::some_filter)] +#![allow(clippy::const_is_empty)] + +macro_rules! unchanged { + ($result:expr) => { + $result + }; +} + +macro_rules! condition { + ($condition:expr) => { + $condition || false + }; +} + +#[clippy::msrv = "1.61"] +fn older() { + let _ = Some(0).filter(|_| false); +} + +#[clippy::msrv = "1.62"] +fn newer() { + let _ = false.then_some(0); + //~^ some_filter +} + +fn main() { + let _ = false.then_some(0); + //~^ some_filter + + // The condition contains an operator. The program should add parentheses. + let _ = (1 == 0).then_some(0); + //~^ some_filter + + let _ = match 0 { + //~^ some_filter + 0 => false, + 1 => true, + _ => true, + }.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); + + // The expression is a macro argument. The program should change the macro + // argument. It should not expand the macro. + let _ = unchanged!(false.then_some(0)); + //~^ some_filter + let _ = vec![false].is_empty().then_some(0); + //~^ some_filter + + // The condition is a macro that expands to an expression containing an + // operator. The program should not add parentheses. + let _ = condition!(false).then_some(0); + //~^ some_filter + + (1 == 0).then_some(String::from( + //~^ some_filter + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong", + )); + { + //~^ some_filter + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong".is_empty() + }.then_some(5); + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong".is_empty().then_some(String::from( + //~^ some_filter + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong", + )); +} diff --git a/tests/ui/some_filter.rs b/tests/ui/some_filter.rs new file mode 100644 index 000000000000..eec797536a8f --- /dev/null +++ b/tests/ui/some_filter.rs @@ -0,0 +1,74 @@ +#![warn(clippy::some_filter)] +#![allow(clippy::const_is_empty)] + +macro_rules! unchanged { + ($result:expr) => { + $result + }; +} + +macro_rules! condition { + ($condition:expr) => { + $condition || false + }; +} + +#[clippy::msrv = "1.61"] +fn older() { + let _ = Some(0).filter(|_| false); +} + +#[clippy::msrv = "1.62"] +fn newer() { + let _ = Some(0).filter(|_| false); + //~^ some_filter +} + +fn main() { + let _ = Some(0).filter(|_| false); + //~^ some_filter + + // The condition contains an operator. The program should add parentheses. + let _ = Some(0).filter(|_| 1 == 0); + //~^ some_filter + + let _ = Some(0).filter(|_| match 0 { + //~^ some_filter + 0 => false, + 1 => true, + _ => true, + }); + + // 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); + + // The expression is a macro argument. The program should change the macro + // argument. It should not expand the macro. + let _ = unchanged!(Some(0).filter(|_| false)); + //~^ some_filter + let _ = Some(0).filter(|_| vec![false].is_empty()); + //~^ some_filter + + // The condition is a macro that expands to an expression containing an + // operator. The program should not add parentheses. + let _ = Some(0).filter(|_| condition!(false)); + //~^ some_filter + + Some(String::from( + //~^ some_filter + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong", + )) + .filter(|_| 1 == 0); + Some(5).filter(|_| { + //~^ some_filter + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong".is_empty() + }); + Some(String::from( + //~^ some_filter + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong", + )) + .filter(|_| { + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong".is_empty() + }); +} diff --git a/tests/ui/some_filter.stderr b/tests/ui/some_filter.stderr new file mode 100644 index 000000000000..a4f38f49df69 --- /dev/null +++ b/tests/ui/some_filter.stderr @@ -0,0 +1,163 @@ +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:23:13 + | +LL | let _ = Some(0).filter(|_| false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this change will alter the order in which the condition and the value are evaluated + = note: `-D clippy::some-filter` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::some_filter)]` +help: consider using `bool::then_some` instead + | +LL - let _ = Some(0).filter(|_| false); +LL + let _ = false.then_some(0); + | + +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:28:13 + | +LL | let _ = Some(0).filter(|_| false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this change will alter the order in which the condition and the value are evaluated +help: consider using `bool::then_some` instead + | +LL - let _ = Some(0).filter(|_| false); +LL + let _ = false.then_some(0); + | + +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:32:13 + | +LL | let _ = Some(0).filter(|_| 1 == 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this change will alter the order in which the condition and the value are evaluated +help: consider using `bool::then_some` instead + | +LL - let _ = Some(0).filter(|_| 1 == 0); +LL + let _ = (1 == 0).then_some(0); + | + +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:35:13 + | +LL | let _ = Some(0).filter(|_| match 0 { + | _____________^ +LL | | +LL | | 0 => false, +LL | | 1 => true, +LL | | _ => true, +LL | | }); + | |______^ + | + = note: this change will alter the order in which the condition and the value are evaluated +help: consider using `bool::then_some` instead + | +LL ~ let _ = match 0 { +LL + +LL + 0 => false, +LL + 1 => true, +LL + _ => true, +LL ~ }.then_some(0); + | + +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:48:24 + | +LL | let _ = unchanged!(Some(0).filter(|_| false)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this change will alter the order in which the condition and the value are evaluated +help: consider using `bool::then_some` instead + | +LL - let _ = unchanged!(Some(0).filter(|_| false)); +LL + let _ = unchanged!(false.then_some(0)); + | + +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:50:13 + | +LL | let _ = Some(0).filter(|_| vec![false].is_empty()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this change will alter the order in which the condition and the value are evaluated +help: consider using `bool::then_some` instead + | +LL - let _ = Some(0).filter(|_| vec![false].is_empty()); +LL + let _ = vec![false].is_empty().then_some(0); + | + +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:55:13 + | +LL | let _ = Some(0).filter(|_| condition!(false)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this change will alter the order in which the condition and the value are evaluated +help: consider using `bool::then_some` instead + | +LL - let _ = Some(0).filter(|_| condition!(false)); +LL + let _ = condition!(false).then_some(0); + | + +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:58:5 + | +LL | / Some(String::from( +LL | | +LL | | "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong", +LL | | )) +LL | | .filter(|_| 1 == 0); + | |_______________________^ + | + = note: this change will alter the order in which the condition and the value are evaluated +help: consider using `bool::then_some` instead + | +LL ~ (1 == 0).then_some(String::from( +LL + +LL + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong", +LL ~ )); + | + +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:63:5 + | +LL | / Some(5).filter(|_| { +LL | | +LL | | "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong".is_empty() +LL | | }); + | |______^ + | + = note: this change will alter the order in which the condition and the value are evaluated +help: consider using `bool::then_some` instead + | +LL ~ { +LL + +LL + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong".is_empty() +LL ~ }.then_some(5); + | + +error: use of `Some(x).filter(|_| predicate)` + --> tests/ui/some_filter.rs:67:5 + | +LL | / Some(String::from( +LL | | +LL | | "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong", +LL | | )) +LL | | .filter(|_| { +LL | | "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong".is_empty() +LL | | }); + | |______^ + | + = note: this change will alter the order in which the condition and the value are evaluated +help: consider using `bool::then_some` instead + | +LL ~ "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong".is_empty().then_some(String::from( +LL + +LL + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong", +LL ~ )); + | + +error: aborting due to 10 previous errors +