mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 13:13:34 +00:00
Auto merge of #101241 - camsteffen:refactor-binding-annotations, r=cjgillot
`BindingAnnotation` refactor * `ast::BindingMode` is deleted and replaced with `hir::BindingAnnotation` (which is moved to `ast`) * `BindingAnnotation` is changed from an enum to a tuple struct e.g. `BindingAnnotation(ByRef::No, Mutability::Mut)` * Associated constants added for convenience `BindingAnnotation::{NONE, REF, MUT, REF_MUT}` One goal is to make it more clear that `BindingAnnotation` merely represents syntax `ref mut` and not the actual binding mode. This was especially confusing since we had `ast::BindingMode`->`hir::BindingAnnotation`->`thir::BindingMode`. I wish there were more symmetry between `ByRef` and `Mutability` (variant) naming (maybe `Mutable::Yes`?), and I also don't love how long the name `BindingAnnotation` is, but this seems like the best compromise. Ideas welcome.
This commit is contained in:
commit
ce339b219a
35 changed files with 95 additions and 103 deletions
|
@ -503,7 +503,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
|
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
|
||||||
if let PatKind::Binding(BindingAnnotation::Ref, id, name, _) = pat.kind {
|
if let PatKind::Binding(BindingAnnotation::REF, id, name, _) = pat.kind {
|
||||||
if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) {
|
if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) {
|
||||||
// This binding id has been seen before. Add this pattern to the list of changes.
|
// This binding id has been seen before. Add this pattern to the list of changes.
|
||||||
if let Some(prev_pat) = opt_prev_pat {
|
if let Some(prev_pat) = opt_prev_pat {
|
||||||
|
|
|
@ -128,7 +128,7 @@ fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>)
|
||||||
if let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res);
|
if let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res);
|
||||||
|
|
||||||
// Find id of the local we found in the block
|
// Find id of the local we found in the block
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, local_hir_id, _ident, None) = local.pat.kind;
|
if let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind;
|
||||||
|
|
||||||
// If those two are the same hir id
|
// If those two are the same hir id
|
||||||
if res_pat.hir_id == local_hir_id;
|
if res_pat.hir_id == local_hir_id;
|
||||||
|
|
|
@ -95,12 +95,14 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir
|
||||||
let mut removed_pat: FxHashSet<hir::HirId> = FxHashSet::default();
|
let mut removed_pat: FxHashSet<hir::HirId> = FxHashSet::default();
|
||||||
let mut slices: FxIndexMap<hir::HirId, SliceLintInformation> = FxIndexMap::default();
|
let mut slices: FxIndexMap<hir::HirId, SliceLintInformation> = FxIndexMap::default();
|
||||||
pat.walk_always(|pat| {
|
pat.walk_always(|pat| {
|
||||||
if let hir::PatKind::Binding(binding, value_hir_id, ident, sub_pat) = pat.kind {
|
// We'll just ignore mut and ref mut for simplicity sake right now
|
||||||
// We'll just ignore mut and ref mut for simplicity sake right now
|
if let hir::PatKind::Binding(
|
||||||
if let hir::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut = binding {
|
hir::BindingAnnotation(by_ref, hir::Mutability::Not),
|
||||||
return;
|
value_hir_id,
|
||||||
}
|
ident,
|
||||||
|
sub_pat,
|
||||||
|
) = pat.kind
|
||||||
|
{
|
||||||
// This block catches bindings with sub patterns. It would be hard to build a correct suggestion
|
// This block catches bindings with sub patterns. It would be hard to build a correct suggestion
|
||||||
// for them and it's likely that the user knows what they are doing in such a case.
|
// for them and it's likely that the user knows what they are doing in such a case.
|
||||||
if removed_pat.contains(&value_hir_id) {
|
if removed_pat.contains(&value_hir_id) {
|
||||||
|
@ -116,7 +118,7 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir
|
||||||
if let ty::Slice(inner_ty) | ty::Array(inner_ty, _) = bound_ty.peel_refs().kind() {
|
if let ty::Slice(inner_ty) | ty::Array(inner_ty, _) = bound_ty.peel_refs().kind() {
|
||||||
// The values need to use the `ref` keyword if they can't be copied.
|
// The values need to use the `ref` keyword if they can't be copied.
|
||||||
// This will need to be adjusted if the lint want to support mutable access in the future
|
// This will need to be adjusted if the lint want to support mutable access in the future
|
||||||
let src_is_ref = bound_ty.is_ref() && binding != hir::BindingAnnotation::Ref;
|
let src_is_ref = bound_ty.is_ref() && by_ref != hir::ByRef::Yes;
|
||||||
let needs_ref = !(src_is_ref || is_copy(cx, *inner_ty));
|
let needs_ref = !(src_is_ref || is_copy(cx, *inner_ty));
|
||||||
|
|
||||||
let slice_info = slices
|
let slice_info = slices
|
||||||
|
|
|
@ -4,7 +4,7 @@ use clippy_utils::{path_to_local_id, visitors::is_local_used};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::BindingAnnotation;
|
use rustc_hir::{BindingAnnotation, Mutability};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mutability = match mode {
|
let mutability = match mode {
|
||||||
BindingAnnotation::RefMut | BindingAnnotation::Mutable => "<mut> ",
|
BindingAnnotation(_, Mutability::Mut) => "<mut> ",
|
||||||
_ => "",
|
_ => "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ fn get_binding(pat: &Pat<'_>) -> Option<HirId> {
|
||||||
hir_id = None;
|
hir_id = None;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let BindingAnnotation::Unannotated = annotation {
|
if let BindingAnnotation::NONE = annotation {
|
||||||
hir_id = Some(id);
|
hir_id = Some(id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId>
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Some(hir_id) = path_to_local(bound);
|
if let Some(hir_id) = path_to_local(bound);
|
||||||
if let Node::Pat(pat) = cx.tcx.hir().get(hir_id);
|
if let Node::Pat(pat) = cx.tcx.hir().get(hir_id);
|
||||||
if let PatKind::Binding(BindingAnnotation::Mutable, ..) = pat.kind;
|
if let PatKind::Binding(BindingAnnotation::MUT, ..) = pat.kind;
|
||||||
then {
|
then {
|
||||||
return Some(hir_id);
|
return Some(hir_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use if_chain::if_chain;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||||
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Node, Pat, PatKind, Stmt, StmtKind};
|
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Node, Pat, PatKind, Stmt, StmtKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
|
@ -65,7 +65,7 @@ pub(super) fn check<'tcx>(
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Node::Pat(pat) = node;
|
if let Node::Pat(pat) = node;
|
||||||
if let PatKind::Binding(bind_ann, ..) = pat.kind;
|
if let PatKind::Binding(bind_ann, ..) = pat.kind;
|
||||||
if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
|
if !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut));
|
||||||
let parent_node = cx.tcx.hir().get_parent_node(hir_id);
|
let parent_node = cx.tcx.hir().get_parent_node(hir_id);
|
||||||
if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
|
if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
|
||||||
if let Some(init) = parent_let_expr.init;
|
if let Some(init) = parent_let_expr.init;
|
||||||
|
|
|
@ -165,7 +165,7 @@ fn check<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// `ref` and `ref mut` annotations were handled earlier.
|
// `ref` and `ref mut` annotations were handled earlier.
|
||||||
let annotation = if matches!(annotation, BindingAnnotation::Mutable) {
|
let annotation = if matches!(annotation, BindingAnnotation::MUT) {
|
||||||
"mut "
|
"mut "
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::{is_lang_ctor, peel_blocks};
|
use clippy_utils::{is_lang_ctor, peel_blocks};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, LangItem, PatKind, QPath};
|
use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
|
||||||
|
@ -10,18 +10,17 @@ use super::MATCH_AS_REF;
|
||||||
|
|
||||||
pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
|
pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
|
||||||
if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() {
|
if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() {
|
||||||
let arm_ref: Option<BindingAnnotation> = if is_none_arm(cx, &arms[0]) {
|
let arm_ref_mut = if is_none_arm(cx, &arms[0]) {
|
||||||
is_ref_some_arm(cx, &arms[1])
|
is_ref_some_arm(cx, &arms[1])
|
||||||
} else if is_none_arm(cx, &arms[1]) {
|
} else if is_none_arm(cx, &arms[1]) {
|
||||||
is_ref_some_arm(cx, &arms[0])
|
is_ref_some_arm(cx, &arms[0])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
if let Some(rb) = arm_ref {
|
if let Some(rb) = arm_ref_mut {
|
||||||
let suggestion = if rb == BindingAnnotation::Ref {
|
let suggestion = match rb {
|
||||||
"as_ref"
|
Mutability::Not => "as_ref",
|
||||||
} else {
|
Mutability::Mut => "as_mut",
|
||||||
"as_mut"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_ty = cx.typeck_results().expr_ty(expr);
|
let output_ty = cx.typeck_results().expr_ty(expr);
|
||||||
|
@ -66,19 +65,18 @@ fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
|
// Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
|
||||||
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<BindingAnnotation> {
|
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind;
|
if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind;
|
||||||
if is_lang_ctor(cx, qpath, LangItem::OptionSome);
|
if is_lang_ctor(cx, qpath, LangItem::OptionSome);
|
||||||
if let PatKind::Binding(rb, .., ident, _) = first_pat.kind;
|
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind;
|
||||||
if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut;
|
|
||||||
if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind;
|
if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind;
|
||||||
if let ExprKind::Path(ref some_path) = e.kind;
|
if let ExprKind::Path(ref some_path) = e.kind;
|
||||||
if is_lang_ctor(cx, some_path, LangItem::OptionSome);
|
if is_lang_ctor(cx, some_path, LangItem::OptionSome);
|
||||||
if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind;
|
if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind;
|
||||||
if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
|
if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
|
||||||
then {
|
then {
|
||||||
return Some(rb)
|
return Some(mutabl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
|
@ -8,7 +8,7 @@ use clippy_utils::{
|
||||||
};
|
};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::OptionNone;
|
use rustc_hir::LangItem::OptionNone;
|
||||||
use rustc_hir::{Arm, BindingAnnotation, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath};
|
use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
use rustc_typeck::hir_ty_to_ty;
|
use rustc_typeck::hir_ty_to_ty;
|
||||||
|
@ -189,8 +189,7 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
) => {
|
) => {
|
||||||
return !matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut)
|
return !matches!(annot, BindingAnnotation(ByRef::Yes, _)) && pat_ident.name == first_seg.ident.name;
|
||||||
&& pat_ident.name == first_seg.ident.name;
|
|
||||||
},
|
},
|
||||||
// Example: `Custom::TypeA => Custom::TypeB`, or `None => None`
|
// Example: `Custom::TypeA => Custom::TypeB`, or `None => None`
|
||||||
(PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => {
|
(PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => {
|
||||||
|
|
|
@ -175,7 +175,7 @@ fn collect_pat_paths<'a>(acc: &mut Vec<Ty<'a>>, cx: &LateContext<'a>, pat: &Pat<
|
||||||
let p_ty = cx.typeck_results().pat_ty(p);
|
let p_ty = cx.typeck_results().pat_ty(p);
|
||||||
collect_pat_paths(acc, cx, p, p_ty);
|
collect_pat_paths(acc, cx, p, p_ty);
|
||||||
}),
|
}),
|
||||||
PatKind::TupleStruct(..) | PatKind::Binding(BindingAnnotation::Unannotated, .., None) | PatKind::Path(_) => {
|
PatKind::TupleStruct(..) | PatKind::Binding(BindingAnnotation::NONE, .., None) | PatKind::Path(_) => {
|
||||||
acc.push(ty);
|
acc.push(ty);
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
|
|
|
@ -4,7 +4,7 @@ use clippy_utils::source::snippet_with_context;
|
||||||
use clippy_utils::sugg;
|
use clippy_utils::sugg;
|
||||||
use clippy_utils::ty::is_copy;
|
use clippy_utils::ty::is_copy;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
|
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::{self, adjustment::Adjust};
|
use rustc_middle::ty::{self, adjustment::Adjust};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
@ -101,12 +101,7 @@ pub(super) fn check(
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
// local binding capturing a reference
|
// local binding capturing a reference
|
||||||
Some(Node::Local(l))
|
Some(Node::Local(l)) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => {
|
||||||
if matches!(
|
|
||||||
l.pat.kind,
|
|
||||||
PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..)
|
|
||||||
) =>
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
|
||||||
if let Some(id) = path_to_local(recv);
|
if let Some(id) = path_to_local(recv);
|
||||||
if let Node::Pat(pat) = cx.tcx.hir().get(id);
|
if let Node::Pat(pat) = cx.tcx.hir().get(id);
|
||||||
if let PatKind::Binding(ann, _, _, _) = pat.kind;
|
if let PatKind::Binding(ann, _, _, _) = pat.kind;
|
||||||
if ann != BindingAnnotation::Mutable;
|
if ann != BindingAnnotation::MUT;
|
||||||
then {
|
then {
|
||||||
application = Applicability::Unspecified;
|
application = Applicability::Unspecified;
|
||||||
diag.span_help(
|
diag.span_help(
|
||||||
|
|
|
@ -33,13 +33,13 @@ pub(super) fn check<'tcx>(
|
||||||
let closure_expr = peel_blocks(&closure_body.value);
|
let closure_expr = peel_blocks(&closure_body.value);
|
||||||
match closure_body.params[0].pat.kind {
|
match closure_body.params[0].pat.kind {
|
||||||
hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding(
|
hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding(
|
||||||
hir::BindingAnnotation::Unannotated, .., name, None
|
hir::BindingAnnotation::NONE, .., name, None
|
||||||
) = inner.kind {
|
) = inner.kind {
|
||||||
if ident_eq(name, closure_expr) {
|
if ident_eq(name, closure_expr) {
|
||||||
lint_explicit_closure(cx, e.span, recv.span, true, msrv);
|
lint_explicit_closure(cx, e.span, recv.span, true, msrv);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, .., name, None) => {
|
hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) => {
|
||||||
match closure_expr.kind {
|
match closure_expr.kind {
|
||||||
hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
|
hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
|
||||||
if ident_eq(name, inner) {
|
if ident_eq(name, inner) {
|
||||||
|
|
|
@ -130,7 +130,7 @@ fn check_manual_split_once_indirect(
|
||||||
let ctxt = expr.span.ctxt();
|
let ctxt = expr.span.ctxt();
|
||||||
let mut parents = cx.tcx.hir().parent_iter(expr.hir_id);
|
let mut parents = cx.tcx.hir().parent_iter(expr.hir_id);
|
||||||
if let (_, Node::Local(local)) = parents.next()?
|
if let (_, Node::Local(local)) = parents.next()?
|
||||||
&& let PatKind::Binding(BindingAnnotation::Mutable, iter_binding_id, iter_ident, None) = local.pat.kind
|
&& let PatKind::Binding(BindingAnnotation::MUT, iter_binding_id, iter_ident, None) = local.pat.kind
|
||||||
&& let (iter_stmt_id, Node::Stmt(_)) = parents.next()?
|
&& let (iter_stmt_id, Node::Stmt(_)) = parents.next()?
|
||||||
&& let (_, Node::Block(enclosing_block)) = parents.next()?
|
&& let (_, Node::Block(enclosing_block)) = parents.next()?
|
||||||
|
|
||||||
|
@ -212,11 +212,10 @@ fn indirect_usage<'tcx>(
|
||||||
ctxt: SyntaxContext,
|
ctxt: SyntaxContext,
|
||||||
) -> Option<IndirectUsage<'tcx>> {
|
) -> Option<IndirectUsage<'tcx>> {
|
||||||
if let StmtKind::Local(Local {
|
if let StmtKind::Local(Local {
|
||||||
pat:
|
pat: Pat {
|
||||||
Pat {
|
kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None),
|
||||||
kind: PatKind::Binding(BindingAnnotation::Unannotated, _, ident, None),
|
..
|
||||||
..
|
},
|
||||||
},
|
|
||||||
init: Some(init_expr),
|
init: Some(init_expr),
|
||||||
hir_id: local_hir_id,
|
hir_id: local_hir_id,
|
||||||
..
|
..
|
||||||
|
|
|
@ -5,8 +5,8 @@ use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
self as hir, def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt,
|
self as hir, def, BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind,
|
||||||
StmtKind, TyKind,
|
Stmt, StmtKind, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
|
@ -146,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for arg in iter_input_pats(decl, body) {
|
for arg in iter_input_pats(decl, body) {
|
||||||
if let PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..) = arg.pat.kind {
|
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind {
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
TOPLEVEL_REF_ARG,
|
TOPLEVEL_REF_ARG,
|
||||||
|
@ -162,9 +162,8 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if !in_external_macro(cx.tcx.sess, stmt.span);
|
if !in_external_macro(cx.tcx.sess, stmt.span);
|
||||||
if let StmtKind::Local(local) = stmt.kind;
|
if let StmtKind::Local(local) = stmt.kind;
|
||||||
if let PatKind::Binding(an, .., name, None) = local.pat.kind;
|
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind;
|
||||||
if let Some(init) = local.init;
|
if let Some(init) = local.init;
|
||||||
if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut;
|
|
||||||
then {
|
then {
|
||||||
// use the macro callsite when the init span (but not the whole local span)
|
// use the macro callsite when the init span (but not the whole local span)
|
||||||
// comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];`
|
// comes from an expansion like `vec![1, 2, 3]` in `let ref _ = vec![1, 2, 3];`
|
||||||
|
@ -173,7 +172,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
|
||||||
} else {
|
} else {
|
||||||
Sugg::hir(cx, init, "..")
|
Sugg::hir(cx, init, "..")
|
||||||
};
|
};
|
||||||
let (mutopt, initref) = if an == BindingAnnotation::RefMut {
|
let (mutopt, initref) = if mutabl == Mutability::Mut {
|
||||||
("mut ", sugg_init.mut_addr())
|
("mut ", sugg_init.mut_addr())
|
||||||
} else {
|
} else {
|
||||||
("", sugg_init.addr())
|
("", sugg_init.addr())
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use rustc_ast::ast::{BindingMode, Mutability, Pat, PatKind};
|
use rustc_ast::ast::{Pat, PatKind};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::EarlyContext;
|
use rustc_lint::EarlyContext;
|
||||||
|
|
||||||
use super::REDUNDANT_PATTERN;
|
use super::REDUNDANT_PATTERN;
|
||||||
|
|
||||||
pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
|
pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
|
||||||
if let PatKind::Ident(left, ident, Some(ref right)) = pat.kind {
|
if let PatKind::Ident(ann, ident, Some(ref right)) = pat.kind {
|
||||||
let left_binding = match left {
|
|
||||||
BindingMode::ByRef(Mutability::Mut) => "ref mut ",
|
|
||||||
BindingMode::ByRef(Mutability::Not) => "ref ",
|
|
||||||
BindingMode::ByValue(..) => "",
|
|
||||||
};
|
|
||||||
|
|
||||||
if let PatKind::Wild = right.kind {
|
if let PatKind::Wild = right.kind {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
|
@ -23,7 +17,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
|
||||||
ident.name, ident.name,
|
ident.name, ident.name,
|
||||||
),
|
),
|
||||||
"try",
|
"try",
|
||||||
format!("{}{}", left_binding, ident.name),
|
format!("{}{}", ann.prefix_str(), ident.name),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind};
|
use rustc_ast::ast::{BindingAnnotation, ByRef, Lifetime, Mutability, Param, PatKind, Path, TyKind};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
@ -120,14 +120,14 @@ impl EarlyLintPass for NeedlessArbitrarySelfType {
|
||||||
|
|
||||||
match &p.ty.kind {
|
match &p.ty.kind {
|
||||||
TyKind::Path(None, path) => {
|
TyKind::Path(None, path) => {
|
||||||
if let PatKind::Ident(BindingMode::ByValue(mutbl), _, _) = p.pat.kind {
|
if let PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), _, _) = p.pat.kind {
|
||||||
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl);
|
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TyKind::Rptr(lifetime, mut_ty) => {
|
TyKind::Rptr(lifetime, mut_ty) => {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let TyKind::Path(None, path) = &mut_ty.ty.kind;
|
if let TyKind::Path(None, path) = &mut_ty.ty.kind;
|
||||||
if let PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, _) = p.pat.kind;
|
if let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind;
|
||||||
then {
|
then {
|
||||||
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
|
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
|
||||||
if let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind;
|
if let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind;
|
||||||
|
|
||||||
// Check sub_pat got a `ref` keyword (excluding `ref mut`).
|
// Check sub_pat got a `ref` keyword (excluding `ref mut`).
|
||||||
if let PatKind::Binding(BindingAnnotation::Ref, .., spanned_name, _) = sub_pat.kind;
|
if let PatKind::Binding(BindingAnnotation::REF, .., spanned_name, _) = sub_pat.kind;
|
||||||
let parent_id = cx.tcx.hir().get_parent_node(pat.hir_id);
|
let parent_id = cx.tcx.hir().get_parent_node(pat.hir_id);
|
||||||
if let Some(parent_node) = cx.tcx.hir().find(parent_id);
|
if let Some(parent_node) = cx.tcx.hir().find(parent_id);
|
||||||
then {
|
then {
|
||||||
|
|
|
@ -373,7 +373,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessLateInit {
|
||||||
if let Local {
|
if let Local {
|
||||||
init: None,
|
init: None,
|
||||||
pat: &Pat {
|
pat: &Pat {
|
||||||
kind: PatKind::Binding(BindingAnnotation::Unannotated, binding_id, _, None),
|
kind: PatKind::Binding(BindingAnnotation::NONE, binding_id, _, None),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
source: LocalSource::Normal,
|
source: LocalSource::Normal,
|
||||||
|
|
|
@ -8,7 +8,9 @@ use rustc_ast::ast::Attribute;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::{Applicability, Diagnostic};
|
use rustc_errors::{Applicability, Diagnostic};
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Node, PatKind, QPath, TyKind};
|
use rustc_hir::{
|
||||||
|
BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind,
|
||||||
|
};
|
||||||
use rustc_hir::{HirIdMap, HirIdSet};
|
use rustc_hir::{HirIdMap, HirIdSet};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
@ -188,13 +190,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||||
if !implements_borrow_trait;
|
if !implements_borrow_trait;
|
||||||
if !all_borrowable_trait;
|
if !all_borrowable_trait;
|
||||||
|
|
||||||
if let PatKind::Binding(mode, canonical_id, ..) = arg.pat.kind;
|
if let PatKind::Binding(BindingAnnotation(_, Mutability::Not), canonical_id, ..) = arg.pat.kind;
|
||||||
if !moved_vars.contains(&canonical_id);
|
if !moved_vars.contains(&canonical_id);
|
||||||
then {
|
then {
|
||||||
if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dereference suggestion
|
// Dereference suggestion
|
||||||
let sugg = |diag: &mut Diagnostic| {
|
let sugg = |diag: &mut Diagnostic| {
|
||||||
if let ty::Adt(def, ..) = ty.kind() {
|
if let ty::Adt(def, ..) = ty.kind() {
|
||||||
|
|
|
@ -130,7 +130,7 @@ fn try_get_option_occurence<'tcx>(
|
||||||
.filter_map(|(id, &c)| none_captures.get(id).map(|&c2| (c, c2)))
|
.filter_map(|(id, &c)| none_captures.get(id).map(|&c2| (c, c2)))
|
||||||
.all(|(x, y)| x.is_imm_ref() && y.is_imm_ref());
|
.all(|(x, y)| x.is_imm_ref() && y.is_imm_ref());
|
||||||
then {
|
then {
|
||||||
let capture_mut = if bind_annotation == BindingAnnotation::Mutable { "mut " } else { "" };
|
let capture_mut = if bind_annotation == BindingAnnotation::MUT { "mut " } else { "" };
|
||||||
let some_body = peel_blocks(if_then);
|
let some_body = peel_blocks(if_then);
|
||||||
let none_body = peel_blocks(if_else);
|
let none_body = peel_blocks(if_else);
|
||||||
let method_sugg = if eager_or_lazy::switch_to_eager_eval(cx, none_body) { "map_or" } else { "map_or_else" };
|
let method_sugg = if eager_or_lazy::switch_to_eager_eval(cx, none_body) { "map_or" } else { "map_or_else" };
|
||||||
|
@ -138,7 +138,7 @@ fn try_get_option_occurence<'tcx>(
|
||||||
let (as_ref, as_mut) = match &expr.kind {
|
let (as_ref, as_mut) = match &expr.kind {
|
||||||
ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
|
ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
|
||||||
ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
|
ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
|
||||||
_ => (bind_annotation == BindingAnnotation::Ref, bind_annotation == BindingAnnotation::RefMut),
|
_ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if captures the closure will need conflict with borrows made in the scrutinee.
|
// Check if captures the closure will need conflict with borrows made in the scrutinee.
|
||||||
|
|
|
@ -221,7 +221,7 @@ impl<'tcx> PassByRefOrValue {
|
||||||
// if function has a body and parameter is annotated with mut, ignore
|
// if function has a body and parameter is annotated with mut, ignore
|
||||||
if let Some(param) = fn_body.and_then(|body| body.params.get(index)) {
|
if let Some(param) = fn_body.and_then(|body| body.params.get(index)) {
|
||||||
match param.pat.kind {
|
match param.pat.kind {
|
||||||
PatKind::Binding(BindingAnnotation::Unannotated, _, _, _) => {},
|
PatKind::Binding(BindingAnnotation::NONE, _, _, _) => {},
|
||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -571,7 +571,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
|
||||||
Some((Node::Stmt(_), _)) => (),
|
Some((Node::Stmt(_), _)) => (),
|
||||||
Some((Node::Local(l), _)) => {
|
Some((Node::Local(l), _)) => {
|
||||||
// Only trace simple bindings. e.g `let x = y;`
|
// Only trace simple bindings. e.g `let x = y;`
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, id, _, None) = l.pat.kind {
|
if let PatKind::Binding(BindingAnnotation::NONE, id, _, None) = l.pat.kind {
|
||||||
self.bindings.insert(id, args_idx);
|
self.bindings.insert(id, args_idx);
|
||||||
} else {
|
} else {
|
||||||
set_skip_flag();
|
set_skip_flag();
|
||||||
|
@ -647,7 +647,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
|
||||||
.filter_map(|(i, arg)| {
|
.filter_map(|(i, arg)| {
|
||||||
let param = &body.params[arg.idx];
|
let param = &body.params[arg.idx];
|
||||||
match param.pat.kind {
|
match param.pat.kind {
|
||||||
PatKind::Binding(BindingAnnotation::Unannotated, id, _, None)
|
PatKind::Binding(BindingAnnotation::NONE, id, _, None)
|
||||||
if !is_lint_allowed(cx, PTR_ARG, param.hir_id) =>
|
if !is_lint_allowed(cx, PTR_ARG, param.hir_id) =>
|
||||||
{
|
{
|
||||||
Some((id, i))
|
Some((id, i))
|
||||||
|
|
|
@ -9,7 +9,7 @@ use clippy_utils::{
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
||||||
use rustc_hir::{BindingAnnotation, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
|
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
@ -123,7 +123,7 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
|
||||||
if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
|
if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
|
||||||
if !is_else_clause(cx.tcx, expr);
|
if !is_else_clause(cx.tcx, expr);
|
||||||
if let PatKind::TupleStruct(ref path1, [field], None) = let_pat.kind;
|
if let PatKind::TupleStruct(ref path1, [field], None) = let_pat.kind;
|
||||||
if let PatKind::Binding(annot, bind_id, ident, None) = field.kind;
|
if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
|
||||||
let caller_ty = cx.typeck_results().expr_ty(let_expr);
|
let caller_ty = cx.typeck_results().expr_ty(let_expr);
|
||||||
let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else);
|
let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else);
|
||||||
if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
|
if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
|
||||||
|
@ -132,12 +132,11 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
|
||||||
then {
|
then {
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
|
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
|
||||||
let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut);
|
|
||||||
let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
|
let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
|
||||||
let sugg = format!(
|
let sugg = format!(
|
||||||
"{}{}?{}",
|
"{}{}?{}",
|
||||||
receiver_str,
|
receiver_str,
|
||||||
if by_ref { ".as_ref()" } else { "" },
|
if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
|
||||||
if requires_semi { ";" } else { "" }
|
if requires_semi { ";" } else { "" }
|
||||||
);
|
);
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
|
|
|
@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit {
|
||||||
// Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)`
|
// Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)`
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let StmtKind::Local(local) = stmt.kind;
|
if let StmtKind::Local(local) = stmt.kind;
|
||||||
if let PatKind::Binding(BindingAnnotation::Mutable, local_id, _, None) = local.pat.kind;
|
if let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind;
|
||||||
if let Some(init) = local.init;
|
if let Some(init) = local.init;
|
||||||
if let Some(len_arg) = Self::is_vec_with_capacity(cx, init);
|
if let Some(len_arg) = Self::is_vec_with_capacity(cx, init);
|
||||||
|
|
||||||
|
|
|
@ -137,12 +137,12 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
|
||||||
struct Visitor;
|
struct Visitor;
|
||||||
impl MutVisitor for Visitor {
|
impl MutVisitor for Visitor {
|
||||||
fn visit_pat(&mut self, pat: &mut P<Pat>) {
|
fn visit_pat(&mut self, pat: &mut P<Pat>) {
|
||||||
use ast::{BindingMode::*, Mutability::*};
|
use ast::BindingAnnotation;
|
||||||
noop_visit_pat(pat, self);
|
noop_visit_pat(pat, self);
|
||||||
let target = match &mut pat.kind {
|
let target = match &mut pat.kind {
|
||||||
// `i @ a | b`, `box a | b`, and `& mut? a | b`.
|
// `i @ a | b`, `box a | b`, and `& mut? a | b`.
|
||||||
Ident(.., Some(p)) | Box(p) | Ref(p, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p,
|
Ident(.., Some(p)) | Box(p) | Ref(p, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p,
|
||||||
Ref(p, Not) if matches!(p.kind, Ident(ByValue(Mut), ..)) => p, // `&(mut x)`
|
Ref(p, Mutability::Not) if matches!(p.kind, Ident(BindingAnnotation::MUT, ..)) => p, // `&(mut x)`
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
target.kind = Paren(P(take_pat(target)));
|
target.kind = Paren(P(take_pat(target)));
|
||||||
|
|
|
@ -6,7 +6,9 @@ use rustc_ast::ast::{LitFloatType, LitKind};
|
||||||
use rustc_ast::LitIntType;
|
use rustc_ast::LitIntType;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{ArrayLen, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind};
|
use rustc_hir::{
|
||||||
|
ArrayLen, BindingAnnotation, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
|
||||||
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::symbol::{Ident, Symbol};
|
use rustc_span::symbol::{Ident, Symbol};
|
||||||
|
@ -610,10 +612,16 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
match pat.value.kind {
|
match pat.value.kind {
|
||||||
PatKind::Wild => kind!("Wild"),
|
PatKind::Wild => kind!("Wild"),
|
||||||
PatKind::Binding(anno, .., name, sub) => {
|
PatKind::Binding(ann, _, name, sub) => {
|
||||||
bind!(self, name);
|
bind!(self, name);
|
||||||
opt_bind!(self, sub);
|
opt_bind!(self, sub);
|
||||||
kind!("Binding(BindingAnnotation::{anno:?}, _, {name}, {sub})");
|
let ann = match ann {
|
||||||
|
BindingAnnotation::NONE => "NONE",
|
||||||
|
BindingAnnotation::REF => "REF",
|
||||||
|
BindingAnnotation::MUT => "MUT",
|
||||||
|
BindingAnnotation::REF_MUT => "REF_MUT",
|
||||||
|
};
|
||||||
|
kind!("Binding(BindingAnnotation::{ann}, _, {name}, {sub})");
|
||||||
self.ident(name);
|
self.ident(name);
|
||||||
sub.if_some(|p| self.pat(p));
|
sub.if_some(|p| self.pat(p));
|
||||||
},
|
},
|
||||||
|
|
|
@ -157,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush {
|
||||||
|
|
||||||
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
|
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
|
||||||
if let Some(init_expr) = local.init
|
if let Some(init_expr) = local.init
|
||||||
&& let PatKind::Binding(BindingAnnotation::Mutable, id, name, None) = local.pat.kind
|
&& let PatKind::Binding(BindingAnnotation::MUT, id, name, None) = local.pat.kind
|
||||||
&& !in_external_macro(cx.sess(), local.span)
|
&& !in_external_macro(cx.sess(), local.span)
|
||||||
&& let Some(init) = get_vec_init_kind(cx, init_expr)
|
&& let Some(init) = get_vec_init_kind(cx, init_expr)
|
||||||
&& !matches!(init, VecInitKind::WithExprCapacity(_))
|
&& !matches!(init, VecInitKind::WithExprCapacity(_))
|
||||||
|
|
|
@ -6,9 +6,9 @@ use rustc_data_structures::fx::FxHasher;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::HirIdMap;
|
use rustc_hir::HirIdMap;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
ArrayLen, BinOpKind, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard,
|
ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
|
||||||
HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath,
|
GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path,
|
||||||
Stmt, StmtKind, Ty, TyKind, TypeBinding,
|
PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
|
||||||
};
|
};
|
||||||
use rustc_lexer::{tokenize, TokenKind};
|
use rustc_lexer::{tokenize, TokenKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
@ -822,8 +822,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
pub fn hash_pat(&mut self, pat: &Pat<'_>) {
|
pub fn hash_pat(&mut self, pat: &Pat<'_>) {
|
||||||
std::mem::discriminant(&pat.kind).hash(&mut self.s);
|
std::mem::discriminant(&pat.kind).hash(&mut self.s);
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
PatKind::Binding(ann, _, _, pat) => {
|
PatKind::Binding(BindingAnnotation(by_ref, mutability), _, _, pat) => {
|
||||||
std::mem::discriminant(&ann).hash(&mut self.s);
|
std::mem::discriminant(&by_ref).hash(&mut self.s);
|
||||||
|
std::mem::discriminant(&mutability).hash(&mut self.s);
|
||||||
if let Some(pat) = pat {
|
if let Some(pat) = pat {
|
||||||
self.hash_pat(pat);
|
self.hash_pat(pat);
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,7 +192,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
|
||||||
let hir = cx.tcx.hir();
|
let hir = cx.tcx.hir();
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Some(Node::Pat(pat)) = hir.find(hir_id);
|
if let Some(Node::Pat(pat)) = hir.find(hir_id);
|
||||||
if matches!(pat.kind, PatKind::Binding(BindingAnnotation::Unannotated, ..));
|
if matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..));
|
||||||
let parent = hir.get_parent_node(hir_id);
|
let parent = hir.get_parent_node(hir_id);
|
||||||
if let Some(Node::Local(local)) = hir.find(parent);
|
if let Some(Node::Local(local)) = hir.find(parent);
|
||||||
then {
|
then {
|
||||||
|
|
|
@ -6,7 +6,7 @@ if_chain! {
|
||||||
if match_qpath(qpath, &["char"]);
|
if match_qpath(qpath, &["char"]);
|
||||||
if let ExprKind::Lit(ref lit) = expr.kind;
|
if let ExprKind::Lit(ref lit) = expr.kind;
|
||||||
if let LitKind::Int(69, LitIntType::Unsuffixed) = lit.node;
|
if let LitKind::Int(69, LitIntType::Unsuffixed) = lit.node;
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind;
|
if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind;
|
||||||
if name.as_str() == "x";
|
if name.as_str() == "x";
|
||||||
then {
|
then {
|
||||||
// report your lint here
|
// report your lint here
|
||||||
|
|
|
@ -5,13 +5,13 @@ if_chain! {
|
||||||
if let Some(init) = local.init;
|
if let Some(init) = local.init;
|
||||||
if let ExprKind::Lit(ref lit) = init.kind;
|
if let ExprKind::Lit(ref lit) = init.kind;
|
||||||
if let LitKind::Int(42, LitIntType::Signed(IntTy::I32)) = lit.node;
|
if let LitKind::Int(42, LitIntType::Signed(IntTy::I32)) = lit.node;
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind;
|
if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind;
|
||||||
if name.as_str() == "x";
|
if name.as_str() == "x";
|
||||||
if let StmtKind::Local(local1) = block.stmts[1].kind;
|
if let StmtKind::Local(local1) = block.stmts[1].kind;
|
||||||
if let Some(init1) = local1.init;
|
if let Some(init1) = local1.init;
|
||||||
if let ExprKind::Lit(ref lit1) = init1.kind;
|
if let ExprKind::Lit(ref lit1) = init1.kind;
|
||||||
if let LitKind::Float(_, LitFloatType::Suffixed(FloatTy::F32)) = lit1.node;
|
if let LitKind::Float(_, LitFloatType::Suffixed(FloatTy::F32)) = lit1.node;
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local1.pat.kind;
|
if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local1.pat.kind;
|
||||||
if name1.as_str() == "_t";
|
if name1.as_str() == "_t";
|
||||||
if let StmtKind::Semi(e) = block.stmts[2].kind;
|
if let StmtKind::Semi(e) = block.stmts[2].kind;
|
||||||
if let ExprKind::Unary(UnOp::Neg, inner) = e.kind;
|
if let ExprKind::Unary(UnOp::Neg, inner) = e.kind;
|
||||||
|
@ -31,7 +31,7 @@ if_chain! {
|
||||||
if let ExprKind::Path(ref qpath) = func.kind;
|
if let ExprKind::Path(ref qpath) = func.kind;
|
||||||
if match_qpath(qpath, &["String", "new"]);
|
if match_qpath(qpath, &["String", "new"]);
|
||||||
if args.is_empty();
|
if args.is_empty();
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local.pat.kind;
|
if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind;
|
||||||
if name.as_str() == "expr";
|
if name.as_str() == "expr";
|
||||||
if let Some(trailing_expr) = block.expr;
|
if let Some(trailing_expr) = block.expr;
|
||||||
if let ExprKind::Call(func1, args1) = trailing_expr.kind;
|
if let ExprKind::Call(func1, args1) = trailing_expr.kind;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr);
|
if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr);
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = pat.kind;
|
if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = pat.kind;
|
||||||
if name.as_str() == "y";
|
if name.as_str() == "y";
|
||||||
if let ExprKind::Struct(qpath, fields, None) = arg.kind;
|
if let ExprKind::Struct(qpath, fields, None) = arg.kind;
|
||||||
if matches!(qpath, QPath::LangItem(LangItem::Range, _));
|
if matches!(qpath, QPath::LangItem(LangItem::Range, _));
|
||||||
|
@ -17,7 +17,7 @@ if_chain! {
|
||||||
if let Some(init) = local.init;
|
if let Some(init) = local.init;
|
||||||
if let ExprKind::Path(ref qpath1) = init.kind;
|
if let ExprKind::Path(ref qpath1) = init.kind;
|
||||||
if match_qpath(qpath1, &["y"]);
|
if match_qpath(qpath1, &["y"]);
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local.pat.kind;
|
if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind;
|
||||||
if name1.as_str() == "z";
|
if name1.as_str() == "z";
|
||||||
if block.expr.is_none();
|
if block.expr.is_none();
|
||||||
then {
|
then {
|
||||||
|
|
|
@ -21,7 +21,7 @@ if_chain! {
|
||||||
if let Some(init1) = local1.init;
|
if let Some(init1) = local1.init;
|
||||||
if let ExprKind::Lit(ref lit4) = init1.kind;
|
if let ExprKind::Lit(ref lit4) = init1.kind;
|
||||||
if let LitKind::Int(3, LitIntType::Unsuffixed) = lit4.node;
|
if let LitKind::Int(3, LitIntType::Unsuffixed) = lit4.node;
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, _, name, None) = local1.pat.kind;
|
if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local1.pat.kind;
|
||||||
if name.as_str() == "x";
|
if name.as_str() == "x";
|
||||||
if let Some(trailing_expr) = block.expr;
|
if let Some(trailing_expr) = block.expr;
|
||||||
if let ExprKind::Path(ref qpath) = trailing_expr.kind;
|
if let ExprKind::Path(ref qpath) = trailing_expr.kind;
|
||||||
|
@ -30,7 +30,7 @@ if_chain! {
|
||||||
if arms[2].guard.is_none();
|
if arms[2].guard.is_none();
|
||||||
if let ExprKind::Lit(ref lit5) = arms[2].body.kind;
|
if let ExprKind::Lit(ref lit5) = arms[2].body.kind;
|
||||||
if let LitKind::Int(1, LitIntType::Unsuffixed) = lit5.node;
|
if let LitKind::Int(1, LitIntType::Unsuffixed) = lit5.node;
|
||||||
if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local.pat.kind;
|
if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind;
|
||||||
if name1.as_str() == "a";
|
if name1.as_str() == "a";
|
||||||
then {
|
then {
|
||||||
// report your lint here
|
// report your lint here
|
||||||
|
|
Loading…
Reference in a new issue