Refactor and re-use BindingAnnotation

This commit is contained in:
Cameron Steffen 2022-08-30 17:34:35 -05:00
parent 9353538c7b
commit 02ba216e3c
25 changed files with 176 additions and 225 deletions

View File

@ -594,7 +594,7 @@ impl Pat {
// In a type expression `_` is an inference variable.
PatKind::Wild => TyKind::Infer,
// 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))
}
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
@ -681,10 +681,43 @@ pub struct PatField {
pub is_placeholder: bool,
}
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
pub enum BindingMode {
ByRef(Mutability),
ByValue(Mutability),
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum ByRef {
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)]
@ -713,7 +746,7 @@ pub enum PatKind {
/// 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
/// 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, ..}`).
/// The `bool` is `true` in the presence of a `..`.
@ -2228,7 +2261,7 @@ pub type ExplicitSelf = Spanned<SelfKind>;
impl Param {
/// Attempts to cast parameter to `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 {
return match self.ty.kind {
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 {
let span = eself.span.to(eself_ident.span);
let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span, tokens: None });
let param = |mutbl, ty| Param {
attrs,
pat: P(Pat {
id: DUMMY_NODE_ID,
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(
let (mutbl, ty) = match eself.node {
SelfKind::Explicit(ty, mutbl) => (mutbl, ty),
SelfKind::Value(mutbl) => (mutbl, infer_ty),
SelfKind::Region(lt, mutbl) => (
Mutability::Not,
P(Ty {
id: DUMMY_NODE_ID,
@ -2283,6 +2303,19 @@ impl Param {
tokens: None,
}),
),
};
Param {
attrs,
pat: P(Pat {
id: DUMMY_NODE_ID,
kind: PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), eself_ident, None),
span,
tokens: None,
}),
span,
ty,
id: DUMMY_NODE_ID,
is_placeholder: false,
}
}
}

View File

@ -577,7 +577,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (pat, task_context_hid) = self.pat_ident_binding_mode(
span,
Ident::with_dummy_span(sym::_task_context),
hir::BindingAnnotation::Mutable,
hir::BindingAnnotation::MUT,
);
let param = hir::Param {
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.
let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
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);
@ -1433,7 +1433,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `mut iter`
let iter = Ident::with_dummy_span(sym::iter);
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) { ... }`
let match_expr = {

View File

@ -1074,12 +1074,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
// 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 (ident, is_simple_parameter) = match parameter.pat.kind {
hir::PatKind::Binding(
hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
_,
ident,
_,
) => (ident, true),
hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => {
(ident, true)
}
// For `ref mut` or wildcard arguments, we can't reuse the binding, but
// we can keep the same name for the parameter.
// This lets rustdoc render it correctly in documentation.
@ -1144,7 +1141,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (move_pat, move_id) = this.pat_ident_binding_mode(
desugared_span,
ident,
hir::BindingAnnotation::Mutable,
hir::BindingAnnotation::MUT,
);
let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id);
let move_stmt = this.stmt_let_pat(

View File

@ -1696,10 +1696,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
output,
c_variadic,
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
use BindingMode::{ByRef, ByValue};
let is_mutable_pat = matches!(
arg.pat.kind,
PatKind::Ident(ByValue(Mutability::Mut) | ByRef(Mutability::Mut), ..)
PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..)
);
match arg.ty.kind {
@ -2361,11 +2360,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
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) {
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(

View File

@ -24,7 +24,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let node = loop {
match pattern.kind {
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));
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;
// 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 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)
};
@ -194,9 +194,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
// Found a sub-slice pattern `$binding_mode $ident @ ..`.
// 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);
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;
}
// 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.
let rest_span = match pat.kind {
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.
after.push(lower_rest_sub(self, pat, bm, ident, sub));
after.push(lower_rest_sub(self, pat, ann, ident, sub));
Some(sub.span)
}
_ => None,
@ -235,7 +235,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_pat_ident(
&mut self,
p: &Pat,
binding_mode: &BindingMode,
annotation: BindingAnnotation,
ident: Ident,
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
) -> hir::PatKind<'hir> {
@ -248,7 +248,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
};
hir::PatKind::Binding(
self.lower_binding_mode(binding_mode),
annotation,
self.lower_node_id(canonical_id),
self.lower_ident(ident),
lower_sub(self),
@ -265,15 +265,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> {
self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild))
}

View File

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

View File

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

View File

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

View File

@ -164,7 +164,9 @@ pub use SubstructureFields::*;
use crate::deriving;
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_attr as attr;
use rustc_expand::base::{Annotatable, ExtCtxt};
@ -1063,9 +1065,9 @@ impl<'a> MethodDef<'a> {
let mut body = mk_body(cx, selflike_fields);
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 =
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.
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 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(
cx,
variant_path,
&variant.data,
&prefixes,
use_ref_pat,
by_ref,
);
// `(VariantK, VariantK, ...)` or just `VariantK`.
@ -1414,7 +1416,7 @@ impl<'a> TraitDef<'a> {
struct_path: ast::Path,
struct_def: &'a VariantData,
prefixes: &[String],
use_ref_pat: bool,
by_ref: ByRef,
) -> Vec<P<ast::Pat>> {
prefixes
.iter()
@ -1422,17 +1424,19 @@ impl<'a> TraitDef<'a> {
let pieces_iter =
struct_def.fields().iter().enumerate().map(|(i, struct_field)| {
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 path = ident.with_span_pos(sp);
(
sp,
struct_field.ident,
cx.pat(path.span, PatKind::Ident(binding_mode, path, None)),
cx.pat(
path.span,
PatKind::Ident(
BindingAnnotation(by_ref, Mutability::Not),
path,
None,
),
),
)
});

View File

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

View File

@ -7,7 +7,7 @@ use crate::LangItem;
use rustc_ast as ast;
use rustc_ast::util::parser::ExprPrecedence;
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};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_data_structures::fingerprint::Fingerprint;
@ -1049,30 +1049,6 @@ pub struct PatField<'hir> {
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)]
pub enum RangeEnd {
Included,

View File

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

View File

@ -9,7 +9,9 @@ use rustc_ast_pretty::pp::{self, Breaks};
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir as hir;
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_span::source_map::SourceMap;
use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
@ -1758,20 +1760,12 @@ impl<'a> State<'a> {
// is that it doesn't matter
match pat.kind {
PatKind::Wild => self.word("_"),
PatKind::Binding(binding_mode, _, ident, sub) => {
match binding_mode {
hir::BindingAnnotation::Ref => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Not, false);
}
hir::BindingAnnotation::RefMut => {
self.word_nbsp("ref");
self.print_mutability(hir::Mutability::Mut, false);
}
hir::BindingAnnotation::Unannotated => {}
hir::BindingAnnotation::Mutable => {
self.word_nbsp("mut");
}
PatKind::Binding(BindingAnnotation(by_ref, mutbl), _, ident, sub) => {
if by_ref == ByRef::Yes {
self.word_nbsp("ref");
}
if mutbl == Mutability::Mut {
self.word_nbsp("mut");
}
self.print_ident(ident);
if let Some(p) = sub {

View File

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

View File

@ -751,7 +751,7 @@ impl UnusedParens {
avoid_or: bool,
avoid_mut: bool,
) {
use ast::{BindingMode, Mutability, PatKind};
use ast::{BindingAnnotation, PatKind};
if let PatKind::Paren(inner) = &value.kind {
match inner.kind {
@ -763,7 +763,9 @@ impl UnusedParens {
// Avoid `p0 | .. | pn` if we should.
PatKind::Or(..) if avoid_or => return,
// 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.
_ => {}
}

View File

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

View File

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

View File

@ -8,7 +8,7 @@ use rustc_ast::token::{self, Delimiter, TokenKind};
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
use rustc_ast::{self as ast, AttrVec, Attribute, DUMMY_NODE_ID};
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::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::{MacArgs, MacCall, MacDelimiter};
@ -2322,7 +2322,7 @@ impl<'a> Parser<'a> {
match ty {
Ok(ty) => {
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);
(pat, ty)
}

View File

@ -4,8 +4,8 @@ use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter};
use rustc_ast::{
self as ast, AttrVec, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField, PatKind,
Path, QSelf, RangeEnd, RangeSyntax,
self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat,
PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
};
use rustc_ast_pretty::pprust;
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) {
// Parse ref ident @ pat / ref mut ident @ pat
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) {
self.parse_pat_box()?
} else if self.check_inline_const(0) {
@ -369,7 +369,7 @@ impl<'a> Parser<'a> {
// Parse `ident @ pat`
// This can give false positives and parse nullary enums,
// 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() {
// Parse pattern starting with a path
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"))?;
// 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.
// `mut` on the outer binding doesn't affect the inner bindings.
*m = Mutability::Mut;
@ -604,7 +605,7 @@ impl<'a> Parser<'a> {
)
.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.
@ -613,7 +614,8 @@ impl<'a> Parser<'a> {
struct AddMut(bool);
impl MutVisitor for AddMut {
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;
*m = Mutability::Mut;
@ -838,7 +840,7 @@ impl<'a> Parser<'a> {
/// Parses `ident` or `ident @ pat`.
/// Used by the copy foo and ref foo patterns to give a good
/// 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 sub = if self.eat(&token::At) {
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"));
}
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 { ... }`).
@ -936,11 +938,7 @@ impl<'a> Parser<'a> {
None
};
Ok(PatKind::Ident(
BindingMode::ByValue(Mutability::Not),
Ident::new(kw::Box, box_span),
sub,
))
Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub))
} else {
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));
@ -1117,14 +1115,12 @@ impl<'a> Parser<'a> {
let fieldname = self.parse_field_name()?;
hi = self.prev_token.span;
let bind_type = match (is_ref, is_mut) {
(true, true) => BindingMode::ByRef(Mutability::Mut),
(true, false) => BindingMode::ByRef(Mutability::Not),
(false, true) => BindingMode::ByValue(Mutability::Mut),
(false, false) => BindingMode::ByValue(Mutability::Not),
let mutability = match is_mut {
false => Mutability::Not,
true => Mutability::Mut,
};
let fieldpat = self.mk_pat_ident(boxed_span.to(hi), bind_type, fieldname);
let ann = BindingAnnotation(ByRef::from(is_ref), mutability);
let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname);
let subpat =
if is_box { self.mk_pat(lo.to(hi), PatKind::Box(fieldpat)) } else { fieldpat };
(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> {
self.mk_pat(span, PatKind::Ident(bm, ident, None))
pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingAnnotation, ident: Ident) -> P<Pat> {
self.mk_pat(span, PatKind::Ident(ann, ident, None))
}
pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {

View File

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

View File

@ -20,7 +20,7 @@ use rustc_errors::DiagnosticId;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
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::ty::DefIdTree;
use rustc_middle::{bug, span_bug};
@ -50,7 +50,7 @@ use diagnostics::{
#[derive(Copy, Clone, Debug)]
struct BindingInfo {
span: Span,
binding_mode: BindingMode,
annotation: BindingAnnotation,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@ -2865,10 +2865,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
pat.walk(&mut |pat| {
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) =>
{
binding_map.insert(ident, BindingInfo { span: ident.span, binding_mode });
binding_map.insert(ident, BindingInfo { span: ident.span, annotation });
}
PatKind::Or(ref ps) => {
// 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);
}
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.
inconsistent_vars
.entry(name)
@ -3146,14 +3146,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn try_resolve_as_non_binding(
&mut self,
pat_src: PatternSource,
bm: BindingMode,
ann: BindingAnnotation,
ident: Ident,
has_sub: bool,
) -> Option<Res> {
// An immutable (no `mut`) by-value (no `ref`) binding pattern without
// a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
// 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 (res, binding) = match ls_binding {

View File

@ -865,23 +865,12 @@ impl<'l> Visitor<'l> for PathCollector<'l> {
hir::PatKind::TupleStruct(ref path, ..) | hir::PatKind::Path(ref path) => {
self.collected_paths.push((p.hir_id, path));
}
hir::PatKind::Binding(bm, _, ident, _) => {
hir::PatKind::Binding(hir::BindingAnnotation(_, mutbl), _, ident, _) => {
debug!(
"PathCollector, visit ident in pat {}: {:?} {:?}",
ident, p.span, ident.span
);
let immut = match bm {
// 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));
self.collected_idents.push((p.hir_id, ident, mutbl));
}
_ => {}
}

View File

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

View File

@ -569,7 +569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
// Determine the binding mode...
let bm = match ba {
hir::BindingAnnotation::Unannotated => def_bm,
hir::BindingAnnotation::NONE => def_bm,
_ => BindingMode::convert(ba),
};
// ...and store it in a side table:
@ -655,7 +655,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ba: hir::BindingAnnotation,
) {
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() =>
{
err.span_suggestion_verbose(
@ -665,7 +665,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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() =>
{
err.span_suggestion_verbose(

View File

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