diff --git a/src/expr.rs b/src/expr.rs index b5661fed16..cde51cdebb 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1673,7 +1673,12 @@ pub(crate) mod parsing { bracket_token: bracketed!(content in input), index: content.parse()?, }); - } else if input.peek(Token![?]) { + } else if input.peek(Token![?]) + && match e { + Expr::Range(_) => false, + _ => true, + } + { e = Expr::Try(ExprTry { attrs: Vec::new(), expr: Box::new(e), @@ -2867,6 +2872,7 @@ pub(crate) mod parsing { || input.peek(Token![,]) || input.peek(Token![;]) || input.peek(Token![.]) && !input.peek(Token![..]) + || input.peek(Token![?]) || input.peek(Token![=>]) || !allow_struct.0 && input.peek(token::Brace)) { diff --git a/tests/test_expr.rs b/tests/test_expr.rs index 652e66ed96..5783c778b2 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -407,6 +407,77 @@ fn test_range_precedence() { syn::parse_str::("x .. x ..").unwrap_err(); } +#[test] +fn test_ranges_dots_bailout() { + syn::parse_str::(".. ?").unwrap_err(); + syn::parse_str::(".. .field").unwrap_err(); + + snapshot!("return .. ?" as Expr, @r" + Expr::Try { + expr: Expr::Return { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + } + "); + + snapshot!("break .. ?" as Expr, @r" + Expr::Try { + expr: Expr::Break { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + } + "); + + snapshot!("|| .. ?" as Expr, @r" + Expr::Try { + expr: Expr::Closure { + output: ReturnType::Default, + body: Expr::Range { + limits: RangeLimits::HalfOpen, + }, + }, + } + "); + + snapshot!("return .. .field" as Expr, @r#" + Expr::Field { + base: Expr::Return { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + member: Member::Named("field"), + } + "#); + + snapshot!("break .. .field" as Expr, @r#" + Expr::Field { + base: Expr::Break { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + member: Member::Named("field"), + } + "#); + + snapshot!("|| .. .field" as Expr, @r#" + Expr::Field { + base: Expr::Closure { + output: ReturnType::Default, + body: Expr::Range { + limits: RangeLimits::HalfOpen, + }, + }, + member: Member::Named("field"), + } + "#); +} + #[test] fn test_ambiguous_label() { for stmt in [