@@ -41,8 +41,9 @@ use crate::errors::{
41
41
IncorrectSemicolon , IncorrectUseOfAwait , IncorrectUseOfUse , PatternMethodParamWithoutBody ,
42
42
QuestionMarkInType , QuestionMarkInTypeSugg , SelfParamNotFirst , StructLiteralBodyWithoutPath ,
43
43
StructLiteralBodyWithoutPathSugg , SuggAddMissingLetStmt , SuggEscapeIdentifier , SuggRemoveComma ,
44
- TernaryOperator , UnexpectedConstInGenericParam , UnexpectedConstParamDeclaration ,
45
- UnexpectedConstParamDeclarationSugg , UnmatchedAngleBrackets , UseEqInstead , WrapType ,
44
+ TernaryOperator , TernaryOperatorSuggestion , UnexpectedConstInGenericParam ,
45
+ UnexpectedConstParamDeclaration , UnexpectedConstParamDeclarationSugg , UnmatchedAngleBrackets ,
46
+ UseEqInstead , WrapType ,
46
47
} ;
47
48
use crate :: parser:: attr:: InnerAttrPolicy ;
48
49
use crate :: { exp, fluent_generated as fluent} ;
@@ -497,7 +498,7 @@ impl<'a> Parser<'a> {
497
498
// If the user is trying to write a ternary expression, recover it and
498
499
// return an Err to prevent a cascade of irrelevant diagnostics.
499
500
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 )
501
502
{
502
503
return Err ( e) ;
503
504
}
@@ -1602,12 +1603,18 @@ impl<'a> Parser<'a> {
1602
1603
/// Rust has no ternary operator (`cond ? then : else`). Parse it and try
1603
1604
/// to recover from it if `then` and `else` are valid expressions. Returns
1604
1605
/// 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 , ( ) > {
1606
1612
if self . prev_token != token:: Question {
1607
1613
return PResult :: Ok ( ( ) ) ;
1608
1614
}
1609
1615
1610
- let lo = self . prev_token . span . lo ( ) ;
1616
+ let question = self . prev_token . span ;
1617
+ let lo = cond. unwrap_or ( question) . lo ( ) ;
1611
1618
let snapshot = self . create_snapshot_for_diagnostic ( ) ;
1612
1619
1613
1620
if match self . parse_expr ( ) {
@@ -1620,11 +1627,20 @@ impl<'a> Parser<'a> {
1620
1627
}
1621
1628
} {
1622
1629
if self . eat_noexpect ( & token:: Colon ) {
1630
+ let colon = self . prev_token . span ;
1623
1631
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
+ } ) ) ;
1628
1644
}
1629
1645
Err ( err) => {
1630
1646
err. cancel ( ) ;
0 commit comments