Allign RecordPat with RecordExpr

This commit is contained in:
Aleksey Kladov 2020-07-31 19:54:16 +02:00
parent 572f1c08b6
commit 14cb96ec0e
22 changed files with 78 additions and 85 deletions

View file

@ -57,7 +57,7 @@ fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> { fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
match node.kind() { match node.kind() {
RECORD_EXPR => vec![RECORD_EXPR_FIELD], RECORD_EXPR => vec![RECORD_EXPR_FIELD],
RECORD_PAT => vec![RECORD_FIELD_PAT, BIND_PAT], RECORD_PAT => vec![RECORD_PAT_FIELD, BIND_PAT],
_ => vec![], _ => vec![],
} }
} }
@ -66,7 +66,7 @@ fn get_field_name(node: &SyntaxNode) -> String {
let res = match_ast! { let res = match_ast! {
match node { match node {
ast::RecordExprField(field) => field.field_name().map(|it| it.to_string()), ast::RecordExprField(field) => field.field_name().map(|it| it.to_string()),
ast::RecordFieldPat(field) => field.field_name().map(|it| it.to_string()), ast::RecordPatField(field) => field.field_name().map(|it| it.to_string()),
_ => None, _ => None,
} }
}; };

View file

@ -216,7 +216,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.resolve_record_field(field) self.imp.resolve_record_field(field)
} }
pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> { pub fn resolve_record_field_pat(&self, field: &ast::RecordPatField) -> Option<Field> {
self.imp.resolve_record_field_pat(field) self.imp.resolve_record_field_pat(field)
} }
@ -429,7 +429,7 @@ impl<'db> SemanticsImpl<'db> {
self.analyze(field.syntax()).resolve_record_field(self.db, field) self.analyze(field.syntax()).resolve_record_field(self.db, field)
} }
fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> { fn resolve_record_field_pat(&self, field: &ast::RecordPatField) -> Option<Field> {
self.analyze(field.syntax()).resolve_record_field_pat(self.db, field) self.analyze(field.syntax()).resolve_record_field_pat(self.db, field)
} }

View file

