@@ -41,8 +41,9 @@ use crate::errors::{
4141 IncorrectSemicolon , IncorrectUseOfAwait , IncorrectUseOfUse , PatternMethodParamWithoutBody ,
4242 QuestionMarkInType , QuestionMarkInTypeSugg , SelfParamNotFirst , StructLiteralBodyWithoutPath ,
4343 StructLiteralBodyWithoutPathSugg , SuggAddMissingLetStmt , SuggEscapeIdentifier , SuggRemoveComma ,
44- TernaryOperator , UnexpectedConstInGenericParam , UnexpectedConstParamDeclaration ,
45- UnexpectedConstParamDeclarationSugg , UnmatchedAngleBrackets , UseEqInstead , WrapType ,
44+ TernaryOperator , TernaryOperatorSuggestion , UnexpectedConstInGenericParam ,
45+ UnexpectedConstParamDeclaration , UnexpectedConstParamDeclarationSugg , UnmatchedAngleBrackets ,
46+ UseEqInstead , WrapType ,
4647} ;
4748use crate :: parser:: attr:: InnerAttrPolicy ;
4849use crate :: { exp, fluent_generated as fluent} ;
@@ -497,7 +498,7 @@ impl<'a> Parser<'a> {
497498 // If the user is trying to write a ternary expression, recover it and
498499 // return an Err to prevent a cascade of irrelevant diagnostics.
499500 if self . prev_token == token:: Question
500- && let Err ( e) = self . maybe_recover_from_ternary_operator ( )
501+ && let Err ( e) = self . maybe_recover_from_ternary_operator ( None )
501502 {
502503 return Err ( e) ;
503504 }
@@ -1602,12 +1603,18 @@ impl<'a> Parser<'a> {
16021603 /// Rust has no ternary operator (`cond ? then : else`). Parse it and try
16031604 /// to recover from it if `then` and `else` are valid expressions. Returns
16041605 /// an err if this appears to be a ternary expression.
1605- pub ( super ) fn maybe_recover_from_ternary_operator ( & mut self ) -> PResult < ' a , ( ) > {
1606+ /// If we have the span of the condition, we can provide a better error span
1607+ /// and code suggestion.
1608+ pub ( super ) fn maybe_recover_from_ternary_operator (
1609+ & mut self ,
1610+ cond : Option < Span > ,
1611+ ) -> PResult < ' a , ( ) > {
16061612 if self . prev_token != token:: Question {
16071613 return PResult :: Ok ( ( ) ) ;
16081614 }
16091615
1610- let lo = self . prev_token . span . lo ( ) ;
1616+ let question = self . prev_token . span ;
1617+ let lo = cond. unwrap_or ( question) . lo ( ) ;
16111618 let snapshot = self . create_snapshot_for_diagnostic ( ) ;
16121619
16131620 if match self . parse_expr ( ) {
@@ -1620,11 +1627,20 @@ impl<'a> Parser<'a> {
16201627 }
16211628 } {
16221629 if self . eat_noexpect ( & token:: Colon ) {
1630+ let colon = self . prev_token . span ;
16231631 match self . parse_expr ( ) {
1624- Ok ( _) => {
1625- return Err ( self
1626- . dcx ( )
1627- . create_err ( TernaryOperator { span : self . token . span . with_lo ( lo) } ) ) ;
1632+ Ok ( expr) => {
1633+ let sugg = cond. map ( |cond| TernaryOperatorSuggestion {
1634+ before_cond : cond. shrink_to_lo ( ) ,
1635+ question,
1636+ colon,
1637+ end : expr. span . shrink_to_hi ( ) ,
1638+ } ) ;
1639+ return Err ( self . dcx ( ) . create_err ( TernaryOperator {
1640+ span : self . prev_token . span . with_lo ( lo) ,
1641+ sugg,
1642+ no_sugg : sugg. is_none ( ) ,
1643+ } ) ) ;
16281644 }
16291645 Err ( err) => {
16301646 err. cancel ( ) ;
0 commit comments