Skip to content

Commit

Permalink
Fix parsing of labeled loop followed by paren in stmt or match arm po…
Browse files Browse the repository at this point in the history
…sition
  • Loading branch information
dtolnay committed Dec 11, 2023
1 parent 1a77631 commit a78859f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 29 deletions.
47 changes: 27 additions & 20 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1663,31 +1663,36 @@ pub(crate) mod parsing {
} else if input.peek(Token![_]) {
input.parse().map(Expr::Infer)
} else if input.peek(Lifetime) {
let the_label: Label = input.parse()?;
let mut expr = if input.peek(Token![while]) {
Expr::While(input.parse()?)
} else if input.peek(Token![for]) {
Expr::ForLoop(input.parse()?)
} else if input.peek(Token![loop]) {
Expr::Loop(input.parse()?)
} else if input.peek(token::Brace) {
Expr::Block(input.parse()?)
} else {
return Err(input.error("expected loop or block expression"));
};
match &mut expr {
Expr::While(ExprWhile { label, .. })
| Expr::ForLoop(ExprForLoop { label, .. })
| Expr::Loop(ExprLoop { label, .. })
| Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
_ => unreachable!(),
}
Ok(expr)
atom_labeled(input)
} else {
Err(input.error("expected an expression"))
}
}

#[cfg(feature = "full")]
fn atom_labeled(input: ParseStream) -> Result<Expr> {
let the_label: Label = input.parse()?;
let mut expr = if input.peek(Token![while]) {
Expr::While(input.parse()?)
} else if input.peek(Token![for]) {
Expr::ForLoop(input.parse()?)
} else if input.peek(Token![loop]) {
Expr::Loop(input.parse()?)
} else if input.peek(token::Brace) {
Expr::Block(input.parse()?)
} else {
return Err(input.error("expected loop or block expression"));
};
match &mut expr {
Expr::While(ExprWhile { label, .. })
| Expr::ForLoop(ExprForLoop { label, .. })
| Expr::Loop(ExprLoop { label, .. })
| Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
_ => unreachable!(),
}
Ok(expr)
}

#[cfg(not(feature = "full"))]
fn atom_expr(input: ParseStream) -> Result<Expr> {
if input.peek(token::Group)
Expand Down Expand Up @@ -1935,6 +1940,8 @@ pub(crate) mod parsing {
Expr::Const(input.parse()?)
} else if input.peek(token::Brace) {
Expr::Block(input.parse()?)
} else if input.peek(Lifetime) {
atom_labeled(input)?
} else {
let allow_struct = AllowStruct(true);
let mut expr = unary_expr(input, allow_struct)?;
Expand Down
20 changes: 11 additions & 9 deletions tests/test_stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,18 +273,20 @@ fn test_early_parse_loop() {
snapshot!(stmts, @r###"
[
Stmt::Expr(
Expr::Call {
func: Expr::Loop {
label: Some(Label {
name: Lifetime {
ident: "a",
},
}),
body: Block,
},
Expr::Loop {
label: Some(Label {
name: Lifetime {
ident: "a",
},
}),
body: Block,
},
None,
),
Stmt::Expr(
Expr::Tuple,
None,
),
]
"###);
}

0 comments on commit a78859f

Please sign in to comment.