Improve ternary operator recovery
This commit is contained in:
@@ -41,8 +41,9 @@ use crate::errors::{
|
||||
IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, PatternMethodParamWithoutBody,
|
||||
QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
|
||||
StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma,
|
||||
TernaryOperator, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
|
||||
UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType,
|
||||
TernaryOperator, TernaryOperatorSuggestion, UnexpectedConstInGenericParam,
|
||||
UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
|
||||
UseEqInstead, WrapType,
|
||||
};
|
||||
use crate::parser::attr::InnerAttrPolicy;
|
||||
use crate::{exp, fluent_generated as fluent};
|
||||
@@ -497,7 +498,7 @@ impl<'a> Parser<'a> {
|
||||
// If the user is trying to write a ternary expression, recover it and
|
||||
// return an Err to prevent a cascade of irrelevant diagnostics.
|
||||
if self.prev_token == token::Question
|
||||
&& let Err(e) = self.maybe_recover_from_ternary_operator()
|
||||
&& let Err(e) = self.maybe_recover_from_ternary_operator(None)
|
||||
{
|
||||
return Err(e);
|
||||
}
|
||||
@@ -1602,12 +1603,18 @@ impl<'a> Parser<'a> {
|
||||
/// Rust has no ternary operator (`cond ? then : else`). Parse it and try
|
||||
/// to recover from it if `then` and `else` are valid expressions. Returns
|
||||
/// an err if this appears to be a ternary expression.
|
||||
pub(super) fn maybe_recover_from_ternary_operator(&mut self) -> PResult<'a, ()> {
|
||||
/// If we have the span of the condition, we can provide a better error span
|
||||
/// and code suggestion.
|
||||
pub(super) fn maybe_recover_from_ternary_operator(
|
||||
&mut self,
|
||||
cond: Option<Span>,
|
||||
) -> PResult<'a, ()> {
|
||||
if self.prev_token != token::Question {
|
||||
return PResult::Ok(());
|
||||
}
|
||||
|
||||
let lo = self.prev_token.span.lo();
|
||||
let question = self.prev_token.span;
|
||||
let lo = cond.unwrap_or(question).lo();
|
||||
let snapshot = self.create_snapshot_for_diagnostic();
|
||||
|
||||
if match self.parse_expr() {
|
||||
@@ -1620,11 +1627,20 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
} {
|
||||
if self.eat_noexpect(&token::Colon) {
|
||||
let colon = self.prev_token.span;
|
||||
match self.parse_expr() {
|
||||
Ok(_) => {
|
||||
return Err(self
|
||||
.dcx()
|
||||
.create_err(TernaryOperator { span: self.token.span.with_lo(lo) }));
|
||||
Ok(expr) => {
|
||||
let sugg = cond.map(|cond| TernaryOperatorSuggestion {
|
||||
before_cond: cond.shrink_to_lo(),
|
||||
question,
|
||||
colon,
|
||||
end: expr.span.shrink_to_hi(),
|
||||
});
|
||||
return Err(self.dcx().create_err(TernaryOperator {
|
||||
span: self.prev_token.span.with_lo(lo),
|
||||
sugg,
|
||||
no_sugg: sugg.is_none(),
|
||||
}));
|
||||
}
|
||||
Err(err) => {
|
||||
err.cancel();
|
||||
|
||||
Reference in New Issue
Block a user