1
Fork 0

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 6c358c67d4
61 changed files with 278 additions and 333 deletions

View file

@ -594,7 +594,7 @@ impl Pat {
// In a type expression `_` is an inference variable. // In a type expression `_` is an inference variable.
PatKind::Wild => TyKind::Infer, PatKind::Wild => TyKind::Infer,
// An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`. // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => { PatKind::Ident(BindingAnnotation::NONE, ident, None) => {
TyKind::Path(None, Path::from_ident(*ident)) TyKind::Path(None, Path::from_ident(*ident))
} }
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
@ -681,10 +681,43 @@ pub struct PatField {
pub is_placeholder: bool, pub is_placeholder: bool,
} }
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum BindingMode { #[derive(Encodable, Decodable, HashStable_Generic)]
ByRef(Mutability), pub enum ByRef {
ByValue(Mutability), Yes,
No,
}
impl From<bool> for ByRef {
fn from(b: bool) -> ByRef {
match b {
false => ByRef::No,
true => ByRef::Yes,
}
}
}
/// Explicit binding annotations given in the HIR for a binding. Note
/// that this is not the final binding *mode* that we infer after type
/// inference.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub struct BindingAnnotation(pub ByRef, pub Mutability);
impl BindingAnnotation {
pub const NONE: Self = Self(ByRef::No, Mutability::Not);
pub const REF: Self = Self(ByRef::Yes, Mutability::Not);
pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
pub const REF_MUT: Self = Self(ByRef::Yes, Mutability::Mut);
pub fn prefix_str(self) -> &'static str {
match self {
Self::NONE => "",
Self::REF => "ref ",
Self::MUT => "mut ",
Self::REF_MUT => "ref mut ",
}
}
} }
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
@ -713,7 +746,7 @@ pub enum PatKind {
/// or a unit struct/variant pattern, or a const pattern (in the last two cases the third /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
/// field must be `None`). Disambiguation cannot be done with parser alone, so it happens /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
/// during name resolution. /// during name resolution.
Ident(BindingMode, Ident, Option<P<Pat>>), Ident(BindingAnnotation, Ident, Option<P<Pat>>),
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
/// The `bool` is `true` in the presence of a `..`. /// The `bool` is `true` in the presence of a `..`.
@ -2228,7 +2261,7 @@ pub type ExplicitSelf = Spanned<SelfKind>;
impl Param { impl Param {
/// Attempts to cast parameter to `ExplicitSelf`. /// Attempts to cast parameter to `ExplicitSelf`.
pub fn to_self(&self) -> Option<ExplicitSelf> { pub fn to_self(&self) -> Option<ExplicitSelf> {
if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.kind { if let PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), ident, _) = self.pat.kind {
if ident.name == kw::SelfLower { if ident.name == kw::SelfLower {
return match self.ty.kind { return match self.ty.kind {
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
@ -2258,23 +2291,10 @@ impl Param {
pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param { pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param {
let span = eself.span.to(eself_ident.span); let span = eself.span.to(eself_ident.span);
let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span, tokens: None }); let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span, tokens: None });
let param = |mutbl, ty| Param { let (mutbl, ty) = match eself.node {
attrs, SelfKind::Explicit(ty, mutbl) => (mutbl, ty),
pat: P(Pat { SelfKind::Value(mutbl) => (mutbl, infer_ty),
id: DUMMY_NODE_ID, SelfKind::Region(lt, mutbl) => (
kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
span,
tokens: None,
}),
span,
ty,
id: DUMMY_NODE_ID,
is_placeholder: false,
};
match eself.node {
SelfKind::Explicit(ty, mutbl) => param(mutbl, ty),
SelfKind::Value(mutbl) => param(mutbl, infer_ty),
SelfKind::Region(lt, mutbl) => param(
Mutability::Not, Mutability::Not,
P(Ty { P(Ty {
id: DUMMY_NODE_ID, id: DUMMY_NODE_ID,
@ -2283,6 +2303,19 @@ impl Param {
tokens: None, tokens: None,
}), }),
), ),
};
Param {
attrs,
pat: P(Pat {
id: DUMMY_NODE_ID,
kind: PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), eself_ident, None),
span,
tokens: None,
}),
span,
ty,
id: DUMMY_NODE_ID,
is_placeholder: false,
} }
} }
} }

View file

@ -577,7 +577,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (pat, task_context_hid) = self.pat_ident_binding_mode( let (pat, task_context_hid) = self.pat_ident_binding_mode(
span, span,
Ident::with_dummy_span(sym::_task_context), Ident::with_dummy_span(sym::_task_context),
hir::BindingAnnotation::Mutable, hir::BindingAnnotation::MUT,
); );
let param = hir::Param { let param = hir::Param {
hir_id: self.next_id(), hir_id: self.next_id(),
@ -671,7 +671,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// this name to identify what is being awaited by a suspended async functions. // this name to identify what is being awaited by a suspended async functions.
let awaitee_ident = Ident::with_dummy_span(sym::__awaitee); let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
let (awaitee_pat, awaitee_pat_hid) = let (awaitee_pat, awaitee_pat_hid) =
self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::Mutable); self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT);
let task_context_ident = Ident::with_dummy_span(sym::_task_context); let task_context_ident = Ident::with_dummy_span(sym::_task_context);
@ -1433,7 +1433,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `mut iter` // `mut iter`
let iter = Ident::with_dummy_span(sym::iter); let iter = Ident::with_dummy_span(sym::iter);
let (iter_pat, iter_pat_nid) = let (iter_pat, iter_pat_nid) =
self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::Mutable); self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT);
// `match Iterator::next(&mut iter) { ... }` // `match Iterator::next(&mut iter) { ... }`
let match_expr = { let match_expr = {

View file

@ -1083,12 +1083,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Check if this is a binding pattern, if so, we can optimize and avoid adding a // Check if this is a binding pattern, if so, we can optimize and avoid adding a
// `let <pat> = __argN;` statement. In this case, we do not rename the parameter. // `let <pat> = __argN;` statement. In this case, we do not rename the parameter.
let (ident, is_simple_parameter) = match parameter.pat.kind { let (ident, is_simple_parameter) = match parameter.pat.kind {
hir::PatKind::Binding( hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => {
hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable, (ident, true)
_, }
ident,
_,
) => (ident, true),
// For `ref mut` or wildcard arguments, we can't reuse the binding, but // For `ref mut` or wildcard arguments, we can't reuse the binding, but
// we can keep the same name for the parameter. // we can keep the same name for the parameter.
// This lets rustdoc render it correctly in documentation. // This lets rustdoc render it correctly in documentation.
@ -1153,7 +1150,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (move_pat, move_id) = this.pat_ident_binding_mode( let (move_pat, move_id) = this.pat_ident_binding_mode(
desugared_span, desugared_span,
ident, ident,
hir::BindingAnnotation::Mutable, hir::BindingAnnotation::MUT,
); );
let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id); let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id);
let move_stmt = this.stmt_let_pat( let move_stmt = this.stmt_let_pat(

View file

@ -1692,10 +1692,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
output, output,
c_variadic, c_variadic,
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| { implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
use BindingMode::{ByRef, ByValue};
let is_mutable_pat = matches!( let is_mutable_pat = matches!(
arg.pat.kind, arg.pat.kind,
PatKind::Ident(ByValue(Mutability::Mut) | ByRef(Mutability::Mut), ..) PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..)
); );
match arg.ty.kind { match arg.ty.kind {
@ -2360,11 +2359,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) { fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated) self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::NONE)
} }
fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) { fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) {
self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::Unannotated) self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::NONE)
} }
fn pat_ident_binding_mode( fn pat_ident_binding_mode(

View file

@ -24,7 +24,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let node = loop { let node = loop {
match pattern.kind { match pattern.kind {
PatKind::Wild => break hir::PatKind::Wild, PatKind::Wild => break hir::PatKind::Wild,
PatKind::Ident(ref binding_mode, ident, ref sub) => { PatKind::Ident(binding_mode, ident, ref sub) => {
let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s)); let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s));
break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub); break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub);
} }
@ -176,9 +176,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let mut prev_rest_span = None; let mut prev_rest_span = None;
// Lowers `$bm $ident @ ..` to `$bm $ident @ _`. // Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| { let lower_rest_sub = |this: &mut Self, pat, ann, ident, sub| {
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
let node = this.lower_pat_ident(pat, bm, ident, lower_sub); let node = this.lower_pat_ident(pat, ann, ident, lower_sub);
this.pat_with_node_id_of(pat, node) this.pat_with_node_id_of(pat, node)
}; };
@ -194,9 +194,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
// Found a sub-slice pattern `$binding_mode $ident @ ..`. // Found a sub-slice pattern `$binding_mode $ident @ ..`.
// Record, lower it to `$binding_mode $ident @ _`, and stop here. // Record, lower it to `$binding_mode $ident @ _`, and stop here.
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => {
prev_rest_span = Some(sub.span); prev_rest_span = Some(sub.span);
slice = Some(self.arena.alloc(lower_rest_sub(self, pat, bm, ident, sub))); slice = Some(self.arena.alloc(lower_rest_sub(self, pat, ann, ident, sub)));
break; break;
} }
// It was not a subslice pattern so lower it normally. // It was not a subslice pattern so lower it normally.
@ -209,9 +209,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// There was a previous subslice pattern; make sure we don't allow more. // There was a previous subslice pattern; make sure we don't allow more.
let rest_span = match pat.kind { let rest_span = match pat.kind {
PatKind::Rest => Some(pat.span), PatKind::Rest => Some(pat.span),
PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => {
// #69103: Lower into `binding @ _` as above to avoid ICEs. // #69103: Lower into `binding @ _` as above to avoid ICEs.
after.push(lower_rest_sub(self, pat, bm, ident, sub)); after.push(lower_rest_sub(self, pat, ann, ident, sub));
Some(sub.span) Some(sub.span)
} }
_ => None, _ => None,
@ -235,7 +235,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_pat_ident( fn lower_pat_ident(
&mut self, &mut self,
p: &Pat, p: &Pat,
binding_mode: &BindingMode, annotation: BindingAnnotation,
ident: Ident, ident: Ident,
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>, lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
) -> hir::PatKind<'hir> { ) -> hir::PatKind<'hir> {
@ -248,7 +248,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}; };
hir::PatKind::Binding( hir::PatKind::Binding(
self.lower_binding_mode(binding_mode), annotation,
self.lower_node_id(canonical_id), self.lower_node_id(canonical_id),
self.lower_ident(ident), self.lower_ident(ident),
lower_sub(self), lower_sub(self),
@ -269,15 +269,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation {
match *b {
BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated,
BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref,
BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable,
BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut,
}
}
fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> { fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> {
self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild)) self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild))
} }

