Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/lib/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,8 +720,6 @@ impl<'src> super::Parser<'_, '_, 'src> {
self.validate_numeric_ident(binder, ExpInNumIdentPolicy::Reject);
}

// NB: Shorthand numeric fields are not permitted
// in struct exprs contrary to struct pats.
let body = if self.consume_or_parse(TokenKind::SingleColon, !numeric)? {
Some(self.parse_expr()?)
} else {
Expand Down
35 changes: 25 additions & 10 deletions src/lib/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,26 +293,32 @@ impl<'src> super::Parser<'_, '_, 'src> {

let attrs = self.parse_attrs(ast::AttrStyle::Outer)?;

let box_ = if let span = self.token.span
let boxed = if let span = self.token.span
&& self.consume(TokenKind::Box)
{
self.feature(Feature::box_patterns, span);
true
Boxed::Yes
} else {
false
Boxed::No
};
let (mut_, by_ref) = self.parse_mut_by_ref();

// NB: Shorthand numeric fields are permitted
// in struct pats contrary to struct exprs.
let (binder, numeric) = self.parse_common_ident_or(TokenKind::NumLit)?;
let unmarked = matches!(
(boxed, mut_, by_ref),
(Boxed::No, ast::Mut::No, ast::ByRef::No)
);

let (binder, numeric) = if unmarked {
self.parse_common_ident_or(TokenKind::NumLit)?
} else {
(self.parse_common_ident()?, false)
};
if numeric {
self.validate_numeric_ident(binder, ExpInNumIdentPolicy::Reject);
}

let (binder, body) = if let (false, ast::Mut::No, ast::ByRef::No) =
(box_, mut_, by_ref)
&& self.consume(TokenKind::SingleColon)
let (binder, body) = if unmarked
&& self.consume_or_parse(TokenKind::SingleColon, !numeric)?
{
let body = self.parse_pat_where(
OrPolicy::Parse,
Expand All @@ -327,7 +333,10 @@ impl<'src> super::Parser<'_, '_, 'src> {
binder,
pat: None,
}));
let body = if box_ { ast::Pat::Box(Box::new(body)) } else { body };
let body = match boxed {
Boxed::Yes => ast::Pat::Box(Box::new(body)),
Boxed::No => body,
};

(None, body)
};
Expand All @@ -337,6 +346,12 @@ impl<'src> super::Parser<'_, '_, 'src> {
if self.token.kind != DELIMITER {
self.parse(SEPARATOR)?;
}

#[derive(Clone, Copy)]
enum Boxed {
Yes,
No,
}
}

return Ok(ast::Pat::Struct(Box::new(ast::StructPat { path, fields, rest })));
Expand Down
4 changes: 2 additions & 2 deletions src/lib/parser/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,9 @@ fn parse_via<'src, T>(
Ok(node.unwrap())
}

macro t($parse:ident, $edition:ident, $source:literal, $ast:pat $(,)?) {
macro t($parse:ident, $edition:ident, $source:expr, $ast:pat $(if $guard:expr)? $(,)?) {
match $parse(normalize($source).as_ref(), $edition) {
$ast => {}
$ast $(if $guard)? => {}
ast => panic!("{:?}: {} != {:#?}", $source, stringify!($ast), ast),
}
}
Expand Down
96 changes: 25 additions & 71 deletions src/lib/parser/test/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,77 +363,31 @@ use {self::*, self::{}};
);

// Make sure that we don't consider these weak / context-dependent keywords as item modifiers:
t!(
parse_stmt,
Rust2015,
"auto as _",
Ok(ast::Stmt::Expr(
ast::Expr {
kind: ast::ExprKind::Cast(
r!(ast::Expr {
kind: ast::ExprKind::Path(r!(ast::ExtPath {
ext: None,
path: ast::Path {
segs: [ast::PathSeg { ident: ast::Ident!("auto"), .. }]
}
})),
..
}),
_
),
..
},
_
))
);

t!(
parse_stmt,
Rust2015,
"default as _",
Ok(ast::Stmt::Expr(
ast::Expr {
kind: ast::ExprKind::Cast(
r!(ast::Expr {
kind: ast::ExprKind::Path(r!(ast::ExtPath {
ext: None,
path: ast::Path {
segs: [ast::PathSeg { ident: ast::Ident!("default"), .. }]
}
})),
..
}),
_
),
..
},
_
))
);

