1
Fork 0

Rollup merge of #127407 - estebank:parser-suggestions, r=oli-obk

Make parse error suggestions verbose and fix spans

Go over all structured parser suggestions and make them verbose style.

When suggesting to add or remove delimiters, turn them into multiple suggestion parts.
This commit is contained in:
Matthias Krüger 2024-07-15 21:11:48 +02:00 committed by GitHub
commit 2b82729b91
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
166 changed files with 3055 additions and 780 deletions

File diff suppressed because it is too large Load diff

View file

@ -3,8 +3,8 @@ use super::{
BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenType,
};
use crate::errors::{
AmbiguousPlus, AsyncMoveBlockIn2015, AttributeOnParamType, BadQPathStage2, BadTypePlus,
BadTypePlusSub, ColonAsSemi, ComparisonOperatorsCannotBeChained,
AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AttributeOnParamType, AwaitSuggestion,
BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi, ComparisonOperatorsCannotBeChained,
ComparisonOperatorsCannotBeChainedSugg, ConstGenericWithoutBraces,
ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything, DocCommentOnParamType,
DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
@ -566,7 +566,10 @@ impl<'a> Parser<'a> {
&& expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Eq)))
{
// Likely typo: `=` → `==` in let expr or enum item
return Err(self.dcx().create_err(UseEqInstead { span: self.token.span }));
return Err(self.dcx().create_err(UseEqInstead {
span: self.token.span,
suggestion: self.token.span.with_lo(self.token.span.lo() + BytePos(1)),
}));
}
if self.token.is_keyword(kw::Move) && self.prev_token.is_keyword(kw::Async) {
@ -1151,7 +1154,7 @@ impl<'a> Parser<'a> {
// Eat from where we started until the end token so that parsing can continue
// as if we didn't have those extra angle brackets.
self.eat_to_tokens(end);
let span = lo.until(self.token.span);
let span = lo.to(self.prev_token.span);
let num_extra_brackets = number_of_gt + number_of_shr * 2;
return Some(self.dcx().emit_err(UnmatchedAngleBrackets { span, num_extra_brackets }));
@ -1539,7 +1542,10 @@ impl<'a> Parser<'a> {
pub(super) fn maybe_report_ambiguous_plus(&mut self, impl_dyn_multi: bool, ty: &Ty) {
if impl_dyn_multi {
self.dcx().emit_err(AmbiguousPlus { sum_ty: pprust::ty_to_string(ty), span: ty.span });
self.dcx().emit_err(AmbiguousPlus {
span: ty.span,
suggestion: AddParen { lo: ty.span.shrink_to_lo(), hi: ty.span.shrink_to_hi() },
});
}
}
@ -1604,25 +1610,14 @@ impl<'a> Parser<'a> {
}
self.bump(); // `+`
let bounds = self.parse_generic_bounds()?;
let _bounds = self.parse_generic_bounds()?;
let sum_span = ty.span.to(self.prev_token.span);
let sub = match &ty.kind {
TyKind::Ref(lifetime, mut_ty) => {
let sum_with_parens = pprust::to_string(|s| {
s.s.word("&");
s.print_opt_lifetime(lifetime);
s.print_mutability(mut_ty.mutbl, false);
s.popen();
s.print_type(&mut_ty.ty);
if !bounds.is_empty() {
s.word(" + ");
s.print_type_bounds(&bounds);
}
s.pclose()
});
BadTypePlusSub::AddParen { sum_with_parens, span: sum_span }
TyKind::Ref(_lifetime, mut_ty) => {
let lo = mut_ty.ty.span.shrink_to_lo();
let hi = self.prev_token.span.shrink_to_hi();
BadTypePlusSub::AddParen { suggestion: AddParen { lo, hi } }
}
TyKind::Ptr(..) | TyKind::BareFn(..) => BadTypePlusSub::ForgotParen { span: sum_span },
_ => BadTypePlusSub::ExpectPath { span: sum_span },
@ -1964,18 +1959,14 @@ impl<'a> Parser<'a> {
is_question: bool,
) -> (Span, ErrorGuaranteed) {
let span = lo.to(hi);
let applicability = match expr.kind {
ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?`
_ => Applicability::MachineApplicable,
};
let guar = self.dcx().emit_err(IncorrectAwait {
span,
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 { "" },
suggestion: AwaitSuggestion {
removal: lo.until(expr.span),
dot_await: expr.span.shrink_to_hi(),
question_mark: if is_question { "?" } else { "" },
},
});
(span, guar)
}

View file

@ -714,7 +714,7 @@ impl<'a> Parser<'a> {
type_err.cancel();
self.dcx().emit_err(errors::MalformedLoopLabel {
span: label.ident.span,
correct_label: label.ident,
suggestion: label.ident.span.shrink_to_lo(),
});
return Ok(expr);
}
@ -856,7 +856,7 @@ impl<'a> Parser<'a> {
let hi = self.interpolated_or_expr_span(&expr);
let span = lo.to(hi);
if let Some(lt) = lifetime {
self.error_remove_borrow_lifetime(span, lt.ident.span);
self.error_remove_borrow_lifetime(span, lt.ident.span.until(expr.span));
}
Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
}
@ -1653,6 +1653,7 @@ impl<'a> Parser<'a> {
let lo = label_.ident.span;
let label = Some(label_);
let ate_colon = self.eat(&token::Colon);
let tok_sp = self.token.span;
let expr = if self.eat_keyword(kw::While) {
self.parse_expr_while(label, lo)
} else if self.eat_keyword(kw::For) {
@ -1747,7 +1748,7 @@ impl<'a> Parser<'a> {
self.dcx().emit_err(errors::RequireColonAfterLabeledExpression {
span: expr.span,
label: lo,
label_end: lo.shrink_to_hi(),
label_end: lo.between(tok_sp),
});
}
@ -2106,7 +2107,7 @@ impl<'a> Parser<'a> {
self.bump();
self.dcx().emit_err(errors::FloatLiteralRequiresIntegerPart {
span: token.span,
correct: pprust::token_to_string(token).into_owned(),
suggestion: token.span.shrink_to_lo(),
});
}
}
@ -2741,7 +2742,7 @@ impl<'a> Parser<'a> {
if !attrs.is_empty()
&& let [x0 @ xn] | [x0, .., xn] = &*attrs.take_for_recovery(self.psess)
{
let attributes = x0.span.to(xn.span);
let attributes = x0.span.until(branch_span);
let last = xn.span;
let ctx = if is_ctx_else { "else" } else { "if" };
self.dcx().emit_err(errors::OuterAttributeNotAllowedOnIfElse {

View file

@ -2241,9 +2241,13 @@ impl<'a> Parser<'a> {
let kw_token = self.token.clone();
let kw_str = pprust::token_to_string(&kw_token);
let item = self.parse_item(ForceCollect::No)?;
let mut item = item.unwrap().span;
if self.token == token::Comma {
item = item.to(self.token.span);
}
self.dcx().emit_err(errors::NestedAdt {
span: kw_token.span,
item: item.unwrap().span,
item,
kw_str,
keyword: keyword.as_str(),
});

View file

@ -4,11 +4,11 @@ use crate::errors::{
DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax,
InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder,
TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed,
UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat,
UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam,
UnexpectedVertVertInPattern,
ParenRangeSuggestion, PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern,
SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern,
UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens,
};
use crate::parser::expr::{could_be_unclosed_char_literal, LhsExpr};
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
@ -24,7 +24,7 @@ use rustc_errors::{Applicability, Diag, PResult};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_span::{BytePos, ErrorGuaranteed, Span};
use thin_vec::{thin_vec, ThinVec};
#[derive(PartialEq, Copy, Clone)]
@ -236,11 +236,15 @@ impl<'a> Parser<'a> {
if let PatKind::Or(pats) = &pat.kind {
let span = pat.span;
let pat = pprust::pat_to_string(&pat);
let sub = if pats.len() == 1 {
Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat })
Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert {
span: span.with_hi(span.lo() + BytePos(1)),
})
} else {
Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
Some(TopLevelOrPatternNotAllowedSugg::WrapInParens {
span,
suggestion: WrapInParens { lo: span.shrink_to_lo(), hi: span.shrink_to_hi() },
})
};
let err = self.dcx().create_err(match syntax_loc {
@ -599,7 +603,10 @@ impl<'a> Parser<'a> {
self.bump(); // `...`
// The user probably mistook `...` for a rest pattern `..`.
self.dcx().emit_err(DotDotDotRestPattern { span: lo });
self.dcx().emit_err(DotDotDotRestPattern {
span: lo,
suggestion: lo.with_lo(lo.hi() - BytePos(1)),
});
PatKind::Rest
}
@ -664,8 +671,13 @@ impl<'a> Parser<'a> {
_ => return,
}
self.dcx()
.emit_err(AmbiguousRangePattern { span: pat.span, pat: pprust::pat_to_string(pat) });
self.dcx().emit_err(AmbiguousRangePattern {
span: pat.span,
suggestion: ParenRangeSuggestion {
lo: pat.span.shrink_to_lo(),
hi: pat.span.shrink_to_hi(),
},
});
}
/// Parse `&pat` / `&mut pat`.
@ -674,8 +686,11 @@ impl<'a> Parser<'a> {
if let token::Lifetime(name) = self.token.kind {
self.bump(); // `'a`
self.dcx()
.emit_err(UnexpectedLifetimeInPattern { span: self.prev_token.span, symbol: name });
self.dcx().emit_err(UnexpectedLifetimeInPattern {
span: self.prev_token.span,
symbol: name,
suggestion: self.prev_token.span.until(self.token.span),
});
}
let mutbl = self.parse_mutability();
@ -913,10 +928,13 @@ impl<'a> Parser<'a> {
self.dcx().emit_err(InclusiveRangeExtraEquals { span: span_with_eq })
}
token::Gt if no_space => {
let after_pat = span.with_hi(span.hi() - rustc_span::BytePos(1)).shrink_to_hi();
let after_pat = span.with_hi(span.hi() - BytePos(1)).shrink_to_hi();
self.dcx().emit_err(InclusiveRangeMatchArrow { span, arrow: tok.span, after_pat })
}
_ => self.dcx().emit_err(InclusiveRangeNoEnd { span }),
_ => self.dcx().emit_err(InclusiveRangeNoEnd {
span,
suggestion: span.with_lo(span.hi() - BytePos(1)),
}),
}
}

View file

@ -258,6 +258,7 @@ impl<'a> Parser<'a> {
self.bump(); // bump past the colon
self.dcx().emit_err(PathSingleColon {
span: self.prev_token.span,
suggestion: self.prev_token.span.shrink_to_hi(),
type_ascription: self
.psess
.unstable_features
@ -329,6 +330,7 @@ impl<'a> Parser<'a> {
err.cancel();
err = self.dcx().create_err(PathSingleColon {
span: self.token.span,
suggestion: self.prev_token.span.shrink_to_hi(),
type_ascription: self
.psess
.unstable_features

View file

@ -430,8 +430,10 @@ impl<'a> Parser<'a> {
let eq_consumed = match self.token.kind {
token::BinOpEq(..) => {
// Recover `let x <op>= 1` as `let x = 1`
self.dcx()
.emit_err(errors::CompoundAssignmentExpressionInLet { span: self.token.span });
self.dcx().emit_err(errors::CompoundAssignmentExpressionInLet {
span: self.token.span,
suggestion: self.token.span.with_hi(self.token.span.lo() + BytePos(1)),
});
self.bump();
true
}
@ -717,7 +719,7 @@ impl<'a> Parser<'a> {
e.cancel();
self.dcx().emit_err(MalformedLoopLabel {
span: label.ident.span,
correct_label: label.ident,
suggestion: label.ident.span.shrink_to_lo(),
});
*expr = labeled_expr;
break 'break_recover None;

View file

@ -209,6 +209,7 @@ impl<'a> Parser<'a> {
recover_qpath: RecoverQPath,
recover_return_sign: RecoverReturnSign,
) -> PResult<'a, FnRetTy> {
let lo = self.prev_token.span;
Ok(if self.eat(&token::RArrow) {
// FIXME(Centril): Can we unconditionally `allow_plus`?
let ty = self.parse_ty_common(
@ -224,7 +225,10 @@ impl<'a> Parser<'a> {
// Don't `eat` to prevent `=>` from being added as an expected token which isn't
// actually expected and could only confuse users
self.bump();
self.dcx().emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span });
self.dcx().emit_err(ReturnTypesUseThinArrow {
span: self.prev_token.span,
suggestion: lo.between(self.token.span),
});
let ty = self.parse_ty_common(
allow_plus,
AllowCVariadic::No,
@ -794,8 +798,11 @@ impl<'a> Parser<'a> {
{
if self.token.is_keyword(kw::Dyn) {
// Account for `&dyn Trait + dyn Other`.
self.dcx().emit_err(InvalidDynKeyword { span: self.token.span });
self.bump();
self.dcx().emit_err(InvalidDynKeyword {
span: self.prev_token.span,
suggestion: self.prev_token.span.until(self.token.span),
});
}
bounds.push(self.parse_generic_bound()?);
if allow_plus == AllowPlus::No || !self.eat_plus() {
@ -861,7 +868,7 @@ impl<'a> Parser<'a> {
if has_parens {
// FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
// possibly introducing `GenericBound::Paren(P<GenericBound>)`?
self.recover_paren_lifetime(lo, lt.ident.span)?;
self.recover_paren_lifetime(lo)?;
}
Ok(bound)
}
@ -909,16 +916,12 @@ impl<'a> Parser<'a> {
}
/// Recover on `('lifetime)` with `(` already eaten.
fn recover_paren_lifetime(&mut self, lo: Span, lt_span: Span) -> PResult<'a, ()> {
fn recover_paren_lifetime(&mut self, lo: Span) -> PResult<'a, ()> {
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
let span = lo.to(self.prev_token.span);
let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(lt_span) {
(Some(span), snippet)
} else {
(None, String::new())
};
let sugg = errors::RemoveParens { lo, hi: self.prev_token.span };
self.dcx().emit_err(errors::ParenthesizedLifetime { span, sugg, snippet });
self.dcx().emit_err(errors::ParenthesizedLifetime { span, sugg });
Ok(())
}