View file

@ -281,8 +281,8 @@ impl<'a> AstValidator<'a> {
fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) { fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
for Param { pat, .. } in &decl.inputs { for Param { pat, .. } in &decl.inputs {
match pat.kind { match pat.kind {
PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {} PatKind::Ident(BindingAnnotation::NONE, _, None) | PatKind::Wild => {}
PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ident, None) => { PatKind::Ident(BindingAnnotation::MUT, ident, None) => {
report_err(pat.span, Some(ident), true) report_err(pat.span, Some(ident), true)
} }
_ => report_err(pat.span, None, false), _ => report_err(pat.span, None, false),

View file

@ -11,8 +11,8 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::util::classify; use rustc_ast::util::classify;
use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle}; use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
use rustc_ast::util::parser; use rustc_ast::util::parser;
use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; use rustc_ast::{self as ast, BlockCheckMode, Mutability, PatKind, RangeEnd, RangeSyntax};
use rustc_ast::{attr, Term}; use rustc_ast::{attr, BindingAnnotation, ByRef, Term};
use rustc_ast::{GenericArg, MacArgs, MacArgsEq}; use rustc_ast::{GenericArg, MacArgs, MacArgsEq};
use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier}; use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier};
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass}; use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
@ -1399,17 +1399,13 @@ impl<'a> State<'a> {
is that it doesn't matter */ is that it doesn't matter */
match pat.kind { match pat.kind {
PatKind::Wild => self.word("_"), PatKind::Wild => self.word("_"),
PatKind::Ident(binding_mode, ident, ref sub) => { PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, ref sub) => {
match binding_mode { if by_ref == ByRef::Yes {
ast::BindingMode::ByRef(mutbl) => {
self.word_nbsp("ref"); self.word_nbsp("ref");
self.print_mutability(mutbl, false);
} }
ast::BindingMode::ByValue(ast::Mutability::Not) => {} if mutbl == Mutability::Mut {
ast::BindingMode::ByValue(ast::Mutability::Mut) => {
self.word_nbsp("mut"); self.word_nbsp("mut");
} }
}
self.print_ident(ident); self.print_ident(ident);
if let Some(ref p) = *sub { if let Some(ref p) = *sub {
self.space(); self.space();
@ -1487,12 +1483,10 @@ impl<'a> State<'a> {
} }
PatKind::Ref(ref inner, mutbl) => { PatKind::Ref(ref inner, mutbl) => {
self.word("&"); self.word("&");
if mutbl == ast::Mutability::Mut { if mutbl == Mutability::Mut {
self.word("mut "); self.word("mut ");
} }
if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) = if let PatKind::Ident(ast::BindingAnnotation::MUT, ..) = inner.kind {
inner.kind
{
self.popen(); self.popen();
self.print_pat(inner); self.print_pat(inner);
self.pclose(); self.pclose();

View file

@ -367,7 +367,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some(Node::Pat(pat)) = self.infcx.tcx.hir().find(upvar_hir_id) if let Some(Node::Pat(pat)) = self.infcx.tcx.hir().find(upvar_hir_id)
&& let hir::PatKind::Binding( && let hir::PatKind::Binding(
hir::BindingAnnotation::Unannotated, hir::BindingAnnotation::NONE,
_, _,
upvar_ident, upvar_ident,
_, _,

View file

@ -164,7 +164,9 @@ pub use SubstructureFields::*;
use crate::deriving; use crate::deriving;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::{self as ast, EnumDef, Expr, Generics, PatKind}; use rustc_ast::{
self as ast, BindingAnnotation, ByRef, EnumDef, Expr, Generics, Mutability, PatKind,
};
use rustc_ast::{GenericArg, GenericParamKind, VariantData}; use rustc_ast::{GenericArg, GenericParamKind, VariantData};
use rustc_attr as attr; use rustc_attr as attr;
use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::base::{Annotatable, ExtCtxt};
@ -1063,9 +1065,9 @@ impl<'a> MethodDef<'a> {
let mut body = mk_body(cx, selflike_fields); let mut body = mk_body(cx, selflike_fields);
let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]); let struct_path = cx.path(span, vec![Ident::new(kw::SelfUpper, type_ident.span)]);
let use_ref_pat = is_packed && !always_copy; let by_ref = ByRef::from(is_packed && !always_copy);
let patterns = let patterns =
trait_.create_struct_patterns(cx, struct_path, struct_def, &prefixes, use_ref_pat); trait_.create_struct_patterns(cx, struct_path, struct_def, &prefixes, by_ref);
// Do the let-destructuring. // Do the let-destructuring.
let mut stmts: Vec<_> = iter::zip(selflike_args, patterns) let mut stmts: Vec<_> = iter::zip(selflike_args, patterns)
@ -1247,13 +1249,13 @@ impl<'a> MethodDef<'a> {
let sp = variant.span.with_ctxt(trait_.span.ctxt()); let sp = variant.span.with_ctxt(trait_.span.ctxt());
let variant_path = cx.path(sp, vec![type_ident, variant.ident]); let variant_path = cx.path(sp, vec![type_ident, variant.ident]);
let use_ref_pat = false; // because enums can't be repr(packed) let by_ref = ByRef::No; // because enums can't be repr(packed)
let mut subpats: Vec<_> = trait_.create_struct_patterns( let mut subpats: Vec<_> = trait_.create_struct_patterns(
cx, cx,
variant_path, variant_path,
&variant.data, &variant.data,
&prefixes, &prefixes,
use_ref_pat, by_ref,
); );
// `(VariantK, VariantK, ...)` or just `VariantK`. // `(VariantK, VariantK, ...)` or just `VariantK`.
@ -1414,7 +1416,7 @@ impl<'a> TraitDef<'a> {
struct_path: ast::Path, struct_path: ast::Path,
struct_def: &'a VariantData, struct_def: &'a VariantData,
prefixes: &[String], prefixes: &[String],
use_ref_pat: bool, by_ref: ByRef,
) -> Vec<P<ast::Pat>> { ) -> Vec<P<ast::Pat>> {
prefixes prefixes
.iter() .iter()
@ -1422,17 +1424,19 @@ impl<'a> TraitDef<'a> {
let pieces_iter = let pieces_iter =
struct_def.fields().iter().enumerate().map(|(i, struct_field)| { struct_def.fields().iter().enumerate().map(|(i, struct_field)| {
let sp = struct_field.span.with_ctxt(self.span.ctxt()); let sp = struct_field.span.with_ctxt(self.span.ctxt());
let binding_mode = if use_ref_pat {
ast::BindingMode::ByRef(ast::Mutability::Not)
} else {
ast::BindingMode::ByValue(ast::Mutability::Not)
};
let ident = self.mk_pattern_ident(prefix, i); let ident = self.mk_pattern_ident(prefix, i);
let path = ident.with_span_pos(sp); let path = ident.with_span_pos(sp);
( (
sp, sp,
struct_field.ident, struct_field.ident,
cx.pat(path.span, PatKind::Ident(binding_mode, path, None)), cx.pat(
path.span,
PatKind::Ident(
BindingAnnotation(by_ref, Mutability::Not),
path,
None,
),
),
) )
}); });

View file

@ -178,8 +178,7 @@ impl<'a> ExtCtxt<'a> {
ex: P<ast::Expr>, ex: P<ast::Expr>,
) -> ast::Stmt { ) -> ast::Stmt {
let pat = if mutbl { let pat = if mutbl {
let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mut); self.pat_ident_binding_mode(sp, ident, ast::BindingAnnotation::MUT)
self.pat_ident_binding_mode(sp, ident, binding_mode)
} else { } else {
self.pat_ident(sp, ident) self.pat_ident(sp, ident)
}; };
@ -445,17 +444,16 @@ impl<'a> ExtCtxt<'a> {
self.pat(span, PatKind::Lit(expr)) self.pat(span, PatKind::Lit(expr))
} }
pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> { pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> {
let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Not); self.pat_ident_binding_mode(span, ident, ast::BindingAnnotation::NONE)
self.pat_ident_binding_mode(span, ident, binding_mode)
} }
pub fn pat_ident_binding_mode( pub fn pat_ident_binding_mode(
&self, &self,
span: Span, span: Span,
ident: Ident, ident: Ident,
bm: ast::BindingMode, ann: ast::BindingAnnotation,
) -> P<ast::Pat> { ) -> P<ast::Pat> {
let pat = PatKind::Ident(bm, ident.with_span_pos(span), None); let pat = PatKind::Ident(ann, ident.with_span_pos(span), None);
self.pat(span, pat) self.pat(span, pat)
} }
pub fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> { pub fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {

View file

@ -7,7 +7,7 @@ use crate::LangItem;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy}; use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy};
pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto}; pub use rustc_ast::{BindingAnnotation, BorrowKind, ByRef, ImplPolarity, IsAuto};
pub use rustc_ast::{CaptureBy, Movability, Mutability}; pub use rustc_ast::{CaptureBy, Movability, Mutability};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
@ -1044,30 +1044,6 @@ pub struct PatField<'hir> {
pub span: Span, pub span: Span,
} }
/// Explicit binding annotations given in the HIR for a binding. Note
/// that this is not the final binding *mode* that we infer after type
/// inference.
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum BindingAnnotation {
/// No binding annotation given: this means that the final binding mode
/// will depend on whether we have skipped through a `&` reference
/// when matching. For example, the `x` in `Some(x)` will have binding
/// mode `None`; if you do `let Some(x) = &Some(22)`, it will
/// ultimately be inferred to be by-reference.
///
/// Note that implicit reference skipping is not implemented yet (#42640).
Unannotated,
/// Annotated with `mut x` -- could be either ref or not, similar to `None`.
Mutable,
/// Annotated as `ref`, like `ref x`
Ref,
/// Annotated as `ref mut x`.
RefMut,
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum RangeEnd { pub enum RangeEnd {
Included, Included,

View file

@ -1,6 +1,6 @@
use crate::def::{CtorOf, DefKind, Res}; use crate::def::{CtorOf, DefKind, Res};
use crate::def_id::DefId; use crate::def_id::DefId;
use crate::hir::{self, HirId, PatKind}; use crate::hir::{self, BindingAnnotation, ByRef, HirId, PatKind};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_span::hygiene::DesugaringKind; use rustc_span::hygiene::DesugaringKind;
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
@ -93,12 +93,7 @@ impl hir::Pat<'_> {
pub fn simple_ident(&self) -> Option<Ident> { pub fn simple_ident(&self) -> Option<Ident> {
match self.kind { match self.kind {
PatKind::Binding( PatKind::Binding(BindingAnnotation(ByRef::No, _), _, ident, None) => Some(ident),
hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
_,
ident,
None,
) => Some(ident),
_ => None, _ => None,
} }
} }
@ -135,11 +130,11 @@ impl hir::Pat<'_> {
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> { pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
let mut result = None; let mut result = None;
self.each_binding(|annotation, _, _, _| match annotation { self.each_binding(|annotation, _, _, _| match annotation {
hir::BindingAnnotation::Ref => match result { hir::BindingAnnotation::REF => match result {
None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not), None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
_ => {} _ => {}
}, },
hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mut), hir::BindingAnnotation::REF_MUT => result = Some(hir::Mutability::Mut),
_ => {} _ => {}
}); });
result result

View file

@ -9,7 +9,9 @@ use rustc_ast_pretty::pp::{self, Breaks};
use rustc_ast_pretty::pprust::{Comments, PrintState}; use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::LifetimeParamKind; use rustc_hir::LifetimeParamKind;
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term}; use rustc_hir::{
BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Mutability, Node, Term,
};
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}; use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol}; use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
@ -1743,21 +1745,13 @@ impl<'a> State<'a> {
// is that it doesn't matter // is that it doesn't matter
match pat.kind { match pat.kind {
PatKind::Wild => self.word("_"), PatKind::Wild => self.word("_"),
PatKind::Binding(binding_mode, _, ident, sub) => { PatKind::Binding(BindingAnnotation(by_ref, mutbl), _, ident, sub) => {
match binding_mode { if by_ref == ByRef::Yes {
hir::BindingAnnotation::Ref => {
self.word_nbsp("ref"); self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Not, false);
} }
hir::BindingAnnotation::RefMut => { if mutbl == Mutability::Mut {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Mut, false);
}
hir::BindingAnnotation::Unannotated => {}
hir::BindingAnnotation::Mutable => {
self.word_nbsp("mut"); self.word_nbsp("mut");
} }
}
self.print_ident(ident); self.print_ident(ident);
if let Some(p) = sub { if let Some(p) = sub {
self.word("@"); self.word("@");

View file

@ -259,17 +259,8 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
== Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results())) == Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
{ {
cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| { cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| {
let binding = match binding_annot { let suggested_ident =
hir::BindingAnnotation::Unannotated => None, format!("{}{}", binding_annot.prefix_str(), ident);
hir::BindingAnnotation::Mutable => Some("mut"),
hir::BindingAnnotation::Ref => Some("ref"),
hir::BindingAnnotation::RefMut => Some("ref mut"),
};
let suggested_ident = if let Some(binding) = binding {
format!("{} {}", binding, ident)
} else {
ident.to_string()
};
lint.build(fluent::lint::builtin_non_shorthand_field_patterns) lint.build(fluent::lint::builtin_non_shorthand_field_patterns)
.set_arg("ident", ident.clone()) .set_arg("ident", ident.clone())
.span_suggestion( .span_suggestion(

View file

@ -751,7 +751,7 @@ impl UnusedParens {
avoid_or: bool, avoid_or: bool,
avoid_mut: bool, avoid_mut: bool,
) { ) {
use ast::{BindingMode, Mutability, PatKind}; use ast::{BindingAnnotation, PatKind};
if let PatKind::Paren(inner) = &value.kind { if let PatKind::Paren(inner) = &value.kind {
match inner.kind { match inner.kind {
@ -763,7 +763,9 @@ impl UnusedParens {
// Avoid `p0 | .. | pn` if we should. // Avoid `p0 | .. | pn` if we should.
PatKind::Or(..) if avoid_or => return, PatKind::Or(..) if avoid_or => return,
// Avoid `mut x` and `mut x @ p` if we should: // Avoid `mut x` and `mut x @ p` if we should:
PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..) if avoid_mut => return, PatKind::Ident(BindingAnnotation::MUT, ..) if avoid_mut => {
return;
}
// Otherwise proceed with linting. // Otherwise proceed with linting.
_ => {} _ => {}
} }

View file

@ -1,6 +1,4 @@
use rustc_hir::BindingAnnotation; use rustc_hir::{BindingAnnotation, ByRef, Mutability};
use rustc_hir::BindingAnnotation::*;
use rustc_hir::Mutability;
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Debug, Copy, HashStable)] #[derive(Clone, PartialEq, TyEncodable, TyDecodable, Debug, Copy, HashStable)]
pub enum BindingMode { pub enum BindingMode {
@ -11,12 +9,10 @@ pub enum BindingMode {
TrivialTypeTraversalAndLiftImpls! { BindingMode, } TrivialTypeTraversalAndLiftImpls! { BindingMode, }
impl BindingMode { impl BindingMode {
pub fn convert(ba: BindingAnnotation) -> BindingMode { pub fn convert(BindingAnnotation(by_ref, mutbl): BindingAnnotation) -> BindingMode {
match ba { match by_ref {
Unannotated => BindingMode::BindByValue(Mutability::Not), ByRef::No => BindingMode::BindByValue(mutbl),
Mutable => BindingMode::BindByValue(Mutability::Mut), ByRef::Yes => BindingMode::BindByReference(mutbl),
Ref => BindingMode::BindByReference(Mutability::Not),
RefMut => BindingMode::BindByReference(Mutability::Mut),
} }
} }
} }

View file

@ -10,9 +10,9 @@ use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind}; use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
use rustc_ast::util::parser::AssocOp; use rustc_ast::util::parser::AssocOp;
use rustc_ast::{ use rustc_ast::{
AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingAnnotation, Block,
BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Mutability, Param, Pat, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind,
PatKind, Path, PathSegment, QSelf, Ty, TyKind, Path, PathSegment, QSelf, Ty, TyKind,
}; };
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
@ -37,7 +37,7 @@ const TURBOFISH_SUGGESTION_STR: &str =
pub(super) fn dummy_arg(ident: Ident) -> Param { pub(super) fn dummy_arg(ident: Ident) -> Param {
let pat = P(Pat { let pat = P(Pat {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None), kind: PatKind::Ident(BindingAnnotation::NONE, ident, None),
span: ident.span, span: ident.span,
tokens: None, tokens: None,
}); });
@ -2961,7 +2961,7 @@ impl<'a> Parser<'a> {
} }
_ => {} _ => {}
}, },
PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => { PatKind::Ident(BindingAnnotation::NONE, ident, None) => {
match &first_pat.kind { match &first_pat.kind {
PatKind::Ident(_, old_ident, _) => { PatKind::Ident(_, old_ident, _) => {
let path = PatKind::Path( let path = PatKind::Path(

View file

@ -8,7 +8,7 @@ use rustc_ast::token::{self, Delimiter, TokenKind};
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
use rustc_ast::{self as ast, AttrVec, Attribute, DUMMY_NODE_ID}; use rustc_ast::{self as ast, AttrVec, Attribute, DUMMY_NODE_ID};
use rustc_ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; use rustc_ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind};
use rustc_ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind}; use rustc_ast::{BindingAnnotation, Block, FnDecl, FnSig, Param, SelfKind};
use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, VariantData}; use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, VariantData};
use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind}; use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::{MacArgs, MacCall, MacDelimiter}; use rustc_ast::{MacArgs, MacCall, MacDelimiter};
@ -2322,7 +2322,7 @@ impl<'a> Parser<'a> {
match ty { match ty {
Ok(ty) => { Ok(ty) => {
let ident = Ident::new(kw::Empty, this.prev_token.span); let ident = Ident::new(kw::Empty, this.prev_token.span);
let bm = BindingMode::ByValue(Mutability::Not); let bm = BindingAnnotation::NONE;
let pat = this.mk_pat_ident(ty.span, bm, ident); let pat = this.mk_pat_ident(ty.span, bm, ident);
(pat, ty) (pat, ty)
} }

View file

@ -4,8 +4,8 @@ use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter}; use rustc_ast::token::{self, Delimiter};
use rustc_ast::{ use rustc_ast::{
self as ast, AttrVec, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField, PatKind, self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat,
Path, QSelf, RangeEnd, RangeSyntax, PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
}; };
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
@ -353,7 +353,7 @@ impl<'a> Parser<'a> {
} else if self.eat_keyword(kw::Ref) { } else if self.eat_keyword(kw::Ref) {
// Parse ref ident @ pat / ref mut ident @ pat // Parse ref ident @ pat / ref mut ident @ pat
let mutbl = self.parse_mutability(); let mutbl = self.parse_mutability();
self.parse_pat_ident(BindingMode::ByRef(mutbl))? self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl))?
} else if self.eat_keyword(kw::Box) { } else if self.eat_keyword(kw::Box) {
self.parse_pat_box()? self.parse_pat_box()?
} else if self.check_inline_const(0) { } else if self.check_inline_const(0) {
@ -369,7 +369,7 @@ impl<'a> Parser<'a> {
// Parse `ident @ pat` // Parse `ident @ pat`
// This can give false positives and parse nullary enums, // This can give false positives and parse nullary enums,
// they are dealt with later in resolve. // they are dealt with later in resolve.
self.parse_pat_ident(BindingMode::ByValue(Mutability::Not))? self.parse_pat_ident(BindingAnnotation::NONE)?
} else if self.is_start_of_pat_with_path() { } else if self.is_start_of_pat_with_path() {
// Parse pattern starting with a path // Parse pattern starting with a path
let (qself, path) = if self.eat_lt() { let (qself, path) = if self.eat_lt() {
@ -578,7 +578,8 @@ impl<'a> Parser<'a> {
let mut pat = self.parse_pat_no_top_alt(Some("identifier"))?; let mut pat = self.parse_pat_no_top_alt(Some("identifier"))?;
// If we don't have `mut $ident (@ pat)?`, error. // If we don't have `mut $ident (@ pat)?`, error.
if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind { if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
{
// Don't recurse into the subpattern. // Don't recurse into the subpattern.
// `mut` on the outer binding doesn't affect the inner bindings. // `mut` on the outer binding doesn't affect the inner bindings.
*m = Mutability::Mut; *m = Mutability::Mut;
@ -604,7 +605,7 @@ impl<'a> Parser<'a> {
) )
.emit(); .emit();
self.parse_pat_ident(BindingMode::ByRef(Mutability::Mut)) self.parse_pat_ident(BindingAnnotation::REF_MUT)
} }
/// Turn all by-value immutable bindings in a pattern into mutable bindings. /// Turn all by-value immutable bindings in a pattern into mutable bindings.
@ -613,7 +614,8 @@ impl<'a> Parser<'a> {
struct AddMut(bool); struct AddMut(bool);
impl MutVisitor for AddMut { impl MutVisitor for AddMut {
fn visit_pat(&mut self, pat: &mut P<Pat>) { fn visit_pat(&mut self, pat: &mut P<Pat>) {
if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) =
&mut pat.kind
{ {
self.0 = true; self.0 = true;
*m = Mutability::Mut; *m = Mutability::Mut;
@ -838,7 +840,7 @@ impl<'a> Parser<'a> {
/// Parses `ident` or `ident @ pat`. /// Parses `ident` or `ident @ pat`.
/// Used by the copy foo and ref foo patterns to give a good /// Used by the copy foo and ref foo patterns to give a good
/// error message when parsing mistakes like `ref foo(a, b)`. /// error message when parsing mistakes like `ref foo(a, b)`.
fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> { fn parse_pat_ident(&mut self, binding_annotation: BindingAnnotation) -> PResult<'a, PatKind> {
let ident = self.parse_ident()?; let ident = self.parse_ident()?;
let sub = if self.eat(&token::At) { let sub = if self.eat(&token::At) {
Some(self.parse_pat_no_top_alt(Some("binding pattern"))?) Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
@ -856,7 +858,7 @@ impl<'a> Parser<'a> {
.struct_span_err(self.prev_token.span, "expected identifier, found enum pattern")); .struct_span_err(self.prev_token.span, "expected identifier, found enum pattern"));
} }
Ok(PatKind::Ident(binding_mode, ident, sub)) Ok(PatKind::Ident(binding_annotation, ident, sub))
} }
/// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`). /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
@ -936,11 +938,7 @@ impl<'a> Parser<'a> {
None None
}; };
Ok(PatKind::Ident( Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub))
BindingMode::ByValue(Mutability::Not),
Ident::new(kw::Box, box_span),
sub,
))
} else { } else {
let pat = self.parse_pat_with_range_pat(false, None)?; let pat = self.parse_pat_with_range_pat(false, None)?;
self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span)); self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
@ -1117,14 +1115,12 @@ impl<'a> Parser<'a> {
let fieldname = self.parse_field_name()?; let fieldname = self.parse_field_name()?;
hi = self.prev_token.span; hi = self.prev_token.span;
let bind_type = match (is_ref, is_mut) { let mutability = match is_mut {
(true, true) => BindingMode::ByRef(Mutability::Mut), false => Mutability::Not,
(true, false) => BindingMode::ByRef(Mutability::Not), true => Mutability::Mut,
(false, true) => BindingMode::ByValue(Mutability::Mut),
(false, false) => BindingMode::ByValue(Mutability::Not),
}; };
let ann = BindingAnnotation(ByRef::from(is_ref), mutability);
let fieldpat = self.mk_pat_ident(boxed_span.to(hi), bind_type, fieldname); let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname);
let subpat = let subpat =
if is_box { self.mk_pat(lo.to(hi), PatKind::Box(fieldpat)) } else { fieldpat }; if is_box { self.mk_pat(lo.to(hi), PatKind::Box(fieldpat)) } else { fieldpat };
(subpat, fieldname, true) (subpat, fieldname, true)
@ -1141,8 +1137,8 @@ impl<'a> Parser<'a> {
}) })
} }
pub(super) fn mk_pat_ident(&self, span: Span, bm: BindingMode, ident: Ident) -> P<Pat> { pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingAnnotation, ident: Ident) -> P<Pat> {
self.mk_pat(span, PatKind::Ident(bm, ident, None)) self.mk_pat(span, PatKind::Ident(ann, ident, None))
} }
pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> { pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {

View file

@ -76,7 +76,7 @@ fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
for param in params { for param in params {
match param.pat.kind { match param.pat.kind {
hir::PatKind::Wild hir::PatKind::Wild
| hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, _, None) => {} | hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, _, None) => {}
_ => { _ => {
tcx.sess tcx.sess
.struct_span_err( .struct_span_err(

View file

@ -20,7 +20,7 @@ use rustc_errors::DiagnosticId;
use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::{PrimTy, TraitCandidate}; use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
use rustc_middle::middle::resolve_lifetime::Set1; use rustc_middle::middle::resolve_lifetime::Set1;
use rustc_middle::ty::DefIdTree; use rustc_middle::ty::DefIdTree;
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
@ -50,7 +50,7 @@ use diagnostics::{
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct BindingInfo { struct BindingInfo {
span: Span, span: Span,
binding_mode: BindingMode, annotation: BindingAnnotation,
} }
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
@ -2865,10 +2865,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
pat.walk(&mut |pat| { pat.walk(&mut |pat| {
match pat.kind { match pat.kind {
PatKind::Ident(binding_mode, ident, ref sub_pat) PatKind::Ident(annotation, ident, ref sub_pat)
if sub_pat.is_some() || self.is_base_res_local(pat.id) => if sub_pat.is_some() || self.is_base_res_local(pat.id) =>
{ {
binding_map.insert(ident, BindingInfo { span: ident.span, binding_mode }); binding_map.insert(ident, BindingInfo { span: ident.span, annotation });
} }
PatKind::Or(ref ps) => { PatKind::Or(ref ps) => {
// Check the consistency of this or-pattern and // Check the consistency of this or-pattern and
@ -2925,7 +2925,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
binding_error.target.insert(pat_outer.span); binding_error.target.insert(pat_outer.span);
} }
Some(binding_outer) => { Some(binding_outer) => {
if binding_outer.binding_mode != binding_inner.binding_mode { if binding_outer.annotation != binding_inner.annotation {
// The binding modes in the outer and inner bindings differ. // The binding modes in the outer and inner bindings differ.
inconsistent_vars inconsistent_vars
.entry(name) .entry(name)
@ -3146,14 +3146,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn try_resolve_as_non_binding( fn try_resolve_as_non_binding(
&mut self, &mut self,
pat_src: PatternSource, pat_src: PatternSource,
bm: BindingMode, ann: BindingAnnotation,
ident: Ident, ident: Ident,
has_sub: bool, has_sub: bool,
) -> Option<Res> { ) -> Option<Res> {
// An immutable (no `mut`) by-value (no `ref`) binding pattern without // An immutable (no `mut`) by-value (no `ref`) binding pattern without
// a sub pattern (no `@ $pat`) is syntactically ambiguous as it could // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
// also be interpreted as a path to e.g. a constant, variant, etc. // also be interpreted as a path to e.g. a constant, variant, etc.
let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not); let is_syntactic_ambiguity = !has_sub && ann == BindingAnnotation::NONE;
let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?; let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?;
let (res, binding) = match ls_binding { let (res, binding) = match ls_binding {

View file

@ -866,23 +866,12 @@ impl<'l> Visitor<'l> for PathCollector<'l> {
hir::PatKind::TupleStruct(ref path, ..) | hir::PatKind::Path(ref path) => { hir::PatKind::TupleStruct(ref path, ..) | hir::PatKind::Path(ref path) => {
self.collected_paths.push((p.hir_id, path)); self.collected_paths.push((p.hir_id, path));
} }
hir::PatKind::Binding(bm, _, ident, _) => { hir::PatKind::Binding(hir::BindingAnnotation(_, mutbl), _, ident, _) => {
debug!( debug!(
"PathCollector, visit ident in pat {}: {:?} {:?}", "PathCollector, visit ident in pat {}: {:?} {:?}",
ident, p.span, ident.span ident, p.span, ident.span
); );
let immut = match bm { self.collected_idents.push((p.hir_id, ident, mutbl));
// Even if the ref is mut, you can't change the ref, only
// the data pointed at, so showing the initialising expression
// is still worthwhile.
hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Ref => {
hir::Mutability::Not
}
hir::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut => {
hir::Mutability::Mut
}
};
self.collected_idents.push((p.hir_id, ident, immut));
} }
_ => {} _ => {}
} }

View file

@ -774,7 +774,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Get the local name of this closure. This can be inaccurate because // Get the local name of this closure. This can be inaccurate because
// of the possibility of reassignment, but this should be good enough. // of the possibility of reassignment, but this should be good enough.
match &kind { match &kind {
hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, None) => { hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, ident, None) => {
Some(ident.name) Some(ident.name)
} }
_ => { _ => {

View file

@ -569,7 +569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> { ) -> Ty<'tcx> {
// Determine the binding mode... // Determine the binding mode...
let bm = match ba { let bm = match ba {
hir::BindingAnnotation::Unannotated => def_bm, hir::BindingAnnotation::NONE => def_bm,
_ => BindingMode::convert(ba), _ => BindingMode::convert(ba),
}; };
// ...and store it in a side table: // ...and store it in a side table:
@ -655,7 +655,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ba: hir::BindingAnnotation, ba: hir::BindingAnnotation,
) { ) {
match (expected.kind(), actual.kind(), ba) { match (expected.kind(), actual.kind(), ba) {
(ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::Unannotated) (ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::NONE)
if self.can_eq(self.param_env, *inner_ty, actual).is_ok() => if self.can_eq(self.param_env, *inner_ty, actual).is_ok() =>
{ {
err.span_suggestion_verbose( err.span_suggestion_verbose(
@ -665,7 +665,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }
(_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::Ref) (_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::REF)
if self.can_eq(self.param_env, expected, *inner_ty).is_ok() => if self.can_eq(self.param_env, expected, *inner_ty).is_ok() =>
{ {
err.span_suggestion_verbose( err.span_suggestion_verbose(

View file

@ -587,8 +587,7 @@ fn resolve_local<'tcx>(
// & expression, and its lifetime would be extended to the end of the block (due // & expression, and its lifetime would be extended to the end of the block (due
// to a different rule, not the below code). // to a different rule, not the below code).
match pat.kind { match pat.kind {
PatKind::Binding(hir::BindingAnnotation::Ref, ..) PatKind::Binding(hir::BindingAnnotation(hir::ByRef::Yes, _), ..) => true,
| PatKind::Binding(hir::BindingAnnotation::RefMut, ..) => true,
PatKind::Struct(_, ref field_pats, _) => { PatKind::Struct(_, ref field_pats, _) => {
field_pats.iter().any(|fp| is_binding_pat(&fp.pat)) field_pats.iter().any(|fp| is_binding_pat(&fp.pat))
@ -607,10 +606,7 @@ fn resolve_local<'tcx>(
PatKind::Box(ref subpat) => is_binding_pat(&subpat), PatKind::Box(ref subpat) => is_binding_pat(&subpat),
PatKind::Ref(_, _) PatKind::Ref(_, _)
| PatKind::Binding( | PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), ..)
hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
..,
)
| PatKind::Wild | PatKind::Wild
| PatKind::Path(_) | PatKind::Path(_)
| PatKind::Lit(_) | PatKind::Lit(_)

View file

@ -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 {

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); 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;

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 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::BindingAnnotation::Mutable | hir::BindingAnnotation::RefMut = binding { if let hir::PatKind::Binding(
return; 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 // 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

View file

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

View file

@ -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);
} }
}); });

View file

@ -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);
} }

View file

@ -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;

View file

@ -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 {
"" ""

View file

@ -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

View file

@ -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))) => {

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

View file

@ -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,

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 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(

View file

@ -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) {

View file

@ -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,9 +212,8 @@ 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),

View file

@ -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())

View file

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

View file

@ -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);
} }

View file

@ -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 {

View file

@ -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,

View file

@ -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() {

View file

@ -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.

View file

@ -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,
} }
} }

View file

@ -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))

View file

@ -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(

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)` // 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);

View file

@ -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)));

View file

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

View file

@ -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(_))

View file

@ -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);
} }

View file

@ -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 {

View file

@ -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

View file

@ -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;

View file

@ -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 {

View file

@ -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

View file

@ -1,4 +1,6 @@
use rustc_ast::ast::{self, BindingMode, Pat, PatField, PatKind, RangeEnd, RangeSyntax}; use rustc_ast::ast::{
self, BindingAnnotation, ByRef, Pat, PatField, PatKind, RangeEnd, RangeSyntax,
};
use rustc_ast::ptr; use rustc_ast::ptr;
use rustc_span::{BytePos, Span}; use rustc_span::{BytePos, Span};
@ -99,10 +101,10 @@ impl Rewrite for Pat {
write_list(&items, &fmt) write_list(&items, &fmt)
} }
PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape),
PatKind::Ident(binding_mode, ident, ref sub_pat) => { PatKind::Ident(BindingAnnotation(by_ref, mutability), ident, ref sub_pat) => {
let (prefix, mutability) = match binding_mode { let prefix = match by_ref {
BindingMode::ByRef(mutability) => ("ref", mutability), ByRef::Yes => "ref",
BindingMode::ByValue(mutability) => ("", mutability), ByRef::No => "",
}; };
let mut_infix = format_mutability(mutability).trim(); let mut_infix = format_mutability(mutability).trim();
let id_str = rewrite_ident(context, ident); let id_str = rewrite_ident(context, ident);