t!(
parse_stmt,
Rust2015,
"safe as _",
Ok(ast::Stmt::Expr(
ast::Expr {
kind: ast::ExprKind::Cast(
r!(ast::Expr {
kind: ast::ExprKind::Path(r!(ast::ExtPath {
ext: None,
path: ast::Path {
segs: [ast::PathSeg { ident: ast::Ident!("safe"), .. }]
}
})),
..
}),
_
),
..
},
_
))
);
for weak in ["auto", "default", "safe"] {
t!(
parse_stmt,
Rust2015,
&format!("{weak} as _"),
Ok(ast::Stmt::Expr(
ast::Expr {
kind: ast::ExprKind::Cast(
r!(ast::Expr {
kind: ast::ExprKind::Path(r!(ast::ExtPath {
ext: None,
path: ast::Path {
segs: [ast::PathSeg { ident: ast::Ident!(name), .. }]
}
})),
..
}),
_
),
..
},
_
)) if name == weak
);
}
}

#[test]
Expand Down
69 changes: 62 additions & 7 deletions src/lib/parser/test/num_lit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn suffixes_invalid_places() {
"Compound { 0suffix: 0 }",
Err(r!([Error::UnexpectedToken(
Token { kind: TokenKind::LitSuffix, .. },
r!([Fragment::Token(TokenKind::Comma)]),
r!([Fragment::Token(TokenKind::SingleColon)]),
)]))
);

Expand All @@ -66,7 +66,7 @@ fn suffixes_invalid_places() {
"Compound { 0suffix }",
Err(r!([Error::UnexpectedToken(
Token { kind: TokenKind::LitSuffix, .. },
r!([Fragment::Token(TokenKind::Comma)]),
r!([Fragment::Token(TokenKind::SingleColon)]),
)]))
);
}
Expand Down Expand Up @@ -168,9 +168,42 @@ fn exponents_invalid_places() {
t!(parse_expr, Rust2015, "Compound { 0e-1: 0 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(parse_pat, Rust2015, "Compound { 0e1: 0 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(parse_pat, Rust2015, "Compound { 0e+1: 0 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(parse_pat, Rust2015, "Compound { 0e1 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(parse_pat, Rust2015, "Compound { 0e+1 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(parse_pat, Rust2015, "Compound { 0e-1 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(
parse_pat,
Rust2015,
"Compound { 0e1 }",
Err(r!([
Error::InvalidNumericIdent(_),
Error::UnexpectedToken(
Token { kind: TokenKind::CloseCurlyBracket, .. },
[Fragment::Token(TokenKind::SingleColon)]
)
]))
);
t!(
parse_pat,
Rust2015,
"Compound { 0e+1 }",
Err(r!([
Error::InvalidNumericIdent(_),
Error::UnexpectedToken(
Token { kind: TokenKind::CloseCurlyBracket, .. },
[Fragment::Token(TokenKind::SingleColon)]
)
]))
);
t!(
parse_pat,
Rust2015,
"Compound { 0e-1 }",
Err(r!([
Error::InvalidNumericIdent(_),
Error::UnexpectedToken(
Token { kind: TokenKind::CloseCurlyBracket, .. },
[Fragment::Token(TokenKind::SingleColon)]
)
]))
);
}

#[test]
Expand All @@ -183,6 +216,28 @@ fn fractional_part_invalid_places() {
t!(parse_expr, Rust2015, "Compound { 0.: 0 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(parse_pat, Rust2015, "Compound { 0.0: 0 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(parse_pat, Rust2015, "Compound { 0.: 0 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(parse_pat, Rust2015, "Compound { 0.0 }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(parse_pat, Rust2015, "Compound { 0. }", Err(r!([Error::InvalidNumericIdent(_)])));
t!(
parse_pat,
Rust2015,
"Compound { 0.0 }",
Err(r!([
Error::InvalidNumericIdent(_),
Error::UnexpectedToken(
Token { kind: TokenKind::CloseCurlyBracket, .. },
[Fragment::Token(TokenKind::SingleColon)]
)
]))
);
t!(
parse_pat,
Rust2015,
"Compound { 0. }",
Err(r!([
Error::InvalidNumericIdent(_),
Error::UnexpectedToken(
Token { kind: TokenKind::CloseCurlyBracket, .. },
[Fragment::Token(TokenKind::SingleColon)]
)
]))
);
}
Loading