diff --git a/src/expr.rs b/src/expr.rs index 334caada90..57b38150de 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1915,7 +1915,15 @@ pub(crate) mod parsing { #[cfg(feature = "full")] pub(crate) fn expr_early(input: ParseStream) -> Result { let mut attrs = input.call(expr_attrs)?; - let mut expr = if input.peek(Token![if]) { + let mut expr = if input.peek(token::Group) { + let allow_struct = AllowStruct(true); + let atom = expr_group(input, allow_struct)?; + if continue_parsing_early(&atom) { + trailer_helper(input, atom)? + } else { + atom + } + } else if input.peek(Token![if]) { Expr::If(input.parse()?) } else if input.peek(Token![while]) { Expr::While(input.parse()?) @@ -1939,13 +1947,16 @@ pub(crate) mod parsing { atom_labeled(input)? } else { let allow_struct = AllowStruct(true); - let mut expr = unary_expr(input, allow_struct)?; + unary_expr(input, allow_struct)? + }; + if continue_parsing_early(&expr) { attrs.extend(expr.replace_attrs(Vec::new())); expr.replace_attrs(attrs); + let allow_struct = AllowStruct(true); return parse_expr(input, expr, allow_struct, Precedence::Any); - }; + } if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) { expr = trailer_helper(input, expr)?; @@ -1962,6 +1973,25 @@ pub(crate) mod parsing { Ok(expr) } + #[cfg(feature = "full")] + fn continue_parsing_early(mut expr: &Expr) -> bool { + while let Expr::Group(group) = expr { + expr = &group.expr; + } + match expr { + Expr::If(_) + | Expr::While(_) + | Expr::ForLoop(_) + | Expr::Loop(_) + | Expr::Match(_) + | Expr::TryBlock(_) + | Expr::Unsafe(_) + | Expr::Const(_) + | Expr::Block(_) => false, + _ => true, + } + } + #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] impl Parse for ExprLit { fn parse(input: ParseStream) -> Result { diff --git a/tests/test_expr.rs b/tests/test_expr.rs index 1d63f8b6f9..449b83bf53 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -272,7 +272,6 @@ fn test_macro_variable_match_arm() { let expr = Group::new(Delimiter::None, quote!(loop {} + 1)); let tokens = quote!(match v { _ => #expr }); - // FIXME snapshot!(tokens as Expr, @r###" Expr::Match { expr: Expr::Path {