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 80604dc
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 30 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
21 changes: 11 additions & 10 deletions tests/test_stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,22 +269,23 @@ fn test_early_parse_loop() {

let stmts = Block::parse_within.parse2(tokens).unwrap();

// FIXME
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 80604dc

Please sign in to comment.