diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 022ba5d8414..6ab2bd59137 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ and resolved paths. To figure out how this syntax structure is encoded in the AST, it is recommended to run `rustc -Z unpretty=ast-tree` on an example of the structure and compare with the [nodes in the AST docs]. Usually the lint will end up to be a nested series of matches and ifs, [like so][deep-nesting]. -But we can make it nest-less by using [if_chain] macro, [like this][nest-less]. +But we can make it nest-less by using [let chains], [like this][nest-less]. [`E-medium`] issues are generally pretty easy too, though it's recommended you work on an [`good-first-issue`] first. Sometimes they are only somewhat involved code wise, but not difficult per-se. @@ -87,9 +87,9 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us [`E-medium`]: https://github.com/rust-lang/rust-clippy/labels/E-medium [`ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty [nodes in the AST docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/ -[deep-nesting]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/mem_forget.rs#L29-L43 -[if_chain]: https://docs.rs/if_chain/*/if_chain -[nest-less]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/bit_mask.rs#L124-L150 +[deep-nesting]: https://github.com/rust-lang/rust-clippy/blob/5e4f0922911536f80d9591180fa604229ac13939/clippy_lints/src/mem_forget.rs#L31-L45 +[let chains]: https://github.com/rust-lang/rust/pull/94927 +[nest-less]: https://github.com/rust-lang/rust-clippy/blob/5e4f0922911536f80d9591180fa604229ac13939/clippy_lints/src/bit_mask.rs#L133-L159 ## Writing code diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index ca4af66cad1..dc7e400fdc2 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -1,7 +1,6 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::sugg::Sugg; -use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; @@ -130,23 +129,24 @@ impl<'tcx> LateLintPass<'tcx> for BitMask { } } } - if_chain! { - if let ExprKind::Binary(op, left, right) = &e.kind; - if BinOpKind::Eq == op.node; - if let ExprKind::Binary(op1, left1, right1) = &left.kind; - if BinOpKind::BitAnd == op1.node; - if let ExprKind::Lit(lit) = &right1.kind; - if let LitKind::Int(n, _) = lit.node; - if let ExprKind::Lit(lit1) = &right.kind; - if let LitKind::Int(0, _) = lit1.node; - if n.leading_zeros() == n.count_zeros(); - if n > u128::from(self.verbose_bit_mask_threshold); - then { - span_lint_and_then(cx, - VERBOSE_BIT_MASK, - e.span, - "bit mask could be simplified with a call to `trailing_zeros`", - |diag| { + + if let ExprKind::Binary(op, left, right) = &e.kind + && BinOpKind::Eq == op.node + && let ExprKind::Binary(op1, left1, right1) = &left.kind + && BinOpKind::BitAnd == op1.node + && let ExprKind::Lit(lit) = &right1.kind + && let LitKind::Int(n, _) = lit.node + && let ExprKind::Lit(lit1) = &right.kind + && let LitKind::Int(0, _) = lit1.node + && n.leading_zeros() == n.count_zeros() + && n > u128::from(self.verbose_bit_mask_threshold) + { + span_lint_and_then( + cx, + VERBOSE_BIT_MASK, + e.span, + "bit mask could be simplified with a call to `trailing_zeros`", + |diag| { let sugg = Sugg::hir(cx, left1, "...").maybe_par(); diag.span_suggestion( e.span, @@ -154,8 +154,8 @@ impl<'tcx> LateLintPass<'tcx> for BitMask { format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()), Applicability::MaybeIncorrect, ); - }); - } + }, + ); } } } diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 5607e2264a6..4dc94d9f5a5 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -656,7 +656,7 @@ Here are some pointers to things you are likely going to need for every lint: * [Clippy utils][utils] - Various helper functions. Maybe the function you need is already in here ([`is_type_diagnostic_item`], [`implements_trait`], [`snippet`], etc) * [Clippy diagnostics][diagnostics] -* [The `if_chain` macro][if_chain] +* [Let chains][let-chains] * [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro] * [`Span`][span] * [`Applicability`][applicability] @@ -684,7 +684,7 @@ don't hesitate to ask on [Zulip] or in the issue/PR. [`is_type_diagnostic_item`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.is_type_diagnostic_item.html [`implements_trait`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.implements_trait.html [`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html -[if_chain]: https://docs.rs/if_chain/*/if_chain/ +[let-chains]: https://github.com/rust-lang/rust/pull/94927 [from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion [in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html [span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html diff --git a/doc/common_tools_writing_lints.md b/doc/common_tools_writing_lints.md index 828bf4cbef9..131ac3c3611 100644 --- a/doc/common_tools_writing_lints.md +++ b/doc/common_tools_writing_lints.md @@ -62,16 +62,14 @@ Starting with an `expr`, you can check whether it is calling a specific method ` ```rust impl<'tcx> LateLintPass<'tcx> for MyStructLint { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if_chain! { - // Check our expr is calling a method - if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind; + // Check our expr is calling a method + if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..]) = &expr.kind // Check the name of this method is `some_method` - if path.ident.name == sym!(some_method); + && path.ident.name == sym!(some_method) // Optionally, check the type of the self argument. // - See "Checking for a specific type" - then { + { // ... - } } } } @@ -165,18 +163,16 @@ use clippy_utils::{is_type_diagnostic_item, return_ty}; impl<'tcx> LateLintPass<'tcx> for MyTypeImpl { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { - if_chain! { - // Check if item is a method/function - if let ImplItemKind::Fn(ref signature, _) = impl_item.kind; + // Check if item is a method/function + if let ImplItemKind::Fn(ref signature, _) = impl_item.kind // Check the method is named `some_method` - if impl_item.ident.name == sym!(some_method); + && impl_item.ident.name == sym!(some_method) // We can also check it has a parameter `self` - if signature.decl.implicit_self.has_implicit_self(); + && signature.decl.implicit_self.has_implicit_self() // We can go further and even check if its return type is `String` - if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(string_type)); - then { - // ... - } + && is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym!(string_type)) + { + // ... } } }