Skip to content
Draft
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
55 changes: 25 additions & 30 deletions crates/hir-def/src/macro_expansion_tests/mbe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1558,7 +1558,7 @@ macro_rules !matches {
}
fn main() {
/* error: unexpected token in input *//* parse error: expected expression */
/* parse error: expected FAT_ARROW */
/* parse error: expected `=>` */
/* parse error: expected `,` */
/* parse error: expected pattern */
match 0 {
Expand Down Expand Up @@ -1737,9 +1737,6 @@ macro_rules! m {
($k:expr) => { fn f() { K::$k; } }
}
/* parse error: expected identifier, `self`, `super`, `crate`, or `Self` */
/* parse error: expected SEMICOLON */
/* parse error: expected SEMICOLON */
/* parse error: expected expression, item or let statement */
fn f() {
K::(C("0"));
}
Expand All @@ -1754,32 +1751,30 @@ fn f() {
// BLOCK_EXPR@5..19
// STMT_LIST@5..19
// L_CURLY@5..6 "{"
// EXPR_STMT@6..10
// PATH_EXPR@6..10
// PATH@6..10
// PATH@6..7
// PATH_SEGMENT@6..7
// NAME_REF@6..7
// IDENT@6..7 "K"
// COLON2@7..9 "::"
// PATH_SEGMENT@9..10
// ERROR@9..10
// L_PAREN@9..10 "("
// EXPR_STMT@10..16
// CALL_EXPR@10..16
// PATH_EXPR@10..11
// PATH@10..11
// PATH_SEGMENT@10..11
// NAME_REF@10..11
// IDENT@10..11 "C"
// ARG_LIST@11..16
// L_PAREN@11..12 "("
// LITERAL@12..15
// STRING@12..15 "\"0\""
// R_PAREN@15..16 ")"
// ERROR@16..17
// R_PAREN@16..17 ")"
// SEMICOLON@17..18 ";"
// EXPR_STMT@6..18
// CALL_EXPR@6..17
// PATH_EXPR@6..9
// PATH@6..9
// PATH@6..7
// PATH_SEGMENT@6..7
// NAME_REF@6..7
// IDENT@6..7 "K"
// COLON2@7..9 "::"
// ARG_LIST@9..17
// L_PAREN@9..10 "("
// CALL_EXPR@10..16
// PATH_EXPR@10..11
// PATH@10..11
// PATH_SEGMENT@10..11
// NAME_REF@10..11
// IDENT@10..11 "C"
// ARG_LIST@11..16
// L_PAREN@11..12 "("
// LITERAL@12..15
// STRING@12..15 "\"0\""
// R_PAREN@15..16 ")"
// R_PAREN@16..17 ")"
// SEMICOLON@17..18 ";"
// R_CURLY@18..19 "}"

"#]],
Expand Down
22 changes: 11 additions & 11 deletions crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ fn main() {
(<[_]>::into_vec(#[rustc_box] crate ::boxed::Box::new([1u32, 2])));
/* error: expected Expr *//* parse error: expected field name or number */
/* parse error: expected expression */
/* parse error: expected R_PAREN */
/* parse error: expected COMMA */
/* parse error: expected `)` */
/* parse error: expected `,` */
/* parse error: expected expression, item or let statement */
(crate ::vec::from_elem((a.), $n));
}
Expand Down Expand Up @@ -921,12 +921,12 @@ macro_rules! rgb_color {
};
}
/* parse error: expected type */
/* parse error: expected R_PAREN */
/* parse error: expected R_ANGLE */
/* parse error: expected `)` */
/* parse error: expected `>` */
/* parse error: expected `::` */
/* parse error: expected COMMA */
/* parse error: expected R_ANGLE */
/* parse error: expected SEMICOLON */
/* parse error: expected `>` */
/* parse error: expected `;` */
/* parse error: expected expression, item or let statement */
pub fn new() {
let _ = 0 as u32<<(8+8);
Expand Down Expand Up @@ -1053,12 +1053,12 @@ fn main() {
macro_rules! format_args {}

fn main() {
/* parse error: expected COMMA */
/* parse error: expected R_BRACK */
/* parse error: expected COMMA */
/* parse error: expected COMMA */
/* parse error: expected `,` */
/* parse error: expected `]` */
/* parse error: expected `,` */
/* parse error: expected `,` */
/* parse error: expected expression */
/* parse error: expected R_PAREN */
/* parse error: expected `)` */
/* parse error: expected expression, item or let statement */
/* parse error: expected expression, item or let statement */
builtin #format_args ("{}", &[0 2]);
Expand Down
3 changes: 1 addition & 2 deletions crates/hir-expand/src/fixup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,6 @@ fn foo () {for bar in qux {}}
)
}

// FIXME: https://github.com/rust-lang/rust-analyzer/pull/12937#discussion_r937633695
#[test]
fn for_no_pat() {
check(
Expand All @@ -555,7 +554,7 @@ fn foo() {
}
"#,
expect![[r#"
fn foo () {__ra_fixup}
fn foo () {for _ in qux {}}
"#]],
)
}
Expand Down
6 changes: 5 additions & 1 deletion crates/ide-completion/src/tests/special.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,11 +1197,15 @@ fn foo { crate:::$0 }
"#,
expect![""],
);
// expected, as recovery reconsiders this as the start of a new path
check_no_kw(
r#"
fn foo { crate::::$0 }
"#,
expect![""],
expect![[r#"
fn foo() fn()
bt u32 u32
"#]],
)
}

Expand Down
2 changes: 1 addition & 1 deletion crates/parser/src/grammar/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod atom;

use super::*;

pub(super) use atom::{EXPR_RECOVERY_SET, LITERAL_FIRST, literal, parse_asm_expr};
pub(super) use atom::{ATOM_EXPR_FIRST, EXPR_RECOVERY_SET, LITERAL_FIRST, literal, parse_asm_expr};
pub(crate) use atom::{block_expr, match_arm_list};

#[derive(PartialEq, Eq)]
Expand Down
19 changes: 15 additions & 4 deletions crates/parser/src/grammar/expressions/atom.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::grammar::types::type_;
use crate::grammar::{patterns::PAT_RECOVERY_SET, types::type_};

use super::*;

Expand Down Expand Up @@ -39,7 +39,7 @@ pub(crate) fn literal(p: &mut Parser<'_>) -> Option<CompletedMarker> {
}

// E.g. for after the break in `if break {}`, this should not match
pub(super) const ATOM_EXPR_FIRST: TokenSet =
pub(in crate::grammar) const ATOM_EXPR_FIRST: TokenSet =
LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[
T!['('],
T!['{'],
Expand Down Expand Up @@ -68,7 +68,9 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
]));

pub(in crate::grammar) const EXPR_RECOVERY_SET: TokenSet =
TokenSet::new(&[T!['}'], T![')'], T![']'], T![,]]);
TokenSet::new(&[T!['}'], T![')'], T![']'], T![,], T![;]])
.union(items::ITEM_RECOVERY_SET)
.union(ATOM_EXPR_FIRST);

pub(super) fn atom_expr(
p: &mut Parser<'_>,
Expand Down Expand Up @@ -750,6 +752,7 @@ fn match_expr(p: &mut Parser<'_>) -> CompletedMarker {
// if true => (),
// _ => (),
// () if => (),
// _ => foo!();
// }
// }
pub(crate) fn match_arm_list(p: &mut Parser<'_>) {
Expand Down Expand Up @@ -810,7 +813,15 @@ fn match_arm(p: &mut Parser<'_>) {
// }
attributes::outer_attrs(p);

patterns::pattern_top_r(p, TokenSet::new(&[T![=], T![if]]));
// test_err match_arm_guard_recovery
// fn foo() {
// match () {
// => (),
// if true => (),
// A A => (),
// };
// }
patterns::pattern_top_r(p, const { PAT_RECOVERY_SET.union(TokenSet::new(&[T![=], T![if]])) });
if p.at(T![if]) {
match_guard(p);
}
Expand Down
4 changes: 3 additions & 1 deletion crates/parser/src/grammar/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ pub(super) fn mod_contents(p: &mut Parser<'_>, stop_on_r_curly: bool) {
pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[
T![fn],
T![struct],
T![union],
T![enum],
T![impl],
T![trait],
T![type],
T![const],
T![async],
T![unsafe],
Expand All @@ -42,7 +44,7 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[
T![crate],
T![use],
T![macro],
T![;],
T![#],
]);

pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool, is_in_extern: bool) {
Expand Down
12 changes: 9 additions & 3 deletions crates/parser/src/grammar/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) {
}
};

if !p.at_ts(PARAM_FIRST.union(ATTRIBUTE_FIRST)) {
if !p.at_ts(param_first(flavor)) {
p.error("expected value parameter");
m.abandon(p);
if p.eat(T![,]) {
Expand All @@ -74,7 +74,7 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) {
}
param(p, m, flavor);
if !p.eat(T![,]) {
if p.at_ts(PARAM_FIRST.union(ATTRIBUTE_FIRST)) {
if p.at_ts(param_first(flavor)) {
p.error("expected `,`");
} else {
break;
Expand All @@ -90,7 +90,13 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) {
list_marker.complete(p, PARAM_LIST);
}

const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
const fn param_first(flavor: Flavor) -> TokenSet {
match flavor {
Flavor::FnDef | Flavor::Closure => patterns::PATTERN_FIRST,
Flavor::FnPointer => patterns::PATTERN_FIRST.union(types::TYPE_FIRST),
}
.union(ATTRIBUTE_FIRST)
}

fn param(p: &mut Parser<'_>, m: Marker, flavor: Flavor) {
match flavor {
Expand Down
3 changes: 1 addition & 2 deletions crates/parser/src/grammar/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ fn path_for_qualifier(
}
}

const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet =
expressions::EXPR_RECOVERY_SET.union(items::ITEM_RECOVERY_SET);
const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet = expressions::EXPR_RECOVERY_SET;
const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET;

fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<CompletedMarker> {
Expand Down
37 changes: 17 additions & 20 deletions crates/parser/src/grammar/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ const PAT_TOP_FIRST: TokenSet = PATTERN_FIRST.union(TokenSet::new(&[T![|]]));
const RANGE_PAT_END_FIRST: TokenSet =
expressions::LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[T![-], T![const]]));

pub(crate) const PAT_RECOVERY_SET: TokenSet =
TokenSet::new(&[T![')'], T![']'], T!['}'], T![,], T![=], T![:], T![in]])
// Useful when people start out typing a new `let pat` in front of a statement
.union(items::ITEM_RECOVERY_SET)
.union(expressions::ATOM_EXPR_FIRST);

/// Parses a pattern list separated by pipes `|`.
pub(crate) fn pattern(p: &mut Parser<'_>) {
pattern_r(p, PAT_RECOVERY_SET);
Expand Down Expand Up @@ -64,6 +70,11 @@ fn pattern_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
}

fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
if !p.at_ts(PATTERN_FIRST) {
p.err_recover("expected pattern", recovery_set);
return;
}

// test range_pat
// fn main() {
// match 92 {
Expand Down Expand Up @@ -102,7 +113,7 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
if p.at(T![..=]) {
let m = p.start();
p.bump(T![..=]);
atom_pat(p, recovery_set);
atom_pat(p);
m.complete(p, RANGE_PAT);
return;
}
Expand Down Expand Up @@ -145,15 +156,15 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
let m = p.start();
p.bump(T![..]);
if p.at_ts(RANGE_PAT_END_FIRST) {
atom_pat(p, recovery_set);
atom_pat(p);
m.complete(p, RANGE_PAT);
} else {
m.complete(p, REST_PAT);
}
return;
}

if let Some(lhs) = atom_pat(p, recovery_set) {
if let Some(lhs) = atom_pat(p) {
for range_op in [T![...], T![..=], T![..]] {
if p.at(range_op) {
let m = lhs.precede(p);
Expand Down Expand Up @@ -191,7 +202,7 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
// }
// }
} else {
atom_pat(p, recovery_set);
atom_pat(p);
}
m.complete(p, RANGE_PAT);
return;
Expand All @@ -217,21 +228,7 @@ fn builtin_pat(p: &mut Parser<'_>) -> Option<CompletedMarker> {
}
}

const PAT_RECOVERY_SET: TokenSet = TokenSet::new(&[
T![let],
T![if],
T![while],
T![loop],
T![match],
T![')'],
T![']'],
T!['}'],
T![,],
T![=],
T![&],
]);

fn atom_pat(p: &mut Parser<'_>, recovery_set: TokenSet) -> Option<CompletedMarker> {
fn atom_pat(p: &mut Parser<'_>) -> Option<CompletedMarker> {
if p.at_contextual_kw(T![builtin]) && p.nth_at(1, T![#]) {
return builtin_pat(p);
}
Expand Down Expand Up @@ -260,7 +257,7 @@ fn atom_pat(p: &mut Parser<'_>, recovery_set: TokenSet) -> Option<CompletedMarke
T![!] => not_null_pat(p),

_ => {
p.err_recover("expected pattern", recovery_set);
p.err_and_bump("expected pattern");
return None;
}
};
Expand Down
Loading
Loading