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