@ -182,7 +182,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_record_field_pat( pub(crate) fn resolve_record_field_pat(
&self, &self,
_db: &dyn HirDatabase, _db: &dyn HirDatabase,
field: &ast::RecordFieldPat, field: &ast::RecordPatField,
) -> Option<Field> { ) -> Option<Field> {
let pat_id = self.pat_id(&field.pat()?)?; let pat_id = self.pat_id(&field.pat()?)?;
let struct_field = self.infer.as_ref()?.record_field_pat_resolution(pat_id)?; let struct_field = self.infer.as_ref()?.record_field_pat_resolution(pat_id)?;

View file

@ -1,6 +1,8 @@
//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
//! representation. //! representation.
use std::{any::type_name, sync::Arc};
use either::Either; use either::Either;
use hir_expand::{ use hir_expand::{
hygiene::Hygiene, hygiene::Hygiene,
@ -10,11 +12,12 @@ use hir_expand::{
use ra_arena::Arena; use ra_arena::Arena;
use ra_syntax::{ use ra_syntax::{
ast::{ ast::{
self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner,
SlicePatComponents, SlicePatComponents,
}, },
AstNode, AstPtr, AstNode, AstPtr,
}; };
use rustc_hash::FxHashMap;
use test_utils::mark; use test_utils::mark;
use crate::{ use crate::{
@ -35,9 +38,6 @@ use crate::{
}; };
use super::{ExprSource, PatSource}; use super::{ExprSource, PatSource};
use ast::AstChildren;
use rustc_hash::FxHashMap;
use std::{any::type_name, sync::Arc};
pub(crate) struct LowerCtx { pub(crate) struct LowerCtx {
hygiene: Hygiene, hygiene: Hygiene,
@ -786,29 +786,26 @@ impl ExprCollector<'_> {
ast::Pat::PlaceholderPat(_) => Pat::Wild, ast::Pat::PlaceholderPat(_) => Pat::Wild,
ast::Pat::RecordPat(p) => { ast::Pat::RecordPat(p) => {
let path = p.path().and_then(|path| self.expander.parse_path(path)); let path = p.path().and_then(|path| self.expander.parse_path(path));
let record_field_pat_list =
p.record_field_pat_list().expect("every struct should have a field list"); let args: Vec<_> = p
let mut fields: Vec<_> = record_field_pat_list .record_pat_field_list()
.bind_pats() .expect("every struct should have a field list")
.filter_map(|bind_pat| { .fields()
let ast_pat = .filter_map(|f| {
ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat"); let ast_pat = f.pat()?;
let pat = self.collect_pat(ast_pat); let pat = self.collect_pat(ast_pat);
let name = bind_pat.name()?.as_name(); let name = f.field_name()?.as_name();
Some(RecordFieldPat { name, pat }) Some(RecordFieldPat { name, pat })
}) })
.collect(); .collect();
let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
let ast_pat = f.pat()?;
let pat = self.collect_pat(ast_pat);
let name = f.field_name()?.as_name();
Some(RecordFieldPat { name, pat })
});
fields.extend(iter);
let ellipsis = record_field_pat_list.dotdot_token().is_some(); let ellipsis = p
.record_pat_field_list()
.expect("every struct should have a field list")
.dotdot_token()
.is_some();
Pat::Record { path, args: fields, ellipsis } Pat::Record { path, args, ellipsis }
} }
ast::Pat::SlicePat(p) => { ast::Pat::SlicePat(p) => {
let SlicePatComponents { prefix, slice, suffix } = p.components(); let SlicePatComponents { prefix, slice, suffix } = p.components();

View file

@ -92,7 +92,7 @@ impl AstDiagnostic for MissingFields {
#[derive(Debug)] #[derive(Debug)]
pub struct MissingPatFields { pub struct MissingPatFields {
pub file: HirFileId, pub file: HirFileId,
pub field_list: AstPtr<ast::RecordFieldPatList>, pub field_list: AstPtr<ast::RecordPatFieldList>,
pub missed_fields: Vec<Name>, pub missed_fields: Vec<Name>,
} }

View file

@ -131,7 +131,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
if let Some(expr) = source_ptr.value.as_ref().left() { if let Some(expr) = source_ptr.value.as_ref().left() {
let root = source_ptr.file_syntax(db.upcast()); let root = source_ptr.file_syntax(db.upcast());
if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
if let Some(field_list) = record_pat.record_field_pat_list() { if let Some(field_list) = record_pat.record_pat_field_list() {
let variant_data = variant_data(db.upcast(), variant_def); let variant_data = variant_data(db.upcast(), variant_def);
let missed_fields = missed_fields let missed_fields = missed_fields
.into_iter() .into_iter()

View file

@ -265,7 +265,7 @@ impl<'a> CompletionContext<'a> {
return; return;
} }
// FIXME: remove this (V) duplication and make the check more precise // FIXME: remove this (V) duplication and make the check more precise
if name_ref.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() { if name_ref.syntax().ancestors().find_map(ast::RecordPatFieldList::cast).is_some() {
self.record_pat_syntax = self.record_pat_syntax =
self.sema.find_node_at_offset_with_macros(&original_file, offset); self.sema.find_node_at_offset_with_macros(&original_file, offset);
} }
@ -283,7 +283,7 @@ impl<'a> CompletionContext<'a> {
{ {
self.is_pat_binding_or_const = false; self.is_pat_binding_or_const = false;
} }
if bind_pat.syntax().parent().and_then(ast::RecordFieldPatList::cast).is_some() { if bind_pat.syntax().parent().and_then(ast::RecordPatFieldList::cast).is_some() {
self.is_pat_binding_or_const = false; self.is_pat_binding_or_const = false;
} }
if let Some(let_stmt) = bind_pat.syntax().ancestors().find_map(ast::LetStmt::cast) { if let Some(let_stmt) = bind_pat.syntax().ancestors().find_map(ast::LetStmt::cast) {
@ -300,7 +300,7 @@ impl<'a> CompletionContext<'a> {
return; return;
} }
// FIXME: remove this (^) duplication and make the check more precise // FIXME: remove this (^) duplication and make the check more precise
if name.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() { if name.syntax().ancestors().find_map(ast::RecordPatFieldList::cast).is_some() {
self.record_pat_syntax = self.record_pat_syntax =
self.sema.find_node_at_offset_with_macros(&original_file, offset); self.sema.find_node_at_offset_with_macros(&original_file, offset);
} }

View file

@ -37,7 +37,7 @@ fn try_extend_selection(
let string_kinds = [COMMENT, STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING]; let string_kinds = [COMMENT, STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
let list_kinds = [ let list_kinds = [
RECORD_FIELD_PAT_LIST, RECORD_PAT_FIELD_LIST,
MATCH_ARM_LIST, MATCH_ARM_LIST,
RECORD_FIELD_LIST, RECORD_FIELD_LIST,
TUPLE_FIELD_LIST, TUPLE_FIELD_LIST,

View file

@ -86,7 +86,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
USE => Some(FoldKind::Imports), USE => Some(FoldKind::Imports),
ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList), ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList),
RECORD_FIELD_LIST RECORD_FIELD_LIST
| RECORD_FIELD_PAT_LIST | RECORD_PAT_FIELD_LIST
| RECORD_EXPR_FIELD_LIST | RECORD_EXPR_FIELD_LIST
| ITEM_LIST | ITEM_LIST
| EXTERN_ITEM_LIST | EXTERN_ITEM_LIST

View file

@ -131,7 +131,7 @@ pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option
ast::BindPat(it) => { ast::BindPat(it) => {
let local = sema.to_def(&it)?; let local = sema.to_def(&it)?;
if let Some(record_field_pat) = it.syntax().parent().and_then(ast::RecordFieldPat::cast) { if let Some(record_field_pat) = it.syntax().parent().and_then(ast::RecordPatField::cast) {
if record_field_pat.name_ref().is_none() { if record_field_pat.name_ref().is_none() {
if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) { if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) {
let field = Definition::Field(field); let field = Definition::Field(field);
@ -247,7 +247,7 @@ pub fn classify_name_ref(
} }
} }
if let Some(record_field_pat) = ast::RecordFieldPat::cast(parent.clone()) { if let Some(record_field_pat) = ast::RecordPatField::cast(parent.clone()) {
if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) { if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) {
let field = Definition::Field(field); let field = Definition::Field(field);
return Some(NameRefClass::Definition(field)); return Some(NameRefClass::Definition(field));

View file

@ -217,7 +217,7 @@ fn record_field_pat_list(p: &mut Parser) {
bind_pat(p, false); bind_pat(p, false);
} }
} }
m.complete(p, RECORD_FIELD_PAT); m.complete(p, RECORD_PAT_FIELD);
} }
} }
if !p.at(T!['}']) { if !p.at(T!['}']) {
@ -225,7 +225,7 @@ fn record_field_pat_list(p: &mut Parser) {
} }
} }
p.expect(T!['}']); p.expect(T!['}']);
m.complete(p, RECORD_FIELD_PAT_LIST); m.complete(p, RECORD_PAT_FIELD_LIST);
} }
// test placeholder_pat // test placeholder_pat

View file

@ -161,8 +161,8 @@ pub enum SyntaxKind {
DOT_DOT_PAT, DOT_DOT_PAT,
PATH_PAT, PATH_PAT,
RECORD_PAT, RECORD_PAT,
RECORD_FIELD_PAT_LIST, RECORD_PAT_FIELD_LIST,
RECORD_FIELD_PAT, RECORD_PAT_FIELD,
TUPLE_STRUCT_PAT, TUPLE_STRUCT_PAT,
TUPLE_PAT, TUPLE_PAT,
SLICE_PAT, SLICE_PAT,

View file

@ -1192,7 +1192,7 @@ pub struct RecordPat {
} }
impl RecordPat { impl RecordPat {
pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
pub fn record_field_pat_list(&self) -> Option<RecordFieldPatList> { pub fn record_pat_field_list(&self) -> Option<RecordPatFieldList> {
support::child(&self.syntax) support::child(&self.syntax)
} }
} }
@ -1234,24 +1234,21 @@ impl TupleStructPat {
pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RecordFieldPatList { pub struct RecordPatFieldList {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
impl RecordFieldPatList { impl RecordPatFieldList {
pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
pub fn record_field_pats(&self) -> AstChildren<RecordFieldPat> { pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
support::children(&self.syntax)
}
pub fn bind_pats(&self) -> AstChildren<BindPat> { support::children(&self.syntax) }
pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RecordFieldPat { pub struct RecordPatField {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
impl ast::AttrsOwner for RecordFieldPat {} impl ast::AttrsOwner for RecordPatField {}
impl RecordFieldPat { impl RecordPatField {
pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
@ -2724,8 +2721,8 @@ impl AstNode for TupleStructPat {
} }
fn syntax(&self) -> &SyntaxNode { &self.syntax } fn syntax(&self) -> &SyntaxNode { &self.syntax }
} }
impl AstNode for RecordFieldPatList { impl AstNode for RecordPatFieldList {
fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_PAT_LIST } fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST }
fn cast(syntax: SyntaxNode) -> Option<Self> { fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) { if Self::can_cast(syntax.kind()) {
Some(Self { syntax }) Some(Self { syntax })
@ -2735,8 +2732,8 @@ impl AstNode for RecordFieldPatList {
} }
fn syntax(&self) -> &SyntaxNode { &self.syntax } fn syntax(&self) -> &SyntaxNode { &self.syntax }
} }
impl AstNode for RecordFieldPat { impl AstNode for RecordPatField {
fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_PAT } fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD }
fn cast(syntax: SyntaxNode) -> Option<Self> { fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) { if Self::can_cast(syntax.kind()) {
Some(Self { syntax }) Some(Self { syntax })
@ -4059,12 +4056,12 @@ impl std::fmt::Display for TupleStructPat {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for RecordFieldPatList { impl std::fmt::Display for RecordPatFieldList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for RecordFieldPat { impl std::fmt::Display for RecordPatField {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }

View file

@ -227,7 +227,7 @@ impl fmt::Display for NameOrNameRef {
} }
} }
impl ast::RecordFieldPat { impl ast::RecordPatField {
/// Deals with field init shorthand /// Deals with field init shorthand
pub fn field_name(&self) -> Option<NameOrNameRef> { pub fn field_name(&self) -> Option<NameOrNameRef> {
if let Some(name_ref) = self.name_ref() { if let Some(name_ref) = self.name_ref() {

View file

@ -58,7 +58,7 @@ SOURCE_FILE@0..103
NAME_REF@62..65 NAME_REF@62..65
IDENT@62..65 "Bar" IDENT@62..65 "Bar"
WHITESPACE@65..66 " " WHITESPACE@65..66 " "
RECORD_FIELD_PAT_LIST@66..72 RECORD_PAT_FIELD_LIST@66..72
L_CURLY@66..67 "{" L_CURLY@66..67 "{"
WHITESPACE@67..68 " " WHITESPACE@67..68 " "
DOT2@68..70 ".." DOT2@68..70 ".."

View file

@ -20,7 +20,7 @@ SOURCE_FILE@0..119
NAME_REF@19..20 NAME_REF@19..20
IDENT@19..20 "S" IDENT@19..20 "S"
WHITESPACE@20..21 " " WHITESPACE@20..21 " "
RECORD_FIELD_PAT_LIST@21..23 RECORD_PAT_FIELD_LIST@21..23
L_CURLY@21..22 "{" L_CURLY@21..22 "{"
R_CURLY@22..23 "}" R_CURLY@22..23 "}"
WHITESPACE@23..24 " " WHITESPACE@23..24 " "
@ -40,16 +40,16 @@ SOURCE_FILE@0..119
NAME_REF@38..39 NAME_REF@38..39
IDENT@38..39 "S" IDENT@38..39 "S"
WHITESPACE@39..40 " " WHITESPACE@39..40 " "
RECORD_FIELD_PAT_LIST@40..56 RECORD_PAT_FIELD_LIST@40..56
L_CURLY@40..41 "{" L_CURLY@40..41 "{"
WHITESPACE@41..42 " " WHITESPACE@41..42 " "
RECORD_FIELD_PAT@42..43 RECORD_PAT_FIELD@42..43
BIND_PAT@42..43 BIND_PAT@42..43
NAME@42..43 NAME@42..43
IDENT@42..43 "f" IDENT@42..43 "f"
COMMA@43..44 "," COMMA@43..44 ","
WHITESPACE@44..45 " " WHITESPACE@44..45 " "
RECORD_FIELD_PAT@45..54 RECORD_PAT_FIELD@45..54
BIND_PAT@45..54 BIND_PAT@45..54
REF_KW@45..48 "ref" REF_KW@45..48 "ref"
WHITESPACE@48..49 " " WHITESPACE@48..49 " "
@ -76,10 +76,10 @@ SOURCE_FILE@0..119
NAME_REF@71..72 NAME_REF@71..72
IDENT@71..72 "S" IDENT@71..72 "S"
WHITESPACE@72..73 " " WHITESPACE@72..73 " "
RECORD_FIELD_PAT_LIST@73..84 RECORD_PAT_FIELD_LIST@73..84
L_CURLY@73..74 "{" L_CURLY@73..74 "{"
WHITESPACE@74..75 " " WHITESPACE@74..75 " "
RECORD_FIELD_PAT@75..79 RECORD_PAT_FIELD@75..79
NAME_REF@75..76 NAME_REF@75..76
IDENT@75..76 "h" IDENT@75..76 "h"
COLON@76..77 ":" COLON@76..77 ":"
@ -107,10 +107,10 @@ SOURCE_FILE@0..119
NAME_REF@99..100 NAME_REF@99..100
IDENT@99..100 "S" IDENT@99..100 "S"
WHITESPACE@100..101 " " WHITESPACE@100..101 " "
RECORD_FIELD_PAT_LIST@101..110 RECORD_PAT_FIELD_LIST@101..110
L_CURLY@101..102 "{" L_CURLY@101..102 "{"
WHITESPACE@102..103 " " WHITESPACE@102..103 " "
RECORD_FIELD_PAT@103..107 RECORD_PAT_FIELD@103..107
NAME_REF@103..104 NAME_REF@103..104
IDENT@103..104 "h" IDENT@103..104 "h"
COLON@104..105 ":" COLON@104..105 ":"

View file

@ -40,10 +40,10 @@ SOURCE_FILE@0..118
NAME_REF@44..49 NAME_REF@44..49
IDENT@44..49 "Outer" IDENT@44..49 "Outer"
WHITESPACE@49..50 " " WHITESPACE@49..50 " "
RECORD_FIELD_PAT_LIST@50..81 RECORD_PAT_FIELD_LIST@50..81
L_CURLY@50..51 "{" L_CURLY@50..51 "{"
WHITESPACE@51..52 " " WHITESPACE@51..52 " "
RECORD_FIELD_PAT@52..57 RECORD_PAT_FIELD@52..57
BOX_PAT@52..57 BOX_PAT@52..57
BOX_KW@52..55 "box" BOX_KW@52..55 "box"
WHITESPACE@55..56 " " WHITESPACE@55..56 " "
@ -52,7 +52,7 @@ SOURCE_FILE@0..118
IDENT@56..57 "i" IDENT@56..57 "i"
COMMA@57..58 "," COMMA@57..58 ","
WHITESPACE@58..59 " " WHITESPACE@58..59 " "
RECORD_FIELD_PAT@59..79 RECORD_PAT_FIELD@59..79
NAME_REF@59..60 NAME_REF@59..60
IDENT@59..60 "j" IDENT@59..60 "j"
COLON@60..61 ":" COLON@60..61 ":"

View file

@ -20,10 +20,10 @@ SOURCE_FILE@0..63
NAME_REF@19..20 NAME_REF@19..20
IDENT@19..20 "S" IDENT@19..20 "S"
WHITESPACE@20..21 " " WHITESPACE@20..21 " "
RECORD_FIELD_PAT_LIST@21..29 RECORD_PAT_FIELD_LIST@21..29
L_CURLY@21..22 "{" L_CURLY@21..22 "{"
WHITESPACE@22..23 " " WHITESPACE@22..23 " "
RECORD_FIELD_PAT@23..27 RECORD_PAT_FIELD@23..27
NAME_REF@23..24 NAME_REF@23..24
INT_NUMBER@23..24 "0" INT_NUMBER@23..24 "0"
COLON@24..25 ":" COLON@24..25 ":"
@ -50,10 +50,10 @@ SOURCE_FILE@0..63
NAME_REF@44..45 NAME_REF@44..45
IDENT@44..45 "S" IDENT@44..45 "S"
WHITESPACE@45..46 " " WHITESPACE@45..46 " "
RECORD_FIELD_PAT_LIST@46..54 RECORD_PAT_FIELD_LIST@46..54
L_CURLY@46..47 "{" L_CURLY@46..47 "{"
WHITESPACE@47..48 " " WHITESPACE@47..48 " "
RECORD_FIELD_PAT@48..52 RECORD_PAT_FIELD@48..52
NAME_REF@48..49 NAME_REF@48..49
IDENT@48..49 "x" IDENT@48..49 "x"
COLON@49..50 ":" COLON@49..50 ":"

View file

@ -64,16 +64,16 @@ SOURCE_FILE@0..170
NAME_REF@57..58 NAME_REF@57..58
IDENT@57..58 "S" IDENT@57..58 "S"
WHITESPACE@58..59 " " WHITESPACE@58..59 " "
RECORD_FIELD_PAT_LIST@59..67 RECORD_PAT_FIELD_LIST@59..67
L_CURLY@59..60 "{" L_CURLY@59..60 "{"
WHITESPACE@60..61 " " WHITESPACE@60..61 " "
RECORD_FIELD_PAT@61..62 RECORD_PAT_FIELD@61..62
BIND_PAT@61..62 BIND_PAT@61..62
NAME@61..62 NAME@61..62
IDENT@61..62 "a" IDENT@61..62 "a"
COMMA@62..63 "," COMMA@62..63 ","
WHITESPACE@63..64 " " WHITESPACE@63..64 " "
RECORD_FIELD_PAT@64..65 RECORD_PAT_FIELD@64..65
BIND_PAT@64..65 BIND_PAT@64..65
NAME@64..65 NAME@64..65
IDENT@64..65 "b" IDENT@64..65 "b"

View file

@ -67,16 +67,16 @@ SOURCE_FILE@0..137
NAME_REF@56..57 NAME_REF@56..57
IDENT@56..57 "S" IDENT@56..57 "S"
WHITESPACE@57..58 " " WHITESPACE@57..58 " "
RECORD_FIELD_PAT_LIST@58..66 RECORD_PAT_FIELD_LIST@58..66
L_CURLY@58..59 "{" L_CURLY@58..59 "{"
WHITESPACE@59..60 " " WHITESPACE@59..60 " "
RECORD_FIELD_PAT@60..61 RECORD_PAT_FIELD@60..61
BIND_PAT@60..61 BIND_PAT@60..61
NAME@60..61 NAME@60..61
IDENT@60..61 "a" IDENT@60..61 "a"
COMMA@61..62 "," COMMA@61..62 ","
WHITESPACE@62..63 " " WHITESPACE@62..63 " "
RECORD_FIELD_PAT@63..64 RECORD_PAT_FIELD@63..64
BIND_PAT@63..64 BIND_PAT@63..64
NAME@63..64 NAME@63..64
IDENT@63..64 "b" IDENT@63..64 "b"

View file

@ -131,8 +131,8 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
"DOT_DOT_PAT", "DOT_DOT_PAT",
"PATH_PAT", "PATH_PAT",
"RECORD_PAT", "RECORD_PAT",
"RECORD_FIELD_PAT_LIST", "RECORD_PAT_FIELD_LIST",
"RECORD_FIELD_PAT", "RECORD_PAT_FIELD",
"TUPLE_STRUCT_PAT", "TUPLE_STRUCT_PAT",
"TUPLE_PAT", "TUPLE_PAT",
"SLICE_PAT", "SLICE_PAT",

View file

@ -529,16 +529,15 @@ RefPat =
'&' 'mut'? Pat '&' 'mut'? Pat
RecordPat = RecordPat =
Path RecordFieldPatList Path RecordPatFieldList
RecordFieldPatList = RecordPatFieldList =
'{' '{'
record_field_pats:RecordFieldPat* fields:(RecordPatField (',' RecordPatField)* ','?)
BindPat*
'..'? '..'?
'}' '}'
RecordFieldPat = RecordPatField =
Attr* (NameRef ':')? Pat Attr* (NameRef ':')? Pat
OrPat = OrPat =