Rollup merge of #97587 - pvdrz:maybe-recover-from-bad-qpath-stage-2, r=davidtwco

Migrate more diagnostics to use the `#[derive(SessionDiagnostic)]`

r? ``@davidtwco``
This commit is contained in:
Dylan DPC 2022-06-02 11:13:24 +02:00 committed by GitHub
commit 19dc28c23e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 95 additions and 44 deletions

View File

@ -14,3 +14,21 @@ parser-add-paren = try adding parentheses
parser-forgot-paren = perhaps you forgot parentheses? parser-forgot-paren = perhaps you forgot parentheses?
parser-expect-path = expected a path parser-expect-path = expected a path
parser-maybe-recover-from-bad-qpath-stage-2 =
missing angle brackets in associated item path
.suggestion = try: `{$ty}`
parser-incorrect-semicolon =
expected item, found `;`
.suggestion = remove this semicolon
.help = {$name} declarations are not followed by a semicolon
parser-incorrect-use-of-await =
incorrect use of `await`
.parentheses-suggestion = `await` is not a method call, remove the parentheses
.postfix-suggestion = `await` is a postfix operation
parser-in-in-typo =
expected iterable, found keyword `in`
.suggestion = remove the duplicated `in`

View File

@ -285,6 +285,54 @@ pub enum BadTypePlusSub {
}, },
} }
#[derive(SessionDiagnostic)]
#[error(slug = "parser-maybe-recover-from-bad-qpath-stage-2")]
struct BadQPathStage2 {
#[primary_span]
#[suggestion(applicability = "maybe-incorrect")]
span: Span,
ty: String,
}
#[derive(SessionDiagnostic)]
#[error(slug = "parser-incorrect-semicolon")]
struct IncorrectSemicolon<'a> {
#[primary_span]
#[suggestion_short(applicability = "machine-applicable")]
span: Span,
#[help]
opt_help: Option<()>,
name: &'a str,
}
#[derive(SessionDiagnostic)]
#[error(slug = "parser-incorrect-use-of-await")]
struct IncorrectUseOfAwait {
#[primary_span]
#[suggestion(message = "parentheses-suggestion", applicability = "machine-applicable")]
span: Span,
}
#[derive(SessionDiagnostic)]
#[error(slug = "parser-incorrect-use-of-await")]
struct IncorrectAwait {
#[primary_span]
span: Span,
#[suggestion(message = "postfix-suggestion", code = "{expr}.await{question_mark}")]
sugg_span: (Span, Applicability),
expr: String,
question_mark: &'static str,
}
#[derive(SessionDiagnostic)]
#[error(slug = "parser-in-in-typo")]
struct InInTypo {
#[primary_span]
span: Span,
#[suggestion(applicability = "machine-applicable")]
sugg_span: Span,
}
// SnapshotParser is used to create a snapshot of the parser // SnapshotParser is used to create a snapshot of the parser
// without causing duplicate errors being emitted when the `Parser` // without causing duplicate errors being emitted when the `Parser`
// is dropped. // is dropped.
@ -1451,15 +1499,10 @@ impl<'a> Parser<'a> {
path.span = ty_span.to(self.prev_token.span); path.span = ty_span.to(self.prev_token.span);
let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty)); let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty));
self.struct_span_err(path.span, "missing angle brackets in associated item path") self.sess.emit_err(BadQPathStage2 {
.span_suggestion( span: path.span,
// This is a best-effort recovery. ty: format!("<{}>::{}", ty_str, pprust::path_to_string(&path)),
path.span, });
"try",
format!("<{}>::{}", ty_str, pprust::path_to_string(&path)),
Applicability::MaybeIncorrect,
)
.emit();
let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`. let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
Ok(P(T::recovered(Some(QSelf { ty, path_span, position: 0 }), path))) Ok(P(T::recovered(Some(QSelf { ty, path_span, position: 0 }), path)))
@ -1468,13 +1511,10 @@ impl<'a> Parser<'a> {
pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool { pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
if self.token.kind == TokenKind::Semi { if self.token.kind == TokenKind::Semi {
self.bump(); self.bump();
let mut err = self.struct_span_err(self.prev_token.span, "expected item, found `;`");
err.span_suggestion_short( let mut err =
self.prev_token.span, IncorrectSemicolon { span: self.prev_token.span, opt_help: None, name: "" };
"remove this semicolon",
String::new(),
Applicability::MachineApplicable,
);
if !items.is_empty() { if !items.is_empty() {
let previous_item = &items[items.len() - 1]; let previous_item = &items[items.len() - 1];
let previous_item_kind_name = match previous_item.kind { let previous_item_kind_name = match previous_item.kind {
@ -1487,10 +1527,11 @@ impl<'a> Parser<'a> {
_ => None, _ => None,
}; };
if let Some(name) = previous_item_kind_name { if let Some(name) = previous_item_kind_name {
err.help(&format!("{name} declarations are not followed by a semicolon")); err.opt_help = Some(());
err.name = name;
} }
} }
err.emit(); self.sess.emit_err(err);
true true
} else { } else {
false false
@ -1604,18 +1645,20 @@ impl<'a> Parser<'a> {
} }
fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: bool) -> Span { fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: bool) -> Span {
let expr_str = let span = lo.to(hi);
self.span_to_snippet(expr.span).unwrap_or_else(|_| pprust::expr_to_string(&expr)); let applicability = match expr.kind {
let suggestion = format!("{}.await{}", expr_str, if is_question { "?" } else { "" });
let sp = lo.to(hi);
let app = match expr.kind {
ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?` ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?`
_ => Applicability::MachineApplicable, _ => Applicability::MachineApplicable,
}; };
self.struct_span_err(sp, "incorrect use of `await`")
.span_suggestion(sp, "`await` is a postfix operation", suggestion, app) self.sess.emit_err(IncorrectAwait {
.emit(); span,
sp sugg_span: (span, applicability),
expr: self.span_to_snippet(expr.span).unwrap_or_else(|_| pprust::expr_to_string(&expr)),
question_mark: if is_question { "?" } else { "" },
});
span
} }
/// If encountering `future.await()`, consumes and emits an error. /// If encountering `future.await()`, consumes and emits an error.
@ -1626,16 +1669,10 @@ impl<'a> Parser<'a> {
// future.await() // future.await()
let lo = self.token.span; let lo = self.token.span;
self.bump(); // ( self.bump(); // (
let sp = lo.to(self.token.span); let span = lo.to(self.token.span);
self.bump(); // ) self.bump(); // )
self.struct_span_err(sp, "incorrect use of `await`")
.span_suggestion( self.sess.emit_err(IncorrectUseOfAwait { span });
sp,
"`await` is not a method call, remove the parentheses",
String::new(),
Applicability::MachineApplicable,
)
.emit();
} }
} }
@ -1907,14 +1944,10 @@ impl<'a> Parser<'a> {
pub(super) fn check_for_for_in_in_typo(&mut self, in_span: Span) { pub(super) fn check_for_for_in_in_typo(&mut self, in_span: Span) {
if self.eat_keyword(kw::In) { if self.eat_keyword(kw::In) {
// a common typo: `for _ in in bar {}` // a common typo: `for _ in in bar {}`
self.struct_span_err(self.prev_token.span, "expected iterable, found keyword `in`") self.sess.emit_err(InInTypo {
.span_suggestion_short( span: self.prev_token.span,
in_span.until(self.prev_token.span), sugg_span: in_span.until(self.prev_token.span),
"remove the duplicated `in`", });
String::new(),
Applicability::MachineApplicable,
)
.emit();
} }
} }