1
Fork 0

Remove a second DiagnosticBuilder::emit_without_consuming call.

Instead of taking `seq` as a mutable reference,
`maybe_recover_struct_lit_bad_delims` now consumes `seq` on the recovery
path, and returns `seq` unchanged on the non-recovery path. The commit
also combines an `if` and a `match` to merge two identical paths.

Also change `recover_seq_parse_error` so it receives a `PErr` instead of
a `PResult`, because all the call sites now handle the `Ok`/`Err`
distinction themselves.
This commit is contained in:
Nicholas Nethercote 2024-01-05 10:42:31 +11:00
parent 1881055000
commit 3ce34f42e1
2 changed files with 30 additions and 39 deletions

View file

@ -35,7 +35,7 @@ use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{ use rustc_errors::{
pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, FatalError, pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, FatalError,
PResult, PErr, PResult,
}; };
use rustc_session::errors::ExprParenthesesNeeded; use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
@ -2044,18 +2044,13 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
delim: Delimiter, delim: Delimiter,
lo: Span, lo: Span,
result: PResult<'a, P<Expr>>, err: PErr<'a>,
) -> P<Expr> { ) -> P<Expr> {
match result {
Ok(x) => x,
Err(err) => {
err.emit(); err.emit();
// Recover from parse error, callers expect the closing delim to be consumed. // Recover from parse error, callers expect the closing delim to be consumed.
self.consume_block(delim, ConsumeClosingDelim::Yes); self.consume_block(delim, ConsumeClosingDelim::Yes);
self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err) self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err)
} }
}
}
/// Eats tokens until we can be relatively sure we reached the end of the /// Eats tokens until we can be relatively sure we reached the end of the
/// statement. This is something of a best-effort heuristic. /// statement. This is something of a best-effort heuristic.

View file

@ -1272,15 +1272,13 @@ impl<'a> Parser<'a> {
}; };
let open_paren = self.token.span; let open_paren = self.token.span;
let mut seq = self let seq = self
.parse_expr_paren_seq() .parse_expr_paren_seq()
.map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args))); .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
if let Some(expr) = match self.maybe_recover_struct_lit_bad_delims(lo, open_paren, seq, snapshot) {
self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot) Ok(expr) => expr,
{ Err(err) => self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err),
return expr;
} }
self.recover_seq_parse_error(Delimiter::Parenthesis, lo, seq)
} }
/// If we encounter a parser state that looks like the user has written a `struct` literal with /// If we encounter a parser state that looks like the user has written a `struct` literal with
@ -1290,14 +1288,11 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
lo: Span, lo: Span,
open_paren: Span, open_paren: Span,
seq: &mut PResult<'a, P<Expr>>, seq: PResult<'a, P<Expr>>,
snapshot: Option<(SnapshotParser<'a>, ExprKind)>, snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
) -> Option<P<Expr>> { ) -> PResult<'a, P<Expr>> {
if !self.may_recover() { match (self.may_recover(), seq, snapshot) {
return None; (true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
}
match (seq.as_mut(), snapshot) {
(Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
snapshot.bump(); // `(` snapshot.bump(); // `(`
match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) { match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) {
Ok((fields, ..)) Ok((fields, ..))
@ -1315,11 +1310,13 @@ impl<'a> Parser<'a> {
if !fields.is_empty() && if !fields.is_empty() &&
// `token.kind` should not be compared here. // `token.kind` should not be compared here.
// This is because the `snapshot.token.kind` is treated as the same as // This is because the `snapshot.token.kind` is treated as the same as
// that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different. // that of the open delim in `TokenTreesReader::parse_token_tree`, even
// if they are different.
self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")") self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")")
{ {
let mut replacement_err = err.cancel();
self.dcx().create_err(errors::ParenthesesWithStructFields { self.dcx()
.create_err(errors::ParenthesesWithStructFields {
span, span,
r#type: path, r#type: path,
braces_for_struct: errors::BracesForStructLiteral { braces_for_struct: errors::BracesForStructLiteral {
@ -1332,23 +1329,22 @@ impl<'a> Parser<'a> {
.map(|field| field.span.until(field.expr.span)) .map(|field| field.span.until(field.expr.span))
.collect(), .collect(),
}, },
}); })
replacement_err.emit_without_consuming(); .emit();
let old_err = mem::replace(err, replacement_err);
old_err.cancel();
} else { } else {
err.emit_without_consuming(); err.emit();
} }
return Some(self.mk_expr_err(span)); Ok(self.mk_expr_err(span))
} }
Ok(_) => {} Ok(_) => Err(err),
Err(err) => err.cancel(), Err(err2) => {
err2.cancel();
Err(err)
} }
} }
_ => {}
} }
None (_, seq, _) => seq,
}
} }
/// Parse an indexing expression `expr[...]`. /// Parse an indexing expression `expr[...]`.
@ -1552,7 +1548,7 @@ impl<'a> Parser<'a> {
) { ) {
Ok(x) => x, Ok(x) => x,
Err(err) => { Err(err) => {
return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, Err(err))); return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err));
} }
}; };
let kind = if es.len() == 1 && !trailing_comma { let kind = if es.len() == 1 && !trailing_comma {