Add a note when the drop order change may result in different behaviour.
/// **Why is this bad?** It's more concise and clear to just use the proper
/// utility function
///
- /// **Known problems:** None.
+ /// **Known problems:** This will change the drop order for the matched type. Both `if let` and
+ /// `while let` will drop the value at the end of the block, both `if` and `while` will drop the
+ /// value before entering the block. For most types this change will not matter, but for a few
+ /// types this will not be an acceptable change (e.g. locks). See the
+ /// [reference](https://doc.rust-lang.org/reference/destructors.html#drop-scopes) for more about
+ /// drop order.
///
/// **Example:**
///
mod redundant_pattern_match {
use super::REDUNDANT_PATTERN_MATCHING;
use clippy_utils::diagnostics::span_lint_and_then;
- use clippy_utils::source::snippet;
+ use clippy_utils::source::{snippet, snippet_with_applicability};
+ use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, is_type_lang_item, match_type};
use clippy_utils::{is_lang_ctor, is_qpath_def_path, is_trait_method, paths};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
- use rustc_hir::{Arm, Expr, ExprKind, MatchSource, PatKind, QPath};
+ use rustc_hir::{
+ intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor},
+ Arm, Block, Expr, ExprKind, LangItem, MatchSource, Node, PatKind, QPath,
+ };
use rustc_lint::LateContext;
+ use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
use rustc_span::sym;
pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Match(op, arms, ref match_source) = &expr.kind {
match match_source {
MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms),
- MatchSource::IfLetDesugar { .. } => find_sugg_for_if_let(cx, expr, op, arms, "if"),
- MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, arms, "while"),
+ MatchSource::IfLetDesugar { contains_else_clause } => {
+ find_sugg_for_if_let(cx, expr, op, &arms[0], "if", *contains_else_clause)
+ },
+ MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, &arms[0], "while", false),
_ => {},
}
}
}
+ // Check if the drop order for a type matters
+ fn type_needs_ordered_drop(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+ if !ty.needs_drop(cx.tcx, cx.param_env) {
+ false
+ } else if cx
+ .tcx
+ .lang_items()
+ .drop_trait()
+ .map_or(false, |id| !implements_trait(cx, ty, id, &[]))
+ {
+ // This type doesn't implement drop, so no side effects here.
+ // Check if any component type has any.
+ match ty.kind() {
+ ty::Tuple(_) => ty.tuple_fields().any(|ty| type_needs_ordered_drop(cx, ty)),
+ ty::Array(ty, _) => type_needs_ordered_drop(cx, ty),
+ ty::Adt(adt, subs) => adt
+ .all_fields()
+ .map(|f| f.ty(cx.tcx, subs))
+ .any(|ty| type_needs_ordered_drop(cx, ty)),
+ _ => true,
+ }
+ }
+ // Check for std types which implement drop, but only for memory allocation.
+ else if is_type_diagnostic_item(cx, ty, sym::vec_type)
+ || is_type_lang_item(cx, ty, LangItem::OwnedBox)
+ || is_type_diagnostic_item(cx, ty, sym::Rc)
+ || is_type_diagnostic_item(cx, ty, sym::Arc)
+ || is_type_diagnostic_item(cx, ty, sym::cstring_type)
+ || match_type(cx, ty, &paths::BTREEMAP)
+ || match_type(cx, ty, &paths::LINKED_LIST)
+ || match_type(cx, ty, &paths::WEAK_RC)
+ || match_type(cx, ty, &paths::WEAK_ARC)
+ {
+ // Check all of the generic arguments.
+ if let ty::Adt(_, subs) = ty.kind() {
+ subs.types().any(|ty| type_needs_ordered_drop(cx, ty))
+ } else {
+ true
+ }
+ } else {
+ true
+ }
+ }
+
+ // Extract the generic arguments out of a type
+ fn try_get_generic_ty(ty: Ty<'_>, index: usize) -> Option<Ty<'_>> {
+ if_chain! {
+ if let ty::Adt(_, subs) = ty.kind();
+ if let Some(sub) = subs.get(index);
+ if let GenericArgKind::Type(sub_ty) = sub.unpack();
+ then {
+ Some(sub_ty)
+ } else {
+ None
+ }
+ }
+ }
+
+ // Checks if there are any temporaries created in the given expression for which drop order
+ // matters.
+ fn temporaries_need_ordered_drop(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
+ struct V<'a, 'tcx> {
+ cx: &'a LateContext<'tcx>,
+ res: bool,
+ }
+ impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> {
+ type Map = ErasedMap<'tcx>;
+ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+ NestedVisitorMap::None
+ }
+
+ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+ match expr.kind {
+ // Taking the reference of a value leaves a temporary
+ // e.g. In `&String::new()` the string is a temporary value.
+ // Remaining fields are temporary values
+ // e.g. In `(String::new(), 0).1` the string is a temporary value.
+ ExprKind::AddrOf(_, _, expr) | ExprKind::Field(expr, _) => {
+ if !matches!(expr.kind, ExprKind::Path(_)) {
+ if type_needs_ordered_drop(self.cx, self.cx.typeck_results().expr_ty(expr)) {
+ self.res = true;
+ } else {
+ self.visit_expr(expr);
+ }
+ }
+ },
+ // the base type is alway taken by reference.
+ // e.g. In `(vec![0])[0]` the vector is a temporary value.
+ ExprKind::Index(base, index) => {
+ if !matches!(base.kind, ExprKind::Path(_)) {
+ if type_needs_ordered_drop(self.cx, self.cx.typeck_results().expr_ty(base)) {
+ self.res = true;
+ } else {
+ self.visit_expr(base);
+ }
+ }
+ self.visit_expr(index);
+ },
+ // Method calls can take self by reference.
+ // e.g. In `String::new().len()` the string is a temporary value.
+ ExprKind::MethodCall(_, _, [self_arg, args @ ..], _) => {
+ if !matches!(self_arg.kind, ExprKind::Path(_)) {
+ let self_by_ref = self
+ .cx
+ .typeck_results()
+ .type_dependent_def_id(expr.hir_id)
+ .map_or(false, |id| self.cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref());
+ if self_by_ref
+ && type_needs_ordered_drop(self.cx, self.cx.typeck_results().expr_ty(self_arg))
+ {
+ self.res = true;
+ } else {
+ self.visit_expr(self_arg)
+ }
+ }
+ args.iter().for_each(|arg| self.visit_expr(arg));
+ },
+ // Either explicitly drops values, or changes control flow.
+ ExprKind::DropTemps(_)
+ | ExprKind::Ret(_)
+ | ExprKind::Break(..)
+ | ExprKind::Yield(..)
+ | ExprKind::Block(Block { expr: None, .. }, _)
+ | ExprKind::Loop(..) => (),
+
+ // Only consider the final expression.
+ ExprKind::Block(Block { expr: Some(expr), .. }, _) => self.visit_expr(expr),
+
+ _ => walk_expr(self, expr),
+ }
+ }
+ }
+
+ let mut v = V { cx, res: false };
+ v.visit_expr(expr);
+ v.res
+ }
+
fn find_sugg_for_if_let<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
- op: &Expr<'_>,
- arms: &[Arm<'_>],
+ op: &'tcx Expr<'tcx>,
+ arm: &Arm<'_>,
keyword: &'static str,
+ has_else: bool,
) {
// also look inside refs
- let mut kind = &arms[0].pat.kind;
+ let mut kind = &arm.pat.kind;
// if we have &None for example, peel it so we can detect "if let None = x"
if let PatKind::Ref(inner, _mutability) = kind {
kind = &inner.kind;
}
- let good_method = match kind {
+ let op_ty = cx.typeck_results().expr_ty(op);
+ // Determine which function should be used, and the type contained by the corresponding
+ // variant.
+ let (good_method, inner_ty) = match kind {
PatKind::TupleStruct(ref path, [sub_pat], _) => {
if let PatKind::Wild = sub_pat.kind {
if is_lang_ctor(cx, path, ResultOk) {
- "is_ok()"
+ ("is_ok()", try_get_generic_ty(op_ty, 0).unwrap_or(op_ty))
} else if is_lang_ctor(cx, path, ResultErr) {
- "is_err()"
+ ("is_err()", try_get_generic_ty(op_ty, 1).unwrap_or(op_ty))
} else if is_lang_ctor(cx, path, OptionSome) {
- "is_some()"
+ ("is_some()", op_ty)
} else if is_lang_ctor(cx, path, PollReady) {
- "is_ready()"
+ ("is_ready()", op_ty)
} else if is_qpath_def_path(cx, path, sub_pat.hir_id, &paths::IPADDR_V4) {
- "is_ipv4()"
+ ("is_ipv4()", op_ty)
} else if is_qpath_def_path(cx, path, sub_pat.hir_id, &paths::IPADDR_V6) {
- "is_ipv6()"
+ ("is_ipv6()", op_ty)
} else {
return;
}
}
},
PatKind::Path(ref path) => {
- if is_lang_ctor(cx, path, OptionNone) {
+ let method = if is_lang_ctor(cx, path, OptionNone) {
"is_none()"
} else if is_lang_ctor(cx, path, PollPending) {
"is_pending()"
} else {
return;
- }
+ };
+ // `None` and `Pending` don't have an inner type.
+ (method, cx.tcx.types.unit)
},
_ => return,
};
+ // If this is the last expression in a block or there is an else clause then the whole
+ // type needs to be considered, not just the inner type of the branch being matched on.
+ // Note the last expression in a block is dropped after all local bindings.
+ let check_ty = if has_else
+ || (keyword == "if" && matches!(cx.tcx.hir().parent_iter(expr.hir_id).next(), Some((_, Node::Block(..)))))
+ {
+ op_ty
+ } else {
+ inner_ty
+ };
+
+ // All temporaries created in the scrutinee expression are dropped at the same time as the
+ // scrutinee would be, so they have to be considered as well.
+ // e.g. in `if let Some(x) = foo.lock().unwrap().baz.as_ref() { .. }` the lock will be held
+ // for the duration if body.
+ let needs_drop = type_needs_ordered_drop(cx, check_ty) || temporaries_need_ordered_drop(cx, op);
+
// check that `while_let_on_iterator` lint does not trigger
if_chain! {
if keyword == "while";
span_lint_and_then(
cx,
REDUNDANT_PATTERN_MATCHING,
- arms[0].pat.span,
+ arm.pat.span,
&format!("redundant pattern matching, consider using `{}`", good_method),
|diag| {
// while let ... = ... { ... }
// while let ... = ... { ... }
// ^^^^^^^^^^^^^^^^^^^
let span = expr_span.until(op_span.shrink_to_hi());
- diag.span_suggestion(
- span,
- "try this",
- format!("{} {}.{}", keyword, snippet(cx, op_span, "_"), good_method),
- Applicability::MachineApplicable, // snippet
- );
+
+ let mut app = if needs_drop {
+ Applicability::MaybeIncorrect
+ } else {
+ Applicability::MachineApplicable
+ };
+ let sugg = snippet_with_applicability(cx, op_span, "_", &mut app);
+
+ diag.span_suggestion(span, "try this", format!("{} {}.{}", keyword, sugg, good_method), app);
+
+ if needs_drop {
+ diag.note("this will change drop order of the result, as well as all temporaries");
+ diag.note("add `#[allow(clippy::redundant_pattern_matching)]` if this is important");
+ }
},
);
}
--- /dev/null
+// run-rustfix
+
+// Issue #5746
+#![warn(clippy::redundant_pattern_matching)]
+#![allow(clippy::if_same_then_else)]
+use std::task::Poll::{Pending, Ready};
+
+fn main() {
+ let m = std::sync::Mutex::new((0, 0));
+
+ // Result
+ if m.lock().is_ok() {}
+ if Err::<(), _>(m.lock().unwrap().0).is_err() {}
+
+ {
+ if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok() {}
+ }
+ if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok() {
+ } else {
+ }
+ if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok() {}
+ if Err::<std::sync::MutexGuard<()>, _>(()).is_err() {}
+
+ if Ok::<_, ()>(String::new()).is_ok() {}
+ if Err::<(), _>((String::new(), ())).is_err() {}
+
+ // Option
+ if Some(m.lock()).is_some() {}
+ if Some(m.lock().unwrap().0).is_some() {}
+
+ {
+ if None::<std::sync::MutexGuard<()>>.is_none() {}
+ }
+ if None::<std::sync::MutexGuard<()>>.is_none() {
+ } else {
+ }
+
+ if None::<std::sync::MutexGuard<()>>.is_none() {}
+
+ if Some(String::new()).is_some() {}
+ if Some((String::new(), ())).is_some() {}
+
+ // Poll
+ if Ready(m.lock()).is_ready() {}
+ if Ready(m.lock().unwrap().0).is_ready() {}
+
+ {
+ if Pending::<std::sync::MutexGuard<()>>.is_pending() {}
+ }
+ if Pending::<std::sync::MutexGuard<()>>.is_pending() {
+ } else {
+ }
+
+ if Pending::<std::sync::MutexGuard<()>>.is_pending() {}
+
+ if Ready(String::new()).is_ready() {}
+ if Ready((String::new(), ())).is_ready() {}
+}
--- /dev/null
+// run-rustfix
+
+// Issue #5746
+#![warn(clippy::redundant_pattern_matching)]
+#![allow(clippy::if_same_then_else)]
+use std::task::Poll::{Pending, Ready};
+
+fn main() {
+ let m = std::sync::Mutex::new((0, 0));
+
+ // Result
+ if let Ok(_) = m.lock() {}
+ if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {}
+
+ {
+ if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {}
+ }
+ if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {
+ } else {
+ }
+ if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {}
+ if let Err(_) = Err::<std::sync::MutexGuard<()>, _>(()) {}
+
+ if let Ok(_) = Ok::<_, ()>(String::new()) {}
+ if let Err(_) = Err::<(), _>((String::new(), ())) {}
+
+ // Option
+ if let Some(_) = Some(m.lock()) {}
+ if let Some(_) = Some(m.lock().unwrap().0) {}
+
+ {
+ if let None = None::<std::sync::MutexGuard<()>> {}
+ }
+ if let None = None::<std::sync::MutexGuard<()>> {
+ } else {
+ }
+
+ if let None = None::<std::sync::MutexGuard<()>> {}
+
+ if let Some(_) = Some(String::new()) {}
+ if let Some(_) = Some((String::new(), ())) {}
+
+ // Poll
+ if let Ready(_) = Ready(m.lock()) {}
+ if let Ready(_) = Ready(m.lock().unwrap().0) {}
+
+ {
+ if let Pending = Pending::<std::sync::MutexGuard<()>> {}
+ }
+ if let Pending = Pending::<std::sync::MutexGuard<()>> {
+ } else {
+ }
+
+ if let Pending = Pending::<std::sync::MutexGuard<()>> {}
+
+ if let Ready(_) = Ready(String::new()) {}
+ if let Ready(_) = Ready((String::new(), ())) {}
+}
--- /dev/null
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:12:12
+ |
+LL | if let Ok(_) = m.lock() {}
+ | -------^^^^^----------- help: try this: `if m.lock().is_ok()`
+ |
+ = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:13:12
+ |
+LL | if let Err(_) = Err::<(), _>(m.lock().unwrap().0) {}
+ | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>(m.lock().unwrap().0).is_err()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:16:16
+ |
+LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {}
+ | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:18:12
+ |
+LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {
+ | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:21:12
+ |
+LL | if let Ok(_) = Ok::<_, std::sync::MutexGuard<()>>(()) {}
+ | -------^^^^^----------------------------------------- help: try this: `if Ok::<_, std::sync::MutexGuard<()>>(()).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:22:12
+ |
+LL | if let Err(_) = Err::<std::sync::MutexGuard<()>, _>(()) {}
+ | -------^^^^^^------------------------------------------ help: try this: `if Err::<std::sync::MutexGuard<()>, _>(()).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:24:12
+ |
+LL | if let Ok(_) = Ok::<_, ()>(String::new()) {}
+ | -------^^^^^----------------------------- help: try this: `if Ok::<_, ()>(String::new()).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:25:12
+ |
+LL | if let Err(_) = Err::<(), _>((String::new(), ())) {}
+ | -------^^^^^^------------------------------------ help: try this: `if Err::<(), _>((String::new(), ())).is_err()`
+
+error: redundant pattern matching, consider using `is_some()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:28:12
+ |
+LL | if let Some(_) = Some(m.lock()) {}
+ | -------^^^^^^^----------------- help: try this: `if Some(m.lock()).is_some()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_some()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:29:12
+ |
+LL | if let Some(_) = Some(m.lock().unwrap().0) {}
+ | -------^^^^^^^---------------------------- help: try this: `if Some(m.lock().unwrap().0).is_some()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_none()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:32:16
+ |
+LL | if let None = None::<std::sync::MutexGuard<()>> {}
+ | -------^^^^------------------------------------ help: try this: `if None::<std::sync::MutexGuard<()>>.is_none()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_none()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:34:12
+ |
+LL | if let None = None::<std::sync::MutexGuard<()>> {
+ | -------^^^^------------------------------------ help: try this: `if None::<std::sync::MutexGuard<()>>.is_none()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_none()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:38:12
+ |
+LL | if let None = None::<std::sync::MutexGuard<()>> {}
+ | -------^^^^------------------------------------ help: try this: `if None::<std::sync::MutexGuard<()>>.is_none()`
+
+error: redundant pattern matching, consider using `is_some()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:40:12
+ |
+LL | if let Some(_) = Some(String::new()) {}
+ | -------^^^^^^^---------------------- help: try this: `if Some(String::new()).is_some()`
+
+error: redundant pattern matching, consider using `is_some()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:41:12
+ |
+LL | if let Some(_) = Some((String::new(), ())) {}
+ | -------^^^^^^^---------------------------- help: try this: `if Some((String::new(), ())).is_some()`
+
+error: redundant pattern matching, consider using `is_ready()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:44:12
+ |
+LL | if let Ready(_) = Ready(m.lock()) {}
+ | -------^^^^^^^^------------------ help: try this: `if Ready(m.lock()).is_ready()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_ready()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:45:12
+ |
+LL | if let Ready(_) = Ready(m.lock().unwrap().0) {}
+ | -------^^^^^^^^----------------------------- help: try this: `if Ready(m.lock().unwrap().0).is_ready()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_pending()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:48:16
+ |
+LL | if let Pending = Pending::<std::sync::MutexGuard<()>> {}
+ | -------^^^^^^^--------------------------------------- help: try this: `if Pending::<std::sync::MutexGuard<()>>.is_pending()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_pending()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:50:12
+ |
+LL | if let Pending = Pending::<std::sync::MutexGuard<()>> {
+ | -------^^^^^^^--------------------------------------- help: try this: `if Pending::<std::sync::MutexGuard<()>>.is_pending()`
+ |
+ = note: this will change drop order of the result, as well as all temporaries
+ = note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+
+error: redundant pattern matching, consider using `is_pending()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:54:12
+ |
+LL | if let Pending = Pending::<std::sync::MutexGuard<()>> {}
+ | -------^^^^^^^--------------------------------------- help: try this: `if Pending::<std::sync::MutexGuard<()>>.is_pending()`
+
+error: redundant pattern matching, consider using `is_ready()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:56:12
+ |
+LL | if let Ready(_) = Ready(String::new()) {}
+ | -------^^^^^^^^----------------------- help: try this: `if Ready(String::new()).is_ready()`
+
+error: redundant pattern matching, consider using `is_ready()`
+ --> $DIR/redundant_pattern_matching_drop_order.rs:57:12
+ |
+LL | if let Ready(_) = Ready((String::new(), ())) {}
+ | -------^^^^^^^^----------------------------- help: try this: `if Ready((String::new(), ())).is_ready()`
+
+error: aborting due to 22 previous errors
+
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
-#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+#![allow(
+ unused_must_use,
+ clippy::needless_bool,
+ clippy::match_like_matches_macro,
+ clippy::if_same_then_else
+)]
fn main() {
if None::<()>.is_none() {}
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
-#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+#![allow(
+ unused_must_use,
+ clippy::needless_bool,
+ clippy::match_like_matches_macro,
+ clippy::if_same_then_else
+)]
fn main() {
if let None = None::<()> {}
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:8:12
+ --> $DIR/redundant_pattern_matching_option.rs:13:12
|
LL | if let None = None::<()> {}
| -------^^^^------------- help: try this: `if None::<()>.is_none()`
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:10:12
+ --> $DIR/redundant_pattern_matching_option.rs:15:12
|
LL | if let Some(_) = Some(42) {}
| -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:12:12
+ --> $DIR/redundant_pattern_matching_option.rs:17:12
|
LL | if let Some(_) = Some(42) {
| -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:18:15
+ --> $DIR/redundant_pattern_matching_option.rs:23:15
|
LL | while let Some(_) = Some(42) {}
| ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:20:15
+ --> $DIR/redundant_pattern_matching_option.rs:25:15
|
LL | while let None = Some(42) {}
| ----------^^^^----------- help: try this: `while Some(42).is_none()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:22:15
+ --> $DIR/redundant_pattern_matching_option.rs:27:15
|
LL | while let None = None::<()> {}
| ----------^^^^------------- help: try this: `while None::<()>.is_none()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:25:15
+ --> $DIR/redundant_pattern_matching_option.rs:30:15
|
LL | while let Some(_) = v.pop() {
| ----------^^^^^^^---------- help: try this: `while v.pop().is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:33:5
+ --> $DIR/redundant_pattern_matching_option.rs:38:5
|
LL | / match Some(42) {
LL | | Some(_) => true,
| |_____^ help: try this: `Some(42).is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:38:5
+ --> $DIR/redundant_pattern_matching_option.rs:43:5
|
LL | / match None::<()> {
LL | | Some(_) => false,
| |_____^ help: try this: `None::<()>.is_none()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:43:13
+ --> $DIR/redundant_pattern_matching_option.rs:48:13
|
LL | let _ = match None::<()> {
| _____________^
| |_____^ help: try this: `None::<()>.is_none()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:49:20
+ --> $DIR/redundant_pattern_matching_option.rs:54:20
|
LL | let _ = if let Some(_) = opt { true } else { false };
| -------^^^^^^^------ help: try this: `if opt.is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:53:20
+ --> $DIR/redundant_pattern_matching_option.rs:58:20
|
LL | let _ = if let Some(_) = gen_opt() {
| -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:55:19
+ --> $DIR/redundant_pattern_matching_option.rs:60:19
|
LL | } else if let None = gen_opt() {
| -------^^^^------------ help: try this: `if gen_opt().is_none()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:74:12
+ --> $DIR/redundant_pattern_matching_option.rs:79:12
|
LL | if let Some(_) = Some(42) {}
| -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:76:12
+ --> $DIR/redundant_pattern_matching_option.rs:81:12
|
LL | if let None = None::<()> {}
| -------^^^^------------- help: try this: `if None::<()>.is_none()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:78:15
+ --> $DIR/redundant_pattern_matching_option.rs:83:15
|
LL | while let Some(_) = Some(42) {}
| ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:80:15
+ --> $DIR/redundant_pattern_matching_option.rs:85:15
|
LL | while let None = None::<()> {}
| ----------^^^^------------- help: try this: `while None::<()>.is_none()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_option.rs:82:5
+ --> $DIR/redundant_pattern_matching_option.rs:87:5
|
LL | / match Some(42) {
LL | | Some(_) => true,
| |_____^ help: try this: `Some(42).is_some()`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/redundant_pattern_matching_option.rs:87:5
+ --> $DIR/redundant_pattern_matching_option.rs:92:5
|
LL | / match None::<()> {
LL | | Some(_) => false,
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
-#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+#![allow(
+ unused_must_use,
+ clippy::needless_bool,
+ clippy::match_like_matches_macro,
+ clippy::if_same_then_else
+)]
use std::task::Poll::{self, Pending, Ready};
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
-#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+#![allow(
+ unused_must_use,
+ clippy::needless_bool,
+ clippy::match_like_matches_macro,
+ clippy::if_same_then_else
+)]
use std::task::Poll::{self, Pending, Ready};
error: redundant pattern matching, consider using `is_pending()`
- --> $DIR/redundant_pattern_matching_poll.rs:10:12
+ --> $DIR/redundant_pattern_matching_poll.rs:15:12
|
LL | if let Pending = Pending::<()> {}
| -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_ready()`
- --> $DIR/redundant_pattern_matching_poll.rs:12:12
+ --> $DIR/redundant_pattern_matching_poll.rs:17:12
|
LL | if let Ready(_) = Ready(42) {}
| -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
error: redundant pattern matching, consider using `is_ready()`
- --> $DIR/redundant_pattern_matching_poll.rs:14:12
+ --> $DIR/redundant_pattern_matching_poll.rs:19:12
|
LL | if let Ready(_) = Ready(42) {
| -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
error: redundant pattern matching, consider using `is_ready()`
- --> $DIR/redundant_pattern_matching_poll.rs:20:15
+ --> $DIR/redundant_pattern_matching_poll.rs:25:15
|
LL | while let Ready(_) = Ready(42) {}
| ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
error: redundant pattern matching, consider using `is_pending()`
- --> $DIR/redundant_pattern_matching_poll.rs:22:15
+ --> $DIR/redundant_pattern_matching_poll.rs:27:15
|
LL | while let Pending = Ready(42) {}
| ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()`
error: redundant pattern matching, consider using `is_pending()`
- --> $DIR/redundant_pattern_matching_poll.rs:24:15
+ --> $DIR/redundant_pattern_matching_poll.rs:29:15
|
LL | while let Pending = Pending::<()> {}
| ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
error: redundant pattern matching, consider using `is_ready()`
- --> $DIR/redundant_pattern_matching_poll.rs:30:5
+ --> $DIR/redundant_pattern_matching_poll.rs:35:5
|
LL | / match Ready(42) {
LL | | Ready(_) => true,
| |_____^ help: try this: `Ready(42).is_ready()`
error: redundant pattern matching, consider using `is_pending()`
- --> $DIR/redundant_pattern_matching_poll.rs:35:5
+ --> $DIR/redundant_pattern_matching_poll.rs:40:5
|
LL | / match Pending::<()> {
LL | | Ready(_) => false,
| |_____^ help: try this: `Pending::<()>.is_pending()`
error: redundant pattern matching, consider using `is_pending()`
- --> $DIR/redundant_pattern_matching_poll.rs:40:13
+ --> $DIR/redundant_pattern_matching_poll.rs:45:13
|
LL | let _ = match Pending::<()> {
| _____________^
| |_____^ help: try this: `Pending::<()>.is_pending()`
error: redundant pattern matching, consider using `is_ready()`
- --> $DIR/redundant_pattern_matching_poll.rs:46:20
+ --> $DIR/redundant_pattern_matching_poll.rs:51:20
|
LL | let _ = if let Ready(_) = poll { true } else { false };
| -------^^^^^^^^------- help: try this: `if poll.is_ready()`
error: redundant pattern matching, consider using `is_ready()`
- --> $DIR/redundant_pattern_matching_poll.rs:50:20
+ --> $DIR/redundant_pattern_matching_poll.rs:55:20
|
LL | let _ = if let Ready(_) = gen_poll() {
| -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()`
error: redundant pattern matching, consider using `is_pending()`
- --> $DIR/redundant_pattern_matching_poll.rs:52:19
+ --> $DIR/redundant_pattern_matching_poll.rs:57:19
|
LL | } else if let Pending = gen_poll() {
| -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()`
error: redundant pattern matching, consider using `is_ready()`
- --> $DIR/redundant_pattern_matching_poll.rs:68:12
+ --> $DIR/redundant_pattern_matching_poll.rs:73:12
|
LL | if let Ready(_) = Ready(42) {}
| -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
error: redundant pattern matching, consider using `is_pending()`
- --> $DIR/redundant_pattern_matching_poll.rs:70:12
+ --> $DIR/redundant_pattern_matching_poll.rs:75:12
|
LL | if let Pending = Pending::<()> {}
| -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
error: redundant pattern matching, consider using `is_ready()`
- --> $DIR/redundant_pattern_matching_poll.rs:72:15
+ --> $DIR/redundant_pattern_matching_poll.rs:77:15
|
LL | while let Ready(_) = Ready(42) {}
| ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
error: redundant pattern matching, consider using `is_pending()`
- --> $DIR/redundant_pattern_matching_poll.rs:74:15
+ --> $DIR/redundant_pattern_matching_poll.rs:79:15
|
LL | while let Pending = Pending::<()> {}
| ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
error: redundant pattern matching, consider using `is_ready()`
- --> $DIR/redundant_pattern_matching_poll.rs:76:5
+ --> $DIR/redundant_pattern_matching_poll.rs:81:5
|
LL | / match Ready(42) {
LL | | Ready(_) => true,
| |_____^ help: try this: `Ready(42).is_ready()`
error: redundant pattern matching, consider using `is_pending()`
- --> $DIR/redundant_pattern_matching_poll.rs:81:5
+ --> $DIR/redundant_pattern_matching_poll.rs:86:5
|
LL | / match Pending::<()> {
LL | | Ready(_) => false,
clippy::needless_bool,
clippy::match_like_matches_macro,
clippy::unnecessary_wraps,
- deprecated
+ deprecated,
+ clippy::if_same_then_else
)]
fn main() {
clippy::needless_bool,
clippy::match_like_matches_macro,
clippy::unnecessary_wraps,
- deprecated
+ deprecated,
+ clippy::if_same_then_else
)]
fn main() {
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:15:12
+ --> $DIR/redundant_pattern_matching_result.rs:16:12
|
LL | if let Ok(_) = &result {}
| -------^^^^^---------- help: try this: `if result.is_ok()`
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:17:12
+ --> $DIR/redundant_pattern_matching_result.rs:18:12
|
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:19:12
+ --> $DIR/redundant_pattern_matching_result.rs:20:12
|
LL | if let Err(_) = Err::<i32, i32>(42) {}
| -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:21:15
+ --> $DIR/redundant_pattern_matching_result.rs:22:15
|
LL | while let Ok(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:23:15
+ --> $DIR/redundant_pattern_matching_result.rs:24:15
|
LL | while let Err(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:33:5
+ --> $DIR/redundant_pattern_matching_result.rs:34:5
|
LL | / match Ok::<i32, i32>(42) {
LL | | Ok(_) => true,
| |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:38:5
+ --> $DIR/redundant_pattern_matching_result.rs:39:5
|
LL | / match Ok::<i32, i32>(42) {
LL | | Ok(_) => false,
| |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:43:5
+ --> $DIR/redundant_pattern_matching_result.rs:44:5
|
LL | / match Err::<i32, i32>(42) {
LL | | Ok(_) => false,
| |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:48:5
+ --> $DIR/redundant_pattern_matching_result.rs:49:5
|
LL | / match Err::<i32, i32>(42) {
LL | | Ok(_) => true,
| |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:53:20
+ --> $DIR/redundant_pattern_matching_result.rs:54:20
|
LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
| -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:59:20
+ --> $DIR/redundant_pattern_matching_result.rs:60:20
|
LL | let _ = if let Ok(_) = gen_res() {
| -------^^^^^------------ help: try this: `if gen_res().is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:61:19
+ --> $DIR/redundant_pattern_matching_result.rs:62:19
|
LL | } else if let Err(_) = gen_res() {
| -------^^^^^^------------ help: try this: `if gen_res().is_err()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:84:19
+ --> $DIR/redundant_pattern_matching_result.rs:85:19
|
LL | while let Some(_) = r#try!(result_opt()) {}
| ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:85:16
+ --> $DIR/redundant_pattern_matching_result.rs:86:16
|
LL | if let Some(_) = r#try!(result_opt()) {}
| -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:91:12
+ --> $DIR/redundant_pattern_matching_result.rs:92:12
|
LL | if let Some(_) = m!() {}
| -------^^^^^^^------- help: try this: `if m!().is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:92:15
+ --> $DIR/redundant_pattern_matching_result.rs:93:15
|
LL | while let Some(_) = m!() {}
| ----------^^^^^^^------- help: try this: `while m!().is_some()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:110:12
+ --> $DIR/redundant_pattern_matching_result.rs:111:12
|
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:112:12
+ --> $DIR/redundant_pattern_matching_result.rs:113:12
|
LL | if let Err(_) = Err::<i32, i32>(42) {}
| -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:114:15
+ --> $DIR/redundant_pattern_matching_result.rs:115:15
|
LL | while let Ok(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:116:15
+ --> $DIR/redundant_pattern_matching_result.rs:117:15
|
LL | while let Err(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:118:5
+ --> $DIR/redundant_pattern_matching_result.rs:119:5
|
LL | / match Ok::<i32, i32>(42) {
LL | | Ok(_) => true,
| |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:123:5
+ --> $DIR/redundant_pattern_matching_result.rs:124:5
|
LL | / match Err::<i32, i32>(42) {
LL | | Ok(_) => false,