Auto merge of #9855 - Alexendoo:needless-borrowed-ref-extra, r=xFrednet

Extend `needless_borrowed_reference` to structs and tuples, ignore _

changelog: [`needless_borrowed_reference`]: Lint struct and tuple patterns, and patterns containing `_`

Now lints patterns like

```rust
&(ref a, ref b)
&Tuple(ref a, ref b)
&Struct { ref a, ref b }

&(ref a, _)
```
This commit is contained in:
bors 2022-11-18 14:26:50 +00:00
commit d019fd9780
13 changed files with 357 additions and 115 deletions

View file

@ -250,7 +250,7 @@ impl LateLintPass<'_> for EnumVariantNames {
let item_name = item.ident.name.as_str();
let item_camel = to_camel_case(item_name);
if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
if let Some(&(ref mod_name, ref mod_camel)) = self.modules.last() {
if let Some((mod_name, mod_camel)) = self.modules.last() {
// constants don't have surrounding modules
if !mod_camel.is_empty() {
if mod_name == &item.ident.name {

View file

@ -62,58 +62,54 @@ impl IntPlusOne {
fn check_binop(cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<String> {
match (binop, &lhs.kind, &rhs.kind) {
// case where `x - 1 >= ...` or `-1 + x >= ...`
(BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => {
(BinOpKind::Ge, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) => {
match (lhskind.node, &lhslhs.kind, &lhsrhs.kind) {
// `-1 + x`
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if Self::check_lit(lit, -1) => {
(BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(lit, -1) => {
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
},
// `x - 1`
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
(BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
},
_ => None,
}
},
// case where `... >= y + 1` or `... >= 1 + y`
(BinOpKind::Ge, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs))
if rhskind.node == BinOpKind::Add =>
{
(BinOpKind::Ge, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) if rhskind.node == BinOpKind::Add => {
match (&rhslhs.kind, &rhsrhs.kind) {
// `y + 1` and `1 + y`
(&ExprKind::Lit(ref lit), _) if Self::check_lit(lit, 1) => {
(ExprKind::Lit(lit), _) if Self::check_lit(lit, 1) => {
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
},
(_, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
(_, ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
},
_ => None,
}
},
// case where `x + 1 <= ...` or `1 + x <= ...`
(BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _)
if lhskind.node == BinOpKind::Add =>
{
(BinOpKind::Le, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) if lhskind.node == BinOpKind::Add => {
match (&lhslhs.kind, &lhsrhs.kind) {
// `1 + x` and `x + 1`
(&ExprKind::Lit(ref lit), _) if Self::check_lit(lit, 1) => {
(ExprKind::Lit(lit), _) if Self::check_lit(lit, 1) => {
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
},
(_, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
(_, ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
},
_ => None,
}
},
// case where `... >= y - 1` or `... >= -1 + y`
(BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => {
(BinOpKind::Le, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) => {
match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
// `-1 + y`
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if Self::check_lit(lit, -1) => {
(BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(lit, -1) => {
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
},
// `y - 1`
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
(BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
},
_ => None,

View file

@ -366,8 +366,7 @@ fn check_for_is_empty<'tcx>(
}
fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
if let (&ExprKind::MethodCall(method_path, receiver, args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind)
{
if let (&ExprKind::MethodCall(method_path, receiver, args, _), ExprKind::Lit(lit)) = (&method.kind, &lit.kind) {
// check if we are in an is_empty() method
if let Some(name) = get_item_name(cx, method) {
if name.as_str() == "is_empty" {

View file

@ -36,14 +36,14 @@ declare_clippy_lint! {
declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]);
impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
if pat.span.from_expansion() {
fn check_pat(&mut self, cx: &LateContext<'tcx>, ref_pat: &'tcx Pat<'_>) {
if ref_pat.span.from_expansion() {
// OK, simple enough, lints doesn't check in macro.
return;
}
// Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
for (_, node) in cx.tcx.hir().parent_iter(pat.hir_id) {
for (_, node) in cx.tcx.hir().parent_iter(ref_pat.hir_id) {
let Node::Pat(pat) = node else { break };
if matches!(pat.kind, PatKind::Or(_)) {
@ -52,20 +52,20 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
}
// Only lint immutable refs, because `&mut ref T` may be useful.
let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind else { return };
let PatKind::Ref(pat, Mutability::Not) = ref_pat.kind else { return };
match sub_pat.kind {
match pat.kind {
// Check sub_pat got a `ref` keyword (excluding `ref mut`).
PatKind::Binding(BindingAnnotation::REF, _, ident, None) => {
span_lint_and_then(
cx,
NEEDLESS_BORROWED_REFERENCE,
pat.span,
ref_pat.span,
"this pattern takes a reference on something that is being dereferenced",
|diag| {
// `&ref ident`
// ^^^^^
let span = pat.span.until(ident.span);
let span = ref_pat.span.until(ident.span);
diag.span_suggestion_verbose(
span,
"try removing the `&ref` part",
@ -84,41 +84,71 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
}),
after,
) => {
let mut suggestions = Vec::new();
for element_pat in itertools::chain(before, after) {
if let PatKind::Binding(BindingAnnotation::REF, _, ident, None) = element_pat.kind {
// `&[..., ref ident, ...]`
// ^^^^
let span = element_pat.span.until(ident.span);
suggestions.push((span, String::new()));
} else {
return;
}
}
if !suggestions.is_empty() {
span_lint_and_then(
cx,
NEEDLESS_BORROWED_REFERENCE,
pat.span,
"dereferencing a slice pattern where every element takes a reference",
|diag| {
// `&[...]`
// ^
let span = pat.span.until(sub_pat.span);
suggestions.push((span, String::new()));
diag.multipart_suggestion(
"try removing the `&` and `ref` parts",
suggestions,
Applicability::MachineApplicable,
);
},
);
}
check_subpatterns(
cx,
"dereferencing a slice pattern where every element takes a reference",
ref_pat,
pat,
itertools::chain(before, after),
);
},
PatKind::Tuple(subpatterns, _) | PatKind::TupleStruct(_, subpatterns, _) => {
check_subpatterns(
cx,
"dereferencing a tuple pattern where every element takes a reference",
ref_pat,
pat,
subpatterns,
);
},
PatKind::Struct(_, fields, _) => {
check_subpatterns(
cx,
"dereferencing a struct pattern where every field's pattern takes a reference",
ref_pat,
pat,
fields.iter().map(|field| field.pat),
);
},
_ => {},
}
}
}
fn check_subpatterns<'tcx>(
cx: &LateContext<'tcx>,
message: &str,
ref_pat: &Pat<'_>,
pat: &Pat<'_>,
subpatterns: impl IntoIterator<Item = &'tcx Pat<'tcx>>,
) {
let mut suggestions = Vec::new();
for subpattern in subpatterns {
match subpattern.kind {
PatKind::Binding(BindingAnnotation::REF, _, ident, None) => {
// `ref ident`
// ^^^^
let span = subpattern.span.until(ident.span);
suggestions.push((span, String::new()));
},
PatKind::Wild => {},
_ => return,
}
}
if !suggestions.is_empty() {
span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, ref_pat.span, message, |diag| {
// `&pat`
// ^
let span = ref_pat.span.until(pat.span);
suggestions.push((span, String::new()));
diag.multipart_suggestion(
"try removing the `&` and `ref` parts",
suggestions,
Applicability::MachineApplicable,
);
});
}
}

View file

@ -50,7 +50,7 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext<'_>, span: Span) {
},
UseTreeKind::Simple(None, ..) | UseTreeKind::Glob => {},
UseTreeKind::Nested(ref nested_use_tree) => {
for &(ref use_tree, _) in nested_use_tree {
for (use_tree, _) in nested_use_tree {
check_use_tree(use_tree, cx, span);
}
},

View file

@ -51,8 +51,8 @@ pub enum Constant {
impl PartialEq for Constant {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(&Self::Str(ref ls), &Self::Str(ref rs)) => ls == rs,
(&Self::Binary(ref l), &Self::Binary(ref r)) => l == r,
(Self::Str(ls), Self::Str(rs)) => ls == rs,
(Self::Binary(l), Self::Binary(r)) => l == r,
(&Self::Char(l), &Self::Char(r)) => l == r,
(&Self::Int(l), &Self::Int(r)) => l == r,
(&Self::F64(l), &Self::F64(r)) => {
@ -69,8 +69,8 @@ impl PartialEq for Constant {
},
(&Self::Bool(l), &Self::Bool(r)) => l == r,
(&Self::Vec(ref l), &Self::Vec(ref r)) | (&Self::Tuple(ref l), &Self::Tuple(ref r)) => l == r,
(&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => ls == rs && lv == rv,
(&Self::Ref(ref lb), &Self::Ref(ref rb)) => *lb == *rb,
(Self::Repeat(lv, ls), Self::Repeat(rv, rs)) => ls == rs && lv == rv,
(Self::Ref(lb), Self::Ref(rb)) => *lb == *rb,
// TODO: are there inter-type equalities?
_ => false,
}
@ -126,8 +126,8 @@ impl Hash for Constant {
impl Constant {
pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
match (left, right) {
(&Self::Str(ref ls), &Self::Str(ref rs)) => Some(ls.cmp(rs)),
(&Self::Char(ref l), &Self::Char(ref r)) => Some(l.cmp(r)),
(Self::Str(ls), Self::Str(rs)) => Some(ls.cmp(rs)),
(Self::Char(l), Self::Char(r)) => Some(l.cmp(r)),
(&Self::Int(l), &Self::Int(r)) => match *cmp_type.kind() {
ty::Int(int_ty) => Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))),
ty::Uint(_) => Some(l.cmp(&r)),
@ -135,8 +135,8 @@ impl Constant {
},
(&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r),
(&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r),
(&Self::Bool(ref l), &Self::Bool(ref r)) => Some(l.cmp(r)),
(&Self::Tuple(ref l), &Self::Tuple(ref r)) if l.len() == r.len() => match *cmp_type.kind() {
(Self::Bool(l), Self::Bool(r)) => Some(l.cmp(r)),
(Self::Tuple(l), Self::Tuple(r)) if l.len() == r.len() => match *cmp_type.kind() {
ty::Tuple(tys) if tys.len() == l.len() => l
.iter()
.zip(r)
@ -146,7 +146,7 @@ impl Constant {
.unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
_ => None,
},
(&Self::Vec(ref l), &Self::Vec(ref r)) => {
(Self::Vec(l), Self::Vec(r)) => {
let (ty::Array(cmp_type, _) | ty::Slice(cmp_type)) = *cmp_type.kind() else {
return None
};
@ -155,7 +155,7 @@ impl Constant {
.find(|r| r.map_or(true, |o| o != Ordering::Equal))
.unwrap_or_else(|| Some(l.len().cmp(&r.len())))
},
(&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => {
(Self::Repeat(lv, ls), Self::Repeat(rv, rs)) => {
match Self::partial_cmp(
tcx,
match *cmp_type.kind() {
@ -169,7 +169,7 @@ impl Constant {
x => x,
}
},
(&Self::Ref(ref lb), &Self::Ref(ref rb)) => Self::partial_cmp(
(Self::Ref(lb), Self::Ref(rb)) => Self::partial_cmp(
tcx,
match *cmp_type.kind() {
ty::Ref(_, ty, _) => ty,

View file

@ -266,7 +266,7 @@ impl HirEqInterExpr<'_, '_, '_> {
(&ExprKind::Let(l), &ExprKind::Let(r)) => {
self.eq_pat(l.pat, r.pat) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && self.eq_expr(l.init, r.init)
},
(&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node,
(ExprKind::Lit(l), ExprKind::Lit(r)) => l.node == r.node,
(&ExprKind::Loop(lb, ref ll, ref lls, _), &ExprKind::Loop(rb, ref rl, ref rls, _)) => {
lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.name == r.ident.name)
},
@ -291,8 +291,8 @@ impl HirEqInterExpr<'_, '_, '_> {
(&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
self.eq_expr(le, re) && self.eq_array_length(ll, rl)
},
(&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
(&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r),
(ExprKind::Ret(l), ExprKind::Ret(r)) => both(l, r, |l, r| self.eq_expr(l, r)),
(ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
(&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
self.eq_qpath(l_path, r_path)
&& both(lo, ro, |l, r| self.eq_expr(l, r))
@ -362,7 +362,7 @@ impl HirEqInterExpr<'_, '_, '_> {
}
eq
},
(&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, r),
(PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r),
(&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_expr(l, r),
(&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
(&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => {
@ -429,13 +429,11 @@ impl HirEqInterExpr<'_, '_, '_> {
match (&left.kind, &right.kind) {
(&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
(&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl),
(&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty)
},
(&TyKind::Rptr(_, ref l_rmut), &TyKind::Rptr(_, ref r_rmut)) => {
(TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty),
(TyKind::Rptr(_, l_rmut), TyKind::Rptr(_, r_rmut)) => {
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
},
(&TyKind::Path(ref l), &TyKind::Path(ref r)) => self.eq_qpath(l, r),
(TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
(&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
(&TyKind::Infer, &TyKind::Infer) => true,
_ => false,

View file

@ -2,7 +2,12 @@
#![feature(custom_inner_attributes)]
#![warn(clippy::match_like_matches_macro)]
#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
#![allow(
unreachable_patterns,
dead_code,
clippy::equatable_if_let,
clippy::needless_borrowed_reference
)]
fn main() {
let x = Some(5);

View file

@ -2,7 +2,12 @@
#![feature(custom_inner_attributes)]
#![warn(clippy::match_like_matches_macro)]
#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
#![allow(
unreachable_patterns,
dead_code,
clippy::equatable_if_let,
clippy::needless_borrowed_reference
)]
fn main() {
let x = Some(5);

View file

@ -1,5 +1,5 @@
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:11:14
--> $DIR/match_expr_like_matches_macro.rs:16:14
|
LL | let _y = match x {
| ______________^
@ -11,7 +11,7 @@ LL | | };
= note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:17:14
--> $DIR/match_expr_like_matches_macro.rs:22:14
|
LL | let _w = match x {
| ______________^
@ -21,7 +21,7 @@ LL | | };
| |_____^ help: try this: `matches!(x, Some(_))`
error: redundant pattern matching, consider using `is_none()`
--> $DIR/match_expr_like_matches_macro.rs:23:14
--> $DIR/match_expr_like_matches_macro.rs:28:14
|
LL | let _z = match x {
| ______________^
@ -33,7 +33,7 @@ LL | | };
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:29:15
--> $DIR/match_expr_like_matches_macro.rs:34:15
|
LL | let _zz = match x {
| _______________^
@ -43,13 +43,13 @@ LL | | };
| |_____^ help: try this: `!matches!(x, Some(r) if r == 0)`
error: if let .. else expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:35:16
--> $DIR/match_expr_like_matches_macro.rs:40:16
|
LL | let _zzz = if let Some(5) = x { true } else { false };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:59:20
--> $DIR/match_expr_like_matches_macro.rs:64:20
|
LL | let _ans = match x {
| ____________________^
@ -60,7 +60,7 @@ LL | | };
| |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:69:20
--> $DIR/match_expr_like_matches_macro.rs:74:20
|
LL | let _ans = match x {
| ____________________^
@ -73,7 +73,7 @@ LL | | };
| |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:79:20
--> $DIR/match_expr_like_matches_macro.rs:84:20
|
LL | let _ans = match x {
| ____________________^
@ -84,7 +84,7 @@ LL | | };
| |_________^ help: try this: `!matches!(x, E::B(_) | E::C)`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:139:18
--> $DIR/match_expr_like_matches_macro.rs:144:18
|
LL | let _z = match &z {
| __________________^
@ -94,7 +94,7 @@ LL | | };
| |_________^ help: try this: `matches!(z, Some(3))`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:148:18
--> $DIR/match_expr_like_matches_macro.rs:153:18
|
LL | let _z = match &z {
| __________________^
@ -104,7 +104,7 @@ LL | | };
| |_________^ help: try this: `matches!(&z, Some(3))`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:165:21
--> $DIR/match_expr_like_matches_macro.rs:170:21
|
LL | let _ = match &z {
| _____________________^
@ -114,7 +114,7 @@ LL | | };
| |_____________^ help: try this: `matches!(&z, AnEnum::X)`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:179:20
--> $DIR/match_expr_like_matches_macro.rs:184:20
|
LL | let _res = match &val {
| ____________________^
@ -124,7 +124,7 @@ LL | | };
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:191:20
--> $DIR/match_expr_like_matches_macro.rs:196:20
|
LL | let _res = match &val {
| ____________________^
@ -134,7 +134,7 @@ LL | | };
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
error: match expression looks like `matches!` macro
--> $DIR/match_expr_like_matches_macro.rs:251:14
--> $DIR/match_expr_like_matches_macro.rs:256:14
|
LL | let _y = match Some(5) {
| ______________^

View file

@ -1,11 +1,32 @@
// run-rustfix
#![warn(clippy::needless_borrowed_reference)]
#![allow(unused, clippy::needless_borrow)]
#![allow(
unused,
irrefutable_let_patterns,
non_shorthand_field_patterns,
clippy::needless_borrow
)]
fn main() {}
fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
struct Struct {
a: usize,
b: usize,
c: usize,
}
struct TupleStruct(u8, u8, u8);
fn should_lint(
array: [u8; 4],
slice: &[u8],
slice_of_refs: &[&u8],
vec: Vec<u8>,
tuple: (u8, u8, u8),
tuple_struct: TupleStruct,
s: Struct,
) {
let mut v = Vec::<String>::new();
let _ = v.iter_mut().filter(|a| a.is_empty());
@ -24,16 +45,54 @@ fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>
if let [a, b, ..] = slice {}
if let [a, .., b] = slice {}
if let [.., a, b] = slice {}
if let [a, _] = slice {}
if let (a, b, c) = &tuple {}
if let (a, _, c) = &tuple {}
if let (a, ..) = &tuple {}
if let TupleStruct(a, ..) = &tuple_struct {}
if let Struct {
a,
b: b,
c: renamed,
} = &s
{}
if let Struct { a, b: _, .. } = &s {}
}
fn should_not_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
fn should_not_lint(
array: [u8; 4],
slice: &[u8],
slice_of_refs: &[&u8],
vec: Vec<u8>,
tuple: (u8, u8, u8),
tuple_struct: TupleStruct,
s: Struct,
) {
if let [ref a] = slice {}
if let &[ref a, b] = slice {}
if let &[ref a, .., b] = slice {}
if let &(ref a, b, ..) = &tuple {}
if let &TupleStruct(ref a, b, ..) = &tuple_struct {}
if let &Struct { ref a, b, .. } = &s {}
// must not be removed as variables must be bound consistently across | patterns
if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
// the `&`s here technically could be removed, but it'd be noisy and without a `ref` doesn't match
// the lint name
if let &[] = slice {}
if let &[_] = slice {}
if let &[..] = slice {}
if let &(..) = &tuple {}
if let &TupleStruct(..) = &tuple_struct {}
if let &Struct { .. } = &s {}
let mut var2 = 5;
let thingy2 = Some(&mut var2);
if let Some(&mut ref mut v) = thingy2 {
@ -59,6 +118,6 @@ fn foo(a: &Animal, b: &Animal) {
// lifetime mismatch error if there is no '&ref' before `feature(nll)` stabilization in 1.63
(&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
// ^ and ^ should **not** be linted
(&Animal::Dog(ref a), &Animal::Dog(_)) => (), // ^ should **not** be linted
(Animal::Dog(a), &Animal::Dog(_)) => (),
}
}

View file

@ -1,11 +1,32 @@
// run-rustfix
#![warn(clippy::needless_borrowed_reference)]
#![allow(unused, clippy::needless_borrow)]
#![allow(
unused,
irrefutable_let_patterns,
non_shorthand_field_patterns,
clippy::needless_borrow
)]
fn main() {}
fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
struct Struct {
a: usize,
b: usize,
c: usize,
}
struct TupleStruct(u8, u8, u8);
fn should_lint(
array: [u8; 4],
slice: &[u8],
slice_of_refs: &[&u8],
vec: Vec<u8>,
tuple: (u8, u8, u8),
tuple_struct: TupleStruct,
s: Struct,
) {
let mut v = Vec::<String>::new();
let _ = v.iter_mut().filter(|&ref a| a.is_empty());
@ -24,16 +45,54 @@ fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>
if let &[ref a, ref b, ..] = slice {}
if let &[ref a, .., ref b] = slice {}
if let &[.., ref a, ref b] = slice {}
if let &[ref a, _] = slice {}
if let &(ref a, ref b, ref c) = &tuple {}
if let &(ref a, _, ref c) = &tuple {}
if let &(ref a, ..) = &tuple {}
if let &TupleStruct(ref a, ..) = &tuple_struct {}
if let &Struct {
ref a,
b: ref b,
c: ref renamed,
} = &s
{}
if let &Struct { ref a, b: _, .. } = &s {}
}
fn should_not_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
fn should_not_lint(
array: [u8; 4],
slice: &[u8],
slice_of_refs: &[&u8],
vec: Vec<u8>,
tuple: (u8, u8, u8),
tuple_struct: TupleStruct,
s: Struct,
) {
if let [ref a] = slice {}
if let &[ref a, b] = slice {}
if let &[ref a, .., b] = slice {}
if let &(ref a, b, ..) = &tuple {}
if let &TupleStruct(ref a, b, ..) = &tuple_struct {}
if let &Struct { ref a, b, .. } = &s {}
// must not be removed as variables must be bound consistently across | patterns
if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
// the `&`s here technically could be removed, but it'd be noisy and without a `ref` doesn't match
// the lint name
if let &[] = slice {}
if let &[_] = slice {}
if let &[..] = slice {}
if let &(..) = &tuple {}
if let &TupleStruct(..) = &tuple_struct {}
if let &Struct { .. } = &s {}
let mut var2 = 5;
let thingy2 = Some(&mut var2);
if let Some(&mut ref mut v) = thingy2 {
@ -59,6 +118,6 @@ fn foo(a: &Animal, b: &Animal) {
// lifetime mismatch error if there is no '&ref' before `feature(nll)` stabilization in 1.63
(&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
// ^ and ^ should **not** be linted
(&Animal::Dog(ref a), &Animal::Dog(_)) => (), // ^ should **not** be linted
(Animal::Dog(a), &Animal::Dog(_)) => (),
}
}

View file

@ -1,5 +1,5 @@
error: this pattern takes a reference on something that is being dereferenced
--> $DIR/needless_borrowed_ref.rs:10:34
--> $DIR/needless_borrowed_ref.rs:31:34
|
LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty());
| ^^^^^^
@ -12,7 +12,7 @@ LL + let _ = v.iter_mut().filter(|a| a.is_empty());
|
error: this pattern takes a reference on something that is being dereferenced
--> $DIR/needless_borrowed_ref.rs:14:17
--> $DIR/needless_borrowed_ref.rs:35:17
|
LL | if let Some(&ref v) = thingy {}
| ^^^^^^
@ -24,7 +24,7 @@ LL + if let Some(v) = thingy {}
|
error: this pattern takes a reference on something that is being dereferenced
--> $DIR/needless_borrowed_ref.rs:16:14
--> $DIR/needless_borrowed_ref.rs:37:14
|
LL | if let &[&ref a, ref b] = slice_of_refs {}
| ^^^^^^
@ -36,7 +36,7 @@ LL + if let &[a, ref b] = slice_of_refs {}
|
error: dereferencing a slice pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:18:9
--> $DIR/needless_borrowed_ref.rs:39:9
|
LL | let &[ref a, ..] = &array;
| ^^^^^^^^^^^^
@ -48,7 +48,7 @@ LL + let [a, ..] = &array;
|
error: dereferencing a slice pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:19:9
--> $DIR/needless_borrowed_ref.rs:40:9
|
LL | let &[ref a, ref b, ..] = &array;
| ^^^^^^^^^^^^^^^^^^^
@ -60,7 +60,7 @@ LL + let [a, b, ..] = &array;
|
error: dereferencing a slice pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:21:12
--> $DIR/needless_borrowed_ref.rs:42:12
|
LL | if let &[ref a, ref b] = slice {}
| ^^^^^^^^^^^^^^^
@ -72,7 +72,7 @@ LL + if let [a, b] = slice {}
|
error: dereferencing a slice pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:22:12
--> $DIR/needless_borrowed_ref.rs:43:12
|
LL | if let &[ref a, ref b] = &vec[..] {}
| ^^^^^^^^^^^^^^^
@ -84,7 +84,7 @@ LL + if let [a, b] = &vec[..] {}
|
error: dereferencing a slice pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:24:12
--> $DIR/needless_borrowed_ref.rs:45:12
|
LL | if let &[ref a, ref b, ..] = slice {}
| ^^^^^^^^^^^^^^^^^^^
@ -96,7 +96,7 @@ LL + if let [a, b, ..] = slice {}
|
error: dereferencing a slice pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:25:12
--> $DIR/needless_borrowed_ref.rs:46:12
|
LL | if let &[ref a, .., ref b] = slice {}
| ^^^^^^^^^^^^^^^^^^^
@ -108,7 +108,7 @@ LL + if let [a, .., b] = slice {}
|
error: dereferencing a slice pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:26:12
--> $DIR/needless_borrowed_ref.rs:47:12
|
LL | if let &[.., ref a, ref b] = slice {}
| ^^^^^^^^^^^^^^^^^^^
@ -119,5 +119,96 @@ LL - if let &[.., ref a, ref b] = slice {}
LL + if let [.., a, b] = slice {}
|
error: aborting due to 10 previous errors
error: dereferencing a slice pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:49:12
|
LL | if let &[ref a, _] = slice {}
| ^^^^^^^^^^^
|
help: try removing the `&` and `ref` parts
|
LL - if let &[ref a, _] = slice {}
LL + if let [a, _] = slice {}
|
error: dereferencing a tuple pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:51:12
|
LL | if let &(ref a, ref b, ref c) = &tuple {}
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: try removing the `&` and `ref` parts
|
LL - if let &(ref a, ref b, ref c) = &tuple {}
LL + if let (a, b, c) = &tuple {}
|
error: dereferencing a tuple pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:52:12
|
LL | if let &(ref a, _, ref c) = &tuple {}
| ^^^^^^^^^^^^^^^^^^
|
help: try removing the `&` and `ref` parts
|
LL - if let &(ref a, _, ref c) = &tuple {}
LL + if let (a, _, c) = &tuple {}
|
error: dereferencing a tuple pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:53:12
|
LL | if let &(ref a, ..) = &tuple {}
| ^^^^^^^^^^^^
|
help: try removing the `&` and `ref` parts
|
LL - if let &(ref a, ..) = &tuple {}
LL + if let (a, ..) = &tuple {}
|
error: dereferencing a tuple pattern where every element takes a reference
--> $DIR/needless_borrowed_ref.rs:55:12
|
LL | if let &TupleStruct(ref a, ..) = &tuple_struct {}
| ^^^^^^^^^^^^^^^^^^^^^^^
|
help: try removing the `&` and `ref` parts
|
LL - if let &TupleStruct(ref a, ..) = &tuple_struct {}
LL + if let TupleStruct(a, ..) = &tuple_struct {}
|
error: dereferencing a struct pattern where every field's pattern takes a reference
--> $DIR/needless_borrowed_ref.rs:57:12
|
LL | if let &Struct {
| ____________^
LL | | ref a,
LL | | b: ref b,
LL | | c: ref renamed,
LL | | } = &s
| |_____^
|
help: try removing the `&` and `ref` parts
|
LL ~ if let Struct {
LL ~ a,
LL ~ b: b,
LL ~ c: renamed,
|
error: dereferencing a struct pattern where every field's pattern takes a reference
--> $DIR/needless_borrowed_ref.rs:64:12
|
LL | if let &Struct { ref a, b: _, .. } = &s {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: try removing the `&` and `ref` parts
|
LL - if let &Struct { ref a, b: _, .. } = &s {}
LL + if let Struct { a, b: _, .. } = &s {}
|
error: aborting due to 17 previous errors