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:
parent
5e311f933d
commit
692bc344d5
175 changed files with 3197 additions and 786 deletions
File diff suppressed because it is too large
Load diff
|
@ -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, 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() },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1608,21 +1614,10 @@ impl<'a> Parser<'a> {
|
|||
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 },
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
});
|
||||
|
|
|
@ -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)),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue