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:
bors 2022-09-06 03:16:29 +00:00
commit ce339b219a
35 changed files with 95 additions and 103 deletions

View file

@ -503,7 +503,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
}
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) {
// This binding id has been seen before. Add this pattern to the list of changes.
if let Some(prev_pat) = opt_prev_pat {

View file

@ -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);
// 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 res_pat.hir_id == local_hir_id;

View file

@ -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 slices: FxIndexMap<hir::HirId, SliceLintInformation> = FxIndexMap::default();
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
if let hir::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut = binding {
return;
}
// We'll just ignore mut and ref mut for simplicity sake right now
if let hir::PatKind::Binding(
hir::BindingAnnotation(by_ref, hir::Mutability::Not),
value_hir_id,
ident,
sub_pat,
) = pat.kind
{
// 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.
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() {
// 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
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 slice_info = slices

View file

@ -4,7 +4,7 @@ use clippy_utils::{path_to_local_id, visitors::is_local_used};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::BindingAnnotation;
use rustc_hir::{BindingAnnotation, Mutability};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
};
let mutability = match mode {
BindingAnnotation::RefMut | BindingAnnotation::Mutable => "<mut> ",
BindingAnnotation(_, Mutability::Mut) => "<mut> ",
_ => "",
};

View file

@ -106,7 +106,7 @@ fn get_binding(pat: &Pat<'_>) -> Option<HirId> {
hir_id = None;
return;
}
if let BindingAnnotation::Unannotated = annotation {
if let BindingAnnotation::NONE = annotation {
hir_id = Some(id);
}
});

View file

@ -44,7 +44,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId>
if_chain! {
if let Some(hir_id) = path_to_local(bound);
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 {
return Some(hir_id);
}

View file

@ -7,7 +7,7 @@ use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res};
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_span::symbol::sym;
use std::iter::Iterator;
@ -65,7 +65,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let Node::Pat(pat) = node;
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);
if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
if let Some(init) = parent_let_expr.init;

View file

@ -165,7 +165,7 @@ fn check<'tcx>(
}
// `ref` and `ref mut` annotations were handled earlier.
let annotation = if matches!(annotation, BindingAnnotation::Mutable) {
let annotation = if matches!(annotation, BindingAnnotation::MUT) {
"mut "
} else {
""

View file

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_lang_ctor, peel_blocks};
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_middle::ty;
@ -10,18 +10,17 @@ use super::MATCH_AS_REF;
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() {
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])
} else if is_none_arm(cx, &arms[1]) {
is_ref_some_arm(cx, &arms[0])
} else {
None
};
if let Some(rb) = arm_ref {
let suggestion = if rb == BindingAnnotation::Ref {
"as_ref"
} else {
"as_mut"
if let Some(rb) = arm_ref_mut {
let suggestion = match rb {
Mutability::Not => "as_ref",
Mutability::Mut => "as_mut",
};
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`)
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 let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind;
if is_lang_ctor(cx, qpath, LangItem::OptionSome);
if let PatKind::Binding(rb, .., ident, _) = first_pat.kind;
if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut;
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind;
if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind;
if let ExprKind::Path(ref some_path) = e.kind;
if is_lang_ctor(cx, some_path, LangItem::OptionSome);
if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind;
if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
then {
return Some(rb)
return Some(mutabl)
}
}
None

View file

@ -8,7 +8,7 @@ use clippy_utils::{
};
use rustc_errors::Applicability;
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_span::sym;
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)
&& pat_ident.name == first_seg.ident.name;
return !matches!(annot, BindingAnnotation(ByRef::Yes, _)) && pat_ident.name == first_seg.ident.name;
},
// Example: `Custom::TypeA => Custom::TypeB`, or `None => None`
(PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => {

View file

@ -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);
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);
},
_ => {},

View file

@ -4,7 +4,7 @@ use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg;
use clippy_utils::ty::is_copy;
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_middle::ty::{self, adjustment::Adjust};
use rustc_span::symbol::{sym, Symbol};
@ -101,12 +101,7 @@ pub(super) fn check(
_ => false,
},
// local binding capturing a reference
Some(Node::Local(l))
if matches!(
l.pat.kind,
PatKind::Binding(BindingAnnotation::Ref | BindingAnnotation::RefMut, ..)
) =>
{
Some(Node::Local(l)) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => {
return;
},
_ => false,

View file

@ -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 Node::Pat(pat) = cx.tcx.hir().get(id);
if let PatKind::Binding(ann, _, _, _) = pat.kind;
if ann != BindingAnnotation::Mutable;
if ann != BindingAnnotation::MUT;
then {
application = Applicability::Unspecified;
diag.span_help(

View file

@ -33,13 +33,13 @@ pub(super) fn check<'tcx>(
let closure_expr = peel_blocks(&closure_body.value);
match closure_body.params[0].pat.kind {
hir::PatKind::Ref(inner, hir::Mutability::Not) => if let hir::PatKind::Binding(
hir::BindingAnnotation::Unannotated, .., name, None
hir::BindingAnnotation::NONE, .., name, None
) = inner.kind {
if ident_eq(name, closure_expr) {
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 {
hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
if ident_eq(name, inner) {

View file

@ -130,7 +130,7 @@ fn check_manual_split_once_indirect(
let ctxt = expr.span.ctxt();
let mut parents = cx.tcx.hir().parent_iter(expr.hir_id);
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 (_, Node::Block(enclosing_block)) = parents.next()?
@ -212,11 +212,10 @@ fn indirect_usage<'tcx>(
ctxt: SyntaxContext,
) -> Option<IndirectUsage<'tcx>> {
if let StmtKind::Local(Local {
pat:
Pat {
kind: PatKind::Binding(BindingAnnotation::Unannotated, _, ident, None),
..
},
pat: Pat {
kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None),
..
},
init: Some(init_expr),
hir_id: local_hir_id,
..

View file

@ -5,8 +5,8 @@ use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
self as hir, def, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind, Stmt,
StmtKind, TyKind,
self as hir, def, BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind,
Stmt, StmtKind, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
@ -146,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
return;
}
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(
cx,
TOPLEVEL_REF_ARG,
@ -162,9 +162,8 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
if_chain! {
if !in_external_macro(cx.tcx.sess, stmt.span);
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 an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut;
then {
// 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];`
@ -173,7 +172,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
} else {
Sugg::hir(cx, init, "..")
};
let (mutopt, initref) = if an == BindingAnnotation::RefMut {
let (mutopt, initref) = if mutabl == Mutability::Mut {
("mut ", sugg_init.mut_addr())
} else {
("", sugg_init.addr())

View file

@ -1,18 +1,12 @@
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_lint::EarlyContext;
use super::REDUNDANT_PATTERN;
pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
if let PatKind::Ident(left, 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::Ident(ann, ident, Some(ref right)) = pat.kind {
if let PatKind::Wild = right.kind {
span_lint_and_sugg(
cx,
@ -23,7 +17,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
ident.name, ident.name,
),
"try",
format!("{}{}", left_binding, ident.name),
format!("{}{}", ann.prefix_str(), ident.name),
Applicability::MachineApplicable,
);
}

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
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_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -120,14 +120,14 @@ impl EarlyLintPass for NeedlessArbitrarySelfType {
match &p.ty.kind {
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);
}
},
TyKind::Rptr(lifetime, mut_ty) => {
if_chain! {
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 {
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
}

View file

@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
if let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind;
// 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);
if let Some(parent_node) = cx.tcx.hir().find(parent_id);
then {

View file

@ -373,7 +373,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessLateInit {
if let Local {
init: None,
pat: &Pat {
kind: PatKind::Binding(BindingAnnotation::Unannotated, binding_id, _, None),
kind: PatKind::Binding(BindingAnnotation::NONE, binding_id, _, None),
..
},
source: LocalSource::Normal,

View file

@ -8,7 +8,9 @@ use rustc_ast::ast::Attribute;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic};
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_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
@ -188,13 +190,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
if !implements_borrow_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);
then {
if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut {
continue;
}
// Dereference suggestion
let sugg = |diag: &mut Diagnostic| {
if let ty::Adt(def, ..) = ty.kind() {

View file

@ -130,7 +130,7 @@ fn try_get_option_occurence<'tcx>(
.filter_map(|(id, &c)| none_captures.get(id).map(|&c2| (c, c2)))
.all(|(x, y)| x.is_imm_ref() && y.is_imm_ref());
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 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" };
@ -138,7 +138,7 @@ fn try_get_option_occurence<'tcx>(
let (as_ref, as_mut) = match &expr.kind {
ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
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.

View file

@ -221,7 +221,7 @@ impl<'tcx> PassByRefOrValue {
// 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)) {
match param.pat.kind {
PatKind::Binding(BindingAnnotation::Unannotated, _, _, _) => {},
PatKind::Binding(BindingAnnotation::NONE, _, _, _) => {},
_ => continue,
}
}

View file

@ -571,7 +571,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
Some((Node::Stmt(_), _)) => (),
Some((Node::Local(l), _)) => {
// 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);
} else {
set_skip_flag();
@ -647,7 +647,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
.filter_map(|(i, arg)| {
let param = &body.params[arg.idx];
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) =>
{
Some((id, i))

View file

@ -9,7 +9,7 @@ use clippy_utils::{
use if_chain::if_chain;
use rustc_errors::Applicability;
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_middle::ty::Ty;
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 !is_else_clause(cx.tcx, expr);
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 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))
@ -132,12 +132,11 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
then {
let mut applicability = Applicability::MachineApplicable;
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 sugg = format!(
"{}{}?{}",
receiver_str,
if by_ref { ".as_ref()" } else { "" },
if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
if requires_semi { ";" } else { "" }
);
span_lint_and_sugg(

View file

@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit {
// Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)`
if_chain! {
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(len_arg) = Self::is_vec_with_capacity(cx, init);

View file

@ -137,12 +137,12 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
struct Visitor;
impl MutVisitor for Visitor {
fn visit_pat(&mut self, pat: &mut P<Pat>) {
use ast::{BindingMode::*, Mutability::*};
use ast::BindingAnnotation;
noop_visit_pat(pat, self);
let target = match &mut pat.kind {
// `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,
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,
};
target.kind = Paren(P(take_pat(target)));

View file

@ -6,7 +6,9 @@ use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_ast::LitIntType;
use rustc_data_structures::fx::FxHashMap;
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_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::{Ident, Symbol};
@ -610,10 +612,16 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
match pat.value.kind {
PatKind::Wild => kind!("Wild"),
PatKind::Binding(anno, .., name, sub) => {
PatKind::Binding(ann, _, name, sub) => {
bind!(self, name);
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);
sub.if_some(|p| self.pat(p));
},

View file

@ -157,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush {
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
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)
&& let Some(init) = get_vec_init_kind(cx, init_expr)
&& !matches!(init, VecInitKind::WithExprCapacity(_))

View file

@ -6,9 +6,9 @@ use rustc_data_structures::fx::FxHasher;
use rustc_hir::def::Res;
use rustc_hir::HirIdMap;
use rustc_hir::{
ArrayLen, BinOpKind, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard,
HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath,
Stmt, StmtKind, Ty, TyKind, TypeBinding,
ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path,
PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
};
use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::LateContext;
@ -822,8 +822,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
pub fn hash_pat(&mut self, pat: &Pat<'_>) {
std::mem::discriminant(&pat.kind).hash(&mut self.s);
match pat.kind {
PatKind::Binding(ann, _, _, pat) => {
std::mem::discriminant(&ann).hash(&mut self.s);
PatKind::Binding(BindingAnnotation(by_ref, mutability), _, _, pat) => {
std::mem::discriminant(&by_ref).hash(&mut self.s);
std::mem::discriminant(&mutability).hash(&mut self.s);
if let Some(pat) = pat {
self.hash_pat(pat);
}

View file

@ -192,7 +192,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
let hir = cx.tcx.hir();
if_chain! {
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);
if let Some(Node::Local(local)) = hir.find(parent);
then {

View file

@ -6,7 +6,7 @@ if_chain! {
if match_qpath(qpath, &["char"]);
if let ExprKind::Lit(ref lit) = expr.kind;
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";
then {
// report your lint here

View file

@ -5,13 +5,13 @@ if_chain! {
if let Some(init) = local.init;
if let ExprKind::Lit(ref lit) = init.kind;
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 let StmtKind::Local(local1) = block.stmts[1].kind;
if let Some(init1) = local1.init;
if let ExprKind::Lit(ref lit1) = init1.kind;
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 let StmtKind::Semi(e) = block.stmts[2].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 match_qpath(qpath, &["String", "new"]);
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 let Some(trailing_expr) = block.expr;
if let ExprKind::Call(func1, args1) = trailing_expr.kind;

View file

@ -1,6 +1,6 @@
if_chain! {
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 let ExprKind::Struct(qpath, fields, None) = arg.kind;
if matches!(qpath, QPath::LangItem(LangItem::Range, _));
@ -17,7 +17,7 @@ if_chain! {
if let Some(init) = local.init;
if let ExprKind::Path(ref qpath1) = init.kind;
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 block.expr.is_none();
then {

View file

@ -21,7 +21,7 @@ if_chain! {
if let Some(init1) = local1.init;
if let ExprKind::Lit(ref lit4) = init1.kind;
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 let Some(trailing_expr) = block.expr;
if let ExprKind::Path(ref qpath) = trailing_expr.kind;
@ -30,7 +30,7 @@ if_chain! {
if arms[2].guard.is_none();
if let ExprKind::Lit(ref lit5) = arms[2].body.kind;
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";
then {
// report your lint here