mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-16 05:58:41 +00:00
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:
commit
d019fd9780
13 changed files with 357 additions and 115 deletions
|
@ -250,7 +250,7 @@ impl LateLintPass<'_> for EnumVariantNames {
|
||||||
let item_name = item.ident.name.as_str();
|
let item_name = item.ident.name.as_str();
|
||||||
let item_camel = to_camel_case(item_name);
|
let item_camel = to_camel_case(item_name);
|
||||||
if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
|
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
|
// constants don't have surrounding modules
|
||||||
if !mod_camel.is_empty() {
|
if !mod_camel.is_empty() {
|
||||||
if mod_name == &item.ident.name {
|
if mod_name == &item.ident.name {
|
||||||
|
|
|
@ -62,58 +62,54 @@ impl IntPlusOne {
|
||||||
fn check_binop(cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<String> {
|
fn check_binop(cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option<String> {
|
||||||
match (binop, &lhs.kind, &rhs.kind) {
|
match (binop, &lhs.kind, &rhs.kind) {
|
||||||
// case where `x - 1 >= ...` or `-1 + x >= ...`
|
// 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) {
|
match (lhskind.node, &lhslhs.kind, &lhsrhs.kind) {
|
||||||
// `-1 + x`
|
// `-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)
|
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
|
||||||
},
|
},
|
||||||
// `x - 1`
|
// `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)
|
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// case where `... >= y + 1` or `... >= 1 + y`
|
// case where `... >= y + 1` or `... >= 1 + y`
|
||||||
(BinOpKind::Ge, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs))
|
(BinOpKind::Ge, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) if rhskind.node == BinOpKind::Add => {
|
||||||
if rhskind.node == BinOpKind::Add =>
|
|
||||||
{
|
|
||||||
match (&rhslhs.kind, &rhsrhs.kind) {
|
match (&rhslhs.kind, &rhsrhs.kind) {
|
||||||
// `y + 1` and `1 + y`
|
// `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)
|
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)
|
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// case where `x + 1 <= ...` or `1 + x <= ...`
|
// case where `x + 1 <= ...` or `1 + x <= ...`
|
||||||
(BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _)
|
(BinOpKind::Le, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) if lhskind.node == BinOpKind::Add => {
|
||||||
if lhskind.node == BinOpKind::Add =>
|
|
||||||
{
|
|
||||||
match (&lhslhs.kind, &lhsrhs.kind) {
|
match (&lhslhs.kind, &lhsrhs.kind) {
|
||||||
// `1 + x` and `x + 1`
|
// `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)
|
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)
|
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// case where `... >= y - 1` or `... >= -1 + y`
|
// 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) {
|
match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
|
||||||
// `-1 + y`
|
// `-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)
|
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
|
||||||
},
|
},
|
||||||
// `y - 1`
|
// `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)
|
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -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) {
|
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
|
// check if we are in an is_empty() method
|
||||||
if let Some(name) = get_item_name(cx, method) {
|
if let Some(name) = get_item_name(cx, method) {
|
||||||
if name.as_str() == "is_empty" {
|
if name.as_str() == "is_empty" {
|
||||||
|
|
|
@ -36,14 +36,14 @@ declare_clippy_lint! {
|
||||||
declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]);
|
declare_lint_pass!(NeedlessBorrowedRef => [NEEDLESS_BORROWED_REFERENCE]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
|
impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
|
||||||
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
|
fn check_pat(&mut self, cx: &LateContext<'tcx>, ref_pat: &'tcx Pat<'_>) {
|
||||||
if pat.span.from_expansion() {
|
if ref_pat.span.from_expansion() {
|
||||||
// OK, simple enough, lints doesn't check in macro.
|
// OK, simple enough, lints doesn't check in macro.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
|
// 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 };
|
let Node::Pat(pat) = node else { break };
|
||||||
|
|
||||||
if matches!(pat.kind, PatKind::Or(_)) {
|
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.
|
// 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`).
|
// Check sub_pat got a `ref` keyword (excluding `ref mut`).
|
||||||
PatKind::Binding(BindingAnnotation::REF, _, ident, None) => {
|
PatKind::Binding(BindingAnnotation::REF, _, ident, None) => {
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
NEEDLESS_BORROWED_REFERENCE,
|
NEEDLESS_BORROWED_REFERENCE,
|
||||||
pat.span,
|
ref_pat.span,
|
||||||
"this pattern takes a reference on something that is being dereferenced",
|
"this pattern takes a reference on something that is being dereferenced",
|
||||||
|diag| {
|
|diag| {
|
||||||
// `&ref ident`
|
// `&ref ident`
|
||||||
// ^^^^^
|
// ^^^^^
|
||||||
let span = pat.span.until(ident.span);
|
let span = ref_pat.span.until(ident.span);
|
||||||
diag.span_suggestion_verbose(
|
diag.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
"try removing the `&ref` part",
|
"try removing the `&ref` part",
|
||||||
|
@ -84,41 +84,71 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
|
||||||
}),
|
}),
|
||||||
after,
|
after,
|
||||||
) => {
|
) => {
|
||||||
let mut suggestions = Vec::new();
|
check_subpatterns(
|
||||||
|
cx,
|
||||||
for element_pat in itertools::chain(before, after) {
|
"dereferencing a slice pattern where every element takes a reference",
|
||||||
if let PatKind::Binding(BindingAnnotation::REF, _, ident, None) = element_pat.kind {
|
ref_pat,
|
||||||
// `&[..., ref ident, ...]`
|
pat,
|
||||||
// ^^^^
|
itertools::chain(before, after),
|
||||||
let span = element_pat.span.until(ident.span);
|
);
|
||||||
suggestions.push((span, String::new()));
|
},
|
||||||
} else {
|
PatKind::Tuple(subpatterns, _) | PatKind::TupleStruct(_, subpatterns, _) => {
|
||||||
return;
|
check_subpatterns(
|
||||||
}
|
cx,
|
||||||
}
|
"dereferencing a tuple pattern where every element takes a reference",
|
||||||
|
ref_pat,
|
||||||
if !suggestions.is_empty() {
|
pat,
|
||||||
span_lint_and_then(
|
subpatterns,
|
||||||
cx,
|
);
|
||||||
NEEDLESS_BORROWED_REFERENCE,
|
},
|
||||||
pat.span,
|
PatKind::Struct(_, fields, _) => {
|
||||||
"dereferencing a slice pattern where every element takes a reference",
|
check_subpatterns(
|
||||||
|diag| {
|
cx,
|
||||||
// `&[...]`
|
"dereferencing a struct pattern where every field's pattern takes a reference",
|
||||||
// ^
|
ref_pat,
|
||||||
let span = pat.span.until(sub_pat.span);
|
pat,
|
||||||
suggestions.push((span, String::new()));
|
fields.iter().map(|field| field.pat),
|
||||||
|
);
|
||||||
diag.multipart_suggestion(
|
|
||||||
"try removing the `&` and `ref` parts",
|
|
||||||
suggestions,
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext<'_>, span: Span) {
|
||||||
},
|
},
|
||||||
UseTreeKind::Simple(None, ..) | UseTreeKind::Glob => {},
|
UseTreeKind::Simple(None, ..) | UseTreeKind::Glob => {},
|
||||||
UseTreeKind::Nested(ref nested_use_tree) => {
|
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);
|
check_use_tree(use_tree, cx, span);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -51,8 +51,8 @@ pub enum Constant {
|
||||||
impl PartialEq for Constant {
|
impl PartialEq for Constant {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(&Self::Str(ref ls), &Self::Str(ref rs)) => ls == rs,
|
(Self::Str(ls), Self::Str(rs)) => ls == rs,
|
||||||
(&Self::Binary(ref l), &Self::Binary(ref r)) => l == r,
|
(Self::Binary(l), Self::Binary(r)) => l == r,
|
||||||
(&Self::Char(l), &Self::Char(r)) => l == r,
|
(&Self::Char(l), &Self::Char(r)) => l == r,
|
||||||
(&Self::Int(l), &Self::Int(r)) => l == r,
|
(&Self::Int(l), &Self::Int(r)) => l == r,
|
||||||
(&Self::F64(l), &Self::F64(r)) => {
|
(&Self::F64(l), &Self::F64(r)) => {
|
||||||
|
@ -69,8 +69,8 @@ impl PartialEq for Constant {
|
||||||
},
|
},
|
||||||
(&Self::Bool(l), &Self::Bool(r)) => l == r,
|
(&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::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::Repeat(lv, ls), Self::Repeat(rv, rs)) => ls == rs && lv == rv,
|
||||||
(&Self::Ref(ref lb), &Self::Ref(ref rb)) => *lb == *rb,
|
(Self::Ref(lb), Self::Ref(rb)) => *lb == *rb,
|
||||||
// TODO: are there inter-type equalities?
|
// TODO: are there inter-type equalities?
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -126,8 +126,8 @@ impl Hash for Constant {
|
||||||
impl Constant {
|
impl Constant {
|
||||||
pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
|
pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(&Self::Str(ref ls), &Self::Str(ref rs)) => Some(ls.cmp(rs)),
|
(Self::Str(ls), Self::Str(rs)) => Some(ls.cmp(rs)),
|
||||||
(&Self::Char(ref l), &Self::Char(ref r)) => Some(l.cmp(r)),
|
(Self::Char(l), Self::Char(r)) => Some(l.cmp(r)),
|
||||||
(&Self::Int(l), &Self::Int(r)) => match *cmp_type.kind() {
|
(&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::Int(int_ty) => Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))),
|
||||||
ty::Uint(_) => Some(l.cmp(&r)),
|
ty::Uint(_) => Some(l.cmp(&r)),
|
||||||
|
@ -135,8 +135,8 @@ impl Constant {
|
||||||
},
|
},
|
||||||
(&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r),
|
(&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r),
|
||||||
(&Self::F32(l), &Self::F32(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::Bool(l), Self::Bool(r)) => Some(l.cmp(r)),
|
||||||
(&Self::Tuple(ref l), &Self::Tuple(ref r)) if l.len() == r.len() => match *cmp_type.kind() {
|
(Self::Tuple(l), Self::Tuple(r)) if l.len() == r.len() => match *cmp_type.kind() {
|
||||||
ty::Tuple(tys) if tys.len() == l.len() => l
|
ty::Tuple(tys) if tys.len() == l.len() => l
|
||||||
.iter()
|
.iter()
|
||||||
.zip(r)
|
.zip(r)
|
||||||
|
@ -146,7 +146,7 @@ impl Constant {
|
||||||
.unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
|
.unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
|
||||||
_ => None,
|
_ => 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 {
|
let (ty::Array(cmp_type, _) | ty::Slice(cmp_type)) = *cmp_type.kind() else {
|
||||||
return None
|
return None
|
||||||
};
|
};
|
||||||
|
@ -155,7 +155,7 @@ impl Constant {
|
||||||
.find(|r| r.map_or(true, |o| o != Ordering::Equal))
|
.find(|r| r.map_or(true, |o| o != Ordering::Equal))
|
||||||
.unwrap_or_else(|| Some(l.len().cmp(&r.len())))
|
.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(
|
match Self::partial_cmp(
|
||||||
tcx,
|
tcx,
|
||||||
match *cmp_type.kind() {
|
match *cmp_type.kind() {
|
||||||
|
@ -169,7 +169,7 @@ impl Constant {
|
||||||
x => x,
|
x => x,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(&Self::Ref(ref lb), &Self::Ref(ref rb)) => Self::partial_cmp(
|
(Self::Ref(lb), Self::Ref(rb)) => Self::partial_cmp(
|
||||||
tcx,
|
tcx,
|
||||||
match *cmp_type.kind() {
|
match *cmp_type.kind() {
|
||||||
ty::Ref(_, ty, _) => ty,
|
ty::Ref(_, ty, _) => ty,
|
||||||
|
|
|
@ -266,7 +266,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
(&ExprKind::Let(l), &ExprKind::Let(r)) => {
|
(&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)
|
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, _)) => {
|
(&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)
|
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)) => {
|
(&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
|
||||||
self.eq_expr(le, re) && self.eq_array_length(ll, 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::Ret(l), ExprKind::Ret(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::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
|
||||||
(&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
|
(&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
|
||||||
self.eq_qpath(l_path, r_path)
|
self.eq_qpath(l_path, r_path)
|
||||||
&& both(lo, ro, |l, r| self.eq_expr(l, r))
|
&& both(lo, ro, |l, r| self.eq_expr(l, r))
|
||||||
|
@ -362,7 +362,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
}
|
}
|
||||||
eq
|
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::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::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)) => {
|
(&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) {
|
match (&left.kind, &right.kind) {
|
||||||
(&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
|
(&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::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)) => {
|
(TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty),
|
||||||
l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty)
|
(TyKind::Rptr(_, l_rmut), TyKind::Rptr(_, r_rmut)) => {
|
||||||
},
|
|
||||||
(&TyKind::Rptr(_, ref l_rmut), &TyKind::Rptr(_, ref r_rmut)) => {
|
|
||||||
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
|
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::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
|
||||||
(&TyKind::Infer, &TyKind::Infer) => true,
|
(&TyKind::Infer, &TyKind::Infer) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
@ -2,7 +2,12 @@
|
||||||
|
|
||||||
#![feature(custom_inner_attributes)]
|
#![feature(custom_inner_attributes)]
|
||||||
#![warn(clippy::match_like_matches_macro)]
|
#![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() {
|
fn main() {
|
||||||
let x = Some(5);
|
let x = Some(5);
|
||||||
|
|
|
@ -2,7 +2,12 @@
|
||||||
|
|
||||||
#![feature(custom_inner_attributes)]
|
#![feature(custom_inner_attributes)]
|
||||||
#![warn(clippy::match_like_matches_macro)]
|
#![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() {
|
fn main() {
|
||||||
let x = Some(5);
|
let x = Some(5);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _y = match x {
|
||||||
| ______________^
|
| ______________^
|
||||||
|
@ -11,7 +11,7 @@ LL | | };
|
||||||
= note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
|
= note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _w = match x {
|
||||||
| ______________^
|
| ______________^
|
||||||
|
@ -21,7 +21,7 @@ LL | | };
|
||||||
| |_____^ help: try this: `matches!(x, Some(_))`
|
| |_____^ help: try this: `matches!(x, Some(_))`
|
||||||
|
|
||||||
error: redundant pattern matching, consider using `is_none()`
|
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 {
|
LL | let _z = match x {
|
||||||
| ______________^
|
| ______________^
|
||||||
|
@ -33,7 +33,7 @@ LL | | };
|
||||||
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
|
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _zz = match x {
|
||||||
| _______________^
|
| _______________^
|
||||||
|
@ -43,13 +43,13 @@ LL | | };
|
||||||
| |_____^ help: try this: `!matches!(x, Some(r) if r == 0)`
|
| |_____^ help: try this: `!matches!(x, Some(r) if r == 0)`
|
||||||
|
|
||||||
error: if let .. else expression looks like `matches!` macro
|
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 };
|
LL | let _zzz = if let Some(5) = x { true } else { false };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _ans = match x {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
@ -60,7 +60,7 @@ LL | | };
|
||||||
| |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
|
| |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _ans = match x {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
@ -73,7 +73,7 @@ LL | | };
|
||||||
| |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
|
| |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _ans = match x {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
@ -84,7 +84,7 @@ LL | | };
|
||||||
| |_________^ help: try this: `!matches!(x, E::B(_) | E::C)`
|
| |_________^ help: try this: `!matches!(x, E::B(_) | E::C)`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _z = match &z {
|
||||||
| __________________^
|
| __________________^
|
||||||
|
@ -94,7 +94,7 @@ LL | | };
|
||||||
| |_________^ help: try this: `matches!(z, Some(3))`
|
| |_________^ help: try this: `matches!(z, Some(3))`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _z = match &z {
|
||||||
| __________________^
|
| __________________^
|
||||||
|
@ -104,7 +104,7 @@ LL | | };
|
||||||
| |_________^ help: try this: `matches!(&z, Some(3))`
|
| |_________^ help: try this: `matches!(&z, Some(3))`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _ = match &z {
|
||||||
| _____________________^
|
| _____________________^
|
||||||
|
@ -114,7 +114,7 @@ LL | | };
|
||||||
| |_____________^ help: try this: `matches!(&z, AnEnum::X)`
|
| |_____________^ help: try this: `matches!(&z, AnEnum::X)`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _res = match &val {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
@ -124,7 +124,7 @@ LL | | };
|
||||||
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
|
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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 {
|
LL | let _res = match &val {
|
||||||
| ____________________^
|
| ____________________^
|
||||||
|
@ -134,7 +134,7 @@ LL | | };
|
||||||
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
|
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
|
||||||
|
|
||||||
error: match expression looks like `matches!` macro
|
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) {
|
LL | let _y = match Some(5) {
|
||||||
| ______________^
|
| ______________^
|
||||||
|
|
|
@ -1,11 +1,32 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
#![warn(clippy::needless_borrowed_reference)]
|
#![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 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 mut v = Vec::<String>::new();
|
||||||
let _ = v.iter_mut().filter(|a| a.is_empty());
|
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, .., 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] = slice {}
|
||||||
if let &[ref a, b] = slice {}
|
if let &[ref a, b] = 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
|
// must not be removed as variables must be bound consistently across | patterns
|
||||||
if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
|
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 mut var2 = 5;
|
||||||
let thingy2 = Some(&mut var2);
|
let thingy2 = Some(&mut var2);
|
||||||
if let Some(&mut ref mut v) = thingy2 {
|
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
|
// 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)) => (),
|
(&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
|
||||||
// ^ and ^ should **not** be linted
|
// ^ and ^ should **not** be linted
|
||||||
(&Animal::Dog(ref a), &Animal::Dog(_)) => (), // ^ should **not** be linted
|
(Animal::Dog(a), &Animal::Dog(_)) => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,32 @@
|
||||||
// run-rustfix
|
// run-rustfix
|
||||||
|
|
||||||
#![warn(clippy::needless_borrowed_reference)]
|
#![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 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 mut v = Vec::<String>::new();
|
||||||
let _ = v.iter_mut().filter(|&ref a| a.is_empty());
|
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, .., 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] = slice {}
|
||||||
if let &[ref a, b] = slice {}
|
if let &[ref a, b] = 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
|
// must not be removed as variables must be bound consistently across | patterns
|
||||||
if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
|
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 mut var2 = 5;
|
||||||
let thingy2 = Some(&mut var2);
|
let thingy2 = Some(&mut var2);
|
||||||
if let Some(&mut ref mut v) = thingy2 {
|
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
|
// 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)) => (),
|
(&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
|
||||||
// ^ and ^ should **not** be linted
|
// ^ and ^ should **not** be linted
|
||||||
(&Animal::Dog(ref a), &Animal::Dog(_)) => (), // ^ should **not** be linted
|
(Animal::Dog(a), &Animal::Dog(_)) => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: this pattern takes a reference on something that is being dereferenced
|
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());
|
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
|
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 {}
|
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
|
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 {}
|
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
|
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;
|
LL | let &[ref a, ..] = &array;
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -48,7 +48,7 @@ LL + let [a, ..] = &array;
|
||||||
|
|
|
|
||||||
|
|
||||||
error: dereferencing a slice pattern where every element takes a reference
|
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;
|
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
|
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 {}
|
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
|
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[..] {}
|
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
|
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 {}
|
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
|
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 {}
|
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
|
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 {}
|
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 {}
|
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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue