Skip to content

Commit fbd9809

Browse files
authored
Merge pull request dtolnay#1539 from dtolnay/labeledloop
Fix parsing of labeled loop followed by paren in stmt or match arm position
2 parents 78f8f79 + 80604dc commit fbd9809

File tree

2 files changed

+83
-21
lines changed

2 files changed

+83
-21
lines changed

src/expr.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,31 +1663,36 @@ pub(crate) mod parsing {
16631663
} else if input.peek(Token![_]) {
16641664
input.parse().map(Expr::Infer)
16651665
} else if input.peek(Lifetime) {
1666-
let the_label: Label = input.parse()?;
1667-
let mut expr = if input.peek(Token![while]) {
1668-
Expr::While(input.parse()?)
1669-
} else if input.peek(Token![for]) {
1670-
Expr::ForLoop(input.parse()?)
1671-
} else if input.peek(Token![loop]) {
1672-
Expr::Loop(input.parse()?)
1673-
} else if input.peek(token::Brace) {
1674-
Expr::Block(input.parse()?)
1675-
} else {
1676-
return Err(input.error("expected loop or block expression"));
1677-
};
1678-
match &mut expr {
1679-
Expr::While(ExprWhile { label, .. })
1680-
| Expr::ForLoop(ExprForLoop { label, .. })
1681-
| Expr::Loop(ExprLoop { label, .. })
1682-
| Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1683-
_ => unreachable!(),
1684-
}
1685-
Ok(expr)
1666+
atom_labeled(input)
16861667
} else {
16871668
Err(input.error("expected an expression"))
16881669
}
16891670
}
16901671

1672+
#[cfg(feature = "full")]
1673+
fn atom_labeled(input: ParseStream) -> Result<Expr> {
1674+
let the_label: Label = input.parse()?;
1675+
let mut expr = if input.peek(Token![while]) {
1676+
Expr::While(input.parse()?)
1677+
} else if input.peek(Token![for]) {
1678+
Expr::ForLoop(input.parse()?)
1679+
} else if input.peek(Token![loop]) {
1680+
Expr::Loop(input.parse()?)
1681+
} else if input.peek(token::Brace) {
1682+
Expr::Block(input.parse()?)
1683+
} else {
1684+
return Err(input.error("expected loop or block expression"));
1685+
};
1686+
match &mut expr {
1687+
Expr::While(ExprWhile { label, .. })
1688+
| Expr::ForLoop(ExprForLoop { label, .. })
1689+
| Expr::Loop(ExprLoop { label, .. })
1690+
| Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1691+
_ => unreachable!(),
1692+
}
1693+
Ok(expr)
1694+
}
1695+
16911696
#[cfg(not(feature = "full"))]
16921697
fn atom_expr(input: ParseStream) -> Result<Expr> {
16931698
if input.peek(token::Group)
@@ -1935,6 +1940,8 @@ pub(crate) mod parsing {
19351940
Expr::Const(input.parse()?)
19361941
} else if input.peek(token::Brace) {
19371942
Expr::Block(input.parse()?)
1943+
} else if input.peek(Lifetime) {
1944+
atom_labeled(input)?
19381945
} else {
19391946
let allow_struct = AllowStruct(true);
19401947
let mut expr = unary_expr(input, allow_struct)?;

tests/test_stmt.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ mod macros;
99

1010
use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
1111
use quote::quote;
12-
use syn::Stmt;
12+
use syn::parse::Parser as _;
13+
use syn::{Block, Stmt};
1314

1415
#[test]
1516
fn test_raw_operator() {
@@ -234,3 +235,57 @@ fn test_macros() {
234235
})
235236
"###);
236237
}
238+
239+
#[test]
240+
fn test_early_parse_loop() {
241+
// The following is an Expr::Loop followed by Expr::Tuple. It is not an
242+
// Expr::Call.
243+
let tokens = quote! {
244+
loop {}
245+
()
246+
};
247+
248+
let stmts = Block::parse_within.parse2(tokens).unwrap();
249+
250+
snapshot!(stmts, @r###"
251+
[
252+
Stmt::Expr(
253+
Expr::Loop {
254+
body: Block,
255+
},
256+
None,
257+
),
258+
Stmt::Expr(
259+
Expr::Tuple,
260+
None,
261+
),
262+
]
263+
"###);
264+
265+
let tokens = quote! {
266+
'a: loop {}
267+
()
268+
};
269+
270+
let stmts = Block::parse_within.parse2(tokens).unwrap();
271+
272+
snapshot!(stmts, @r###"
273+
[
274+
Stmt::Expr(
275+
Expr::Loop {
276+
label: Some(Label {
277+
name: Lifetime {
278+
ident: "a",
279+
},
280+
}),
281+
body: Block,
282+
},
283+
None,
284+
),
285+
Stmt::Expr(
286+
Expr::Tuple,
287+
None,
288+
),
289+
]
290+
"###);
291+
}

0 commit comments

Comments
 (0)