Change:
) .emit(); <del> Ok(expr) </del> <ins> expr </ins> } Err(mut path_err) => { // Couldn't parse as a path, return original error and parser state. path_err.cancel(); mem::replace(self, parser_snapshot_after_type); <del> Err(type_err) </del> <ins> return Err(type_err); </ins> } } } <del> } </del> <ins> }; self.parse_and_disallow_postfix_after_cast(cast_expr) } /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast, /// then emits an error and returns the newly parsed tree. /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. fn parse_and_disallow_postfix_after_cast( &mut self, cast_expr: P<Expr>, ) -> PResult<'a, P<Expr>> { use std::collections::hash_map::DefaultHasher; use std::hash::Hasher; // Hash the memory location of expr before parsing any following postfix operators. // This will be compared with the hash of the output expression. // If they different we can assume we parsed another expression because the existing expression is not reallocated. let mut before_hasher = DefaultHasher::new(); std::ptr::hash(&*cast_expr, &mut before_hasher); let before_hash = before_hasher.finish(); let span = cast_expr.span; let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?; let mut after_hasher = DefaultHasher::new(); std::ptr::hash(&*with_postfix, &mut after_hasher); let after_hash = after_hasher.finish(); // Check if an illegal postfix operator has been added after the cast. // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || after_hash != before_hash { let expr_str = self.span_to_snippet(span); let msg = format!( "casts cannot be followed by {}", match with_postfix.kind { ExprKind::Index(_, _) => "indexing", ExprKind::Try(_) => "?", ExprKind::Field(_, _) => "a field access", ExprKind::MethodCall(_, _) => "a method call", ExprKind::Call(_, _) => "a function call", ExprKind::Await(_) => "`.await`", _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"), } ); let mut err = self.struct_span_err(span, &msg); let suggestion = "try surrounding the expression in parentheses"; // if type ascription is "likely an error", the user will already be getting a useful // help message, and doesn't need a second. if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) { self.maybe_annotate_with_ascription(&mut err, false); } else { if let Ok(expr_str) = expr_str { err.span_suggestion( span, suggestion, format!("({})", expr_str), Applicability::MachineApplicable, ); } else { err.span_help(span, suggestion); } } err.emit(); }; Ok(with_postfix) </ins> } fn parse_assoc_op_ascribe(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a, P<Expr>> {

Discussion:
Summary: Parsing leads to the error: It is currently impossible for a cast expression to have a trailing index expression without surrounding the cast expression by parenthesis. This however seems to be a parser limitation, not a grammar limitation. As currently the macro language guarantees that ty/path expressions can be followed by a "[", this seems like a bug in the parser to me, as it seems to be parsing it as which makes no grammatical sense, compared to parsing it as (value as Type)[index] which should be valid if I read the lexical structure specification correctly.
I think it's parsed correctly, but should get a tailored error message to suggest surrounding the cast with parens.
Considering that a trailing "[" is never valid in the type syntax (otherwise macros break) and the fact that and variants are perfectly legal (even which is another symbol that occurs in type syntax). But if a tailored error message will be made instead, then this should also include other postfix operators like which are currently rejected even though technically being legal by the lexical grammar specification. (another one is the proposed "?" operator)
This is still lacking a tailored error message, and as far as I know no movement has been made here.
Submitted a pull request to fix this!
Thanks!