diff options
| author | David Ross <daboross@daboross.net> | 2020-02-08 21:34:38 -0800 |
|---|---|---|
| committer | David Ross <daboross@daboross.net> | 2020-02-15 19:50:50 -0800 |
| commit | 940f65782cc5df7fecad27b38cc25b6d1eeaf2e8 (patch) | |
| tree | efb0a542523c63ed8de3ca72ee26e5abe3b8f4e0 /src/librustc_parse/parser | |
| parent | 8ba3ca0e6bef416ecba3c8ded1f67a953d28600f (diff) | |
| download | rust-940f65782cc5df7fecad27b38cc25b6d1eeaf2e8.tar.gz rust-940f65782cc5df7fecad27b38cc25b6d1eeaf2e8.zip | |
Parse & reject postfix operators after casts
This adds parsing for expressions like 'x as Ty[0]' which will immediately error out, but still give the rest of the parser a valid parse tree to continue.
Diffstat (limited to 'src/librustc_parse/parser')
| -rw-r--r-- | src/librustc_parse/parser/expr.rs | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 20b9df0a2d9..d7d3145770c 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -551,7 +551,7 @@ impl<'a> Parser<'a> { // Save the state of the parser before parsing type normally, in case there is a // LessThan comparison after this cast. let parser_snapshot_before_type = self.clone(); - match self.parse_ty_no_plus() { + let type_result = match self.parse_ty_no_plus() { Ok(rhs) => Ok(mk_expr(self, rhs)), Err(mut type_err) => { // Rewind to before attempting to parse the type with generics, to recover @@ -616,7 +616,44 @@ impl<'a> Parser<'a> { } } } - } + }; + + // Disallow postfix operators such as `.`, `?` or index (`[]`) after casts. + // Parses the postfix operator and emits an error. + let expr = type_result?; + let span = expr.span; + + // The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. + let with_postfix = self.parse_dot_or_call_expr_with_(expr, span)?; + if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) { + let expr_str = self.span_to_snippet(span); + + let msg = format!( + "casts followed by {} are not supported", + match with_postfix.kind { + ExprKind::Index(_, _) => "index operators", + ExprKind::Try(_) => "try operators", + ExprKind::Field(_, _) => "field access expressions", + ExprKind::MethodCall(_, _) => "method call expressions", + ExprKind::Await(_) => "awaits", + _ => "expressions", + } + ); + let mut err = self.struct_span_err(with_postfix.span, &msg); + let suggestion = "try surrounding the expression with parentheses"; + if let Ok(expr_str) = expr_str { + err.span_suggestion( + span, + suggestion, + format!("({})", expr_str), + Applicability::MachineApplicable, + ) + } else { + err.span_help(span, suggestion) + } + .emit(); + }; + Ok(with_postfix) } fn parse_assoc_op_ascribe(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a, P<Expr>> { |
