Skip to content

Commit 20497e1

Browse files
committed
More precise decision to parse expression after return keyword
1 parent c6a651a commit 20497e1

File tree

2 files changed

+28
-15
lines changed

2 files changed

+28
-15
lines changed

src/expr.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,8 @@ pub(crate) fn requires_terminator(expr: &Expr) -> bool {
957957
#[cfg(feature = "parsing")]
958958
pub(crate) mod parsing {
959959
use super::*;
960+
#[cfg(feature = "full")]
961+
use crate::ext::IdentExt;
960962
use crate::parse::discouraged::Speculative;
961963
#[cfg(feature = "full")]
962964
use crate::parse::ParseBuffer;
@@ -1155,6 +1157,25 @@ pub(crate) mod parsing {
11551157
}
11561158
}
11571159

1160+
#[cfg(feature = "full")]
1161+
fn can_begin_expr(input: ParseStream) -> bool {
1162+
input.peek(Ident::peek_any) // value name or keyword
1163+
|| input.peek(token::Paren) // tuple
1164+
|| input.peek(token::Bracket) // array
1165+
|| input.peek(token::Brace) // block
1166+
|| input.peek(Lit) // literal
1167+
|| input.peek(Token![!]) && !input.peek(Token![!=]) // operator not
1168+
|| input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus
1169+
|| input.peek(Token![*]) && !input.peek(Token![*=]) // dereference
1170+
|| input.peek(Token![|]) && !input.peek(Token![|=]) // closure
1171+
|| input.peek(Token![&]) && !input.peek(Token![&=]) // reference
1172+
|| input.peek(Token![..]) // range notation
1173+
|| input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path
1174+
|| input.peek(Token![::]) // global path
1175+
|| input.peek(Lifetime) // labeled loop
1176+
|| input.peek(Token![#]) // expression attributes
1177+
}
1178+
11581179
#[cfg(feature = "full")]
11591180
fn parse_expr(
11601181
input: ParseStream,
@@ -2247,7 +2268,7 @@ pub(crate) mod parsing {
22472268
attrs: Vec::new(),
22482269
yield_token: input.parse()?,
22492270
expr: {
2250-
if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
2271+
if can_begin_expr(input) {
22512272
Some(input.parse()?)
22522273
} else {
22532274
None
@@ -2447,15 +2468,11 @@ pub(crate) mod parsing {
24472468
break_token: input.parse()?,
24482469
label: input.parse()?,
24492470
expr: {
2450-
if input.is_empty()
2451-
|| input.peek(Token![,])
2452-
|| input.peek(Token![;])
2453-
|| !allow_struct.0 && input.peek(token::Brace)
2454-
{
2455-
None
2456-
} else {
2471+
if can_begin_expr(input) && (allow_struct.0 || !input.peek(token::Brace)) {
24572472
let expr = ambiguous_expr(input, allow_struct)?;
24582473
Some(Box::new(expr))
2474+
} else {
2475+
None
24592476
}
24602477
},
24612478
})
@@ -2467,16 +2484,16 @@ pub(crate) mod parsing {
24672484
attrs: Vec::new(),
24682485
return_token: input.parse()?,
24692486
expr: {
2470-
if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2471-
None
2472-
} else {
2487+
if can_begin_expr(input) {
24732488
// NOTE: return is greedy and eats blocks after it even when in a
24742489
// position where structs are not allowed, such as in if statement
24752490
// conditions. For example:
24762491
//
24772492
// if return { println!("A") } {} // Prints "A"
24782493
let expr = ambiguous_expr(input, allow_struct)?;
24792494
Some(Box::new(expr))
2495+
} else {
2496+
None
24802497
}
24812498
},
24822499
})

tests/repo/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,6 @@ static EXCLUDE_FILES: &[&str] = &[
5656
// https://github.com/dtolnay/syn/issues/1527
5757
"tests/ui/parser/struct-literal-in-match-guard.rs",
5858

59-
// TODO: precedence of return in match guard
60-
// https://github.com/dtolnay/syn/issues/1528
61-
"tests/ui/unreachable-code.rs",
62-
6359
// Compile-fail expr parameter in const generic position: f::<1 + 2>()
6460
"tests/ui/const-generics/early/closing-args-token.rs",
6561
"tests/ui/const-generics/early/const-expression-parameter.rs",

0 commit comments

Comments
 (0)