Rollup merge of #119231 - aDotInTheVoid:PatKind-struct-bool-docs, r=compiler-errors

Clairify `ast::PatKind::Struct` presese of `..` by using an enum instead of a bool

The bool is mainly used for when a `..` is present, but it is also set on recovery to avoid errors. The doc comment not describes both of these cases.

See cee794ee98/compiler/rustc_parse/src/parser/pat.rs (L890-L897) for the only place this is constructed.

r? ``@compiler-errors``
This commit is contained in:
Matthias Krüger 2023-12-23 16:23:54 +01:00 committed by GitHub
commit bdc4480914
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 30 additions and 15 deletions

View file

@ -754,8 +754,7 @@ pub enum PatKind {
Ident(BindingAnnotation, 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 `..`. Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),
Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, /* recovered */ bool),
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`). /// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
TupleStruct(Option<P<QSelf>>, Path, ThinVec<P<Pat>>), TupleStruct(Option<P<QSelf>>, Path, ThinVec<P<Pat>>),
@ -812,6 +811,15 @@ pub enum PatKind {
MacCall(P<MacCall>), MacCall(P<MacCall>),
} }
/// Whether the `..` is present in a struct fields pattern.
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)]
pub enum PatFieldsRest {
/// `module::StructName { field, ..}`
Rest,
/// `module::StructName { field }`
None,
}
/// The kind of borrow in an `AddrOf` expression, /// The kind of borrow in an `AddrOf` expression,
/// e.g., `&place` or `&raw const place`. /// e.g., `&place` or `&raw const place`.
#[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Debug)]

View file

@ -82,7 +82,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: self.lower_span(f.span), span: self.lower_span(f.span),
} }
})); }));
break hir::PatKind::Struct(qpath, fs, *etc); break hir::PatKind::Struct(qpath, fs, *etc == ast::PatFieldsRest::Rest);
} }
PatKind::Tuple(pats) => { PatKind::Tuple(pats) => {
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple"); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");

View file

@ -1427,7 +1427,7 @@ impl<'a> State<'a> {
} }
self.nbsp(); self.nbsp();
self.word("{"); self.word("{");
let empty = fields.is_empty() && !etc; let empty = fields.is_empty() && *etc == ast::PatFieldsRest::None;
if !empty { if !empty {
self.space(); self.space();
} }
@ -1445,7 +1445,7 @@ impl<'a> State<'a> {
}, },
|f| f.pat.span, |f| f.pat.span,
); );
if *etc { if *etc == ast::PatFieldsRest::Rest {
if !fields.is_empty() { if !fields.is_empty() {
self.word_space(","); self.word_space(",");
} }

View file

@ -491,7 +491,7 @@ impl<'a> ExtCtxt<'a> {
path: ast::Path, path: ast::Path,
field_pats: ThinVec<ast::PatField>, field_pats: ThinVec<ast::PatField>,
) -> P<ast::Pat> { ) -> P<ast::Pat> {
self.pat(span, PatKind::Struct(None, path, field_pats, false)) self.pat(span, PatKind::Struct(None, path, field_pats, ast::PatFieldsRest::None))
} }
pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> { pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> {
self.pat(span, PatKind::Tuple(pats)) self.pat(span, PatKind::Tuple(pats))

View file

@ -15,7 +15,7 @@ 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, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat,
PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
}; };
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, DiagnosticBuilder, PResult}; use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
@ -891,7 +891,8 @@ impl<'a> Parser<'a> {
e.span_label(path.span, "while parsing the fields for this pattern"); e.span_label(path.span, "while parsing the fields for this pattern");
e.emit(); e.emit();
self.recover_stmt(); self.recover_stmt();
(ThinVec::new(), true) // When recovering, pretend we had `Foo { .. }`, to avoid cascading errors.
(ThinVec::new(), PatFieldsRest::Rest)
}); });
self.bump(); self.bump();
Ok(PatKind::Struct(qself, path, fields, etc)) Ok(PatKind::Struct(qself, path, fields, etc))
@ -965,9 +966,9 @@ impl<'a> Parser<'a> {
} }
/// Parses the fields of a struct-like pattern. /// Parses the fields of a struct-like pattern.
fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, bool)> { fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, PatFieldsRest)> {
let mut fields = ThinVec::new(); let mut fields = ThinVec::new();
let mut etc = false; let mut etc = PatFieldsRest::None;
let mut ate_comma = true; let mut ate_comma = true;
let mut delayed_err: Option<DiagnosticBuilder<'a>> = None; let mut delayed_err: Option<DiagnosticBuilder<'a>> = None;
let mut first_etc_and_maybe_comma_span = None; let mut first_etc_and_maybe_comma_span = None;
@ -1001,7 +1002,7 @@ impl<'a> Parser<'a> {
|| self.check_noexpect(&token::DotDotDot) || self.check_noexpect(&token::DotDotDot)
|| self.check_keyword(kw::Underscore) || self.check_keyword(kw::Underscore)
{ {
etc = true; etc = PatFieldsRest::Rest;
let mut etc_sp = self.token.span; let mut etc_sp = self.token.span;
if first_etc_and_maybe_comma_span.is_none() { if first_etc_and_maybe_comma_span.is_none() {
if let Some(comma_tok) = self if let Some(comma_tok) = self

View file

@ -293,7 +293,7 @@ fn extend_with_struct_pat(
qself1: &Option<P<ast::QSelf>>, qself1: &Option<P<ast::QSelf>>,
path1: &ast::Path, path1: &ast::Path,
fps1: &mut [ast::PatField], fps1: &mut [ast::PatField],
rest1: bool, rest1: ast::PatFieldsRest,
start: usize, start: usize,
alternatives: &mut ThinVec<P<Pat>>, alternatives: &mut ThinVec<P<Pat>>,
) -> bool { ) -> bool {

View file

@ -259,9 +259,15 @@ impl Rewrite for Pat {
None, None,
None, None,
), ),
PatKind::Struct(ref qself, ref path, ref fields, ellipsis) => { PatKind::Struct(ref qself, ref path, ref fields, rest) => rewrite_struct_pat(
rewrite_struct_pat(qself, path, fields, ellipsis, self.span, context, shape) qself,
} path,
fields,
rest == ast::PatFieldsRest::Rest,
self.span,
context,
shape,
),
PatKind::MacCall(ref mac) => { PatKind::MacCall(ref mac) => {
rewrite_macro(mac, None, context, shape, MacroPosition::Pat) rewrite_macro(mac, None, context, shape, MacroPosition::Pat)
} }