diff --git a/src/expr.rs b/src/expr.rs index 78f735997a..b04450ff2d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1365,6 +1365,7 @@ pub(crate) mod parsing { } else if Precedence::Cast >= base && input.peek(Token![as]) { let as_token: Token![as] = input.parse()?; let ty = input.call(Type::without_plus)?; + check_cast(input)?; lhs = Expr::Cast(ExprCast { attrs: Vec::new(), expr: Box::new(lhs), @@ -1374,6 +1375,7 @@ pub(crate) mod parsing { } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) { let colon_token: Token![:] = input.parse()?; let ty = input.call(Type::without_plus)?; + check_cast(input)?; lhs = Expr::Type(ExprType { attrs: Vec::new(), expr: Box::new(lhs), @@ -1421,6 +1423,7 @@ pub(crate) mod parsing { } else if Precedence::Cast >= base && input.peek(Token![as]) { let as_token: Token![as] = input.parse()?; let ty = input.call(Type::without_plus)?; + check_cast(input)?; lhs = Expr::Cast(ExprCast { attrs: Vec::new(), expr: Box::new(lhs), @@ -2896,6 +2899,28 @@ pub(crate) mod parsing { } } } + + fn check_cast(input: ParseStream) -> Result<()> { + let kind = if input.peek(Token![.]) && !input.peek(Token![..]) { + if input.peek2(token::Await) { + "`.await`" + } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) { + "a method call" + } else { + "a field access" + } + } else if input.peek(Token![?]) { + "`?`" + } else if input.peek(token::Bracket) { + "indexing" + } else if input.peek(token::Paren) { + "a function call" + } else { + return Ok(()); + }; + let msg = format!("casts cannot be followed by {}", kind); + Err(input.error(msg)) + } } #[cfg(feature = "printing")] diff --git a/tests/test_expr.rs b/tests/test_expr.rs index 8c1cc73a96..8fd911e2ad 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -318,3 +318,9 @@ fn test_closure_vs_rangefull() { } "###); } + +#[test] +fn test_postfix_operator_after_cast() { + syn::parse_str::("|| &x as T[0]").unwrap_err(); + syn::parse_str::("|| () as ()()").unwrap_err(); +}