@@ -100,6 +100,7 @@ pub enum PathStyle {
100100enum SemiColonMode {
101101 Break ,
102102 Ignore ,
103+ Comma ,
103104}
104105
105106#[ derive( Clone , Copy , PartialEq , Debug ) ]
@@ -1988,6 +1989,44 @@ impl<'a> Parser<'a> {
19881989
19891990 result. unwrap ( )
19901991 }
1992+ token:: Dot if self . look_ahead ( 1 , |t| match t {
1993+ token:: Literal ( parse:: token:: Lit :: Integer ( _) , _) => true ,
1994+ _ => false ,
1995+ } ) => { // recover from `let x = .4;`
1996+ let lo = self . span ;
1997+ self . bump ( ) ;
1998+ if let token:: Literal (
1999+ parse:: token:: Lit :: Integer ( val) ,
2000+ suffix,
2001+ ) = self . token {
2002+ let suffix = suffix. and_then ( |s| {
2003+ let s = s. as_str ( ) . get ( ) ;
2004+ if [ "f32" , "f64" ] . contains ( & s) {
2005+ Some ( s)
2006+ } else {
2007+ None
2008+ }
2009+ } ) . unwrap_or ( "" ) ;
2010+ self . bump ( ) ;
2011+ let sp = lo. to ( self . prev_span ) ;
2012+ let mut err = self . diagnostic ( )
2013+ . struct_span_err ( sp, "float literals must have an integer part" ) ;
2014+ err. span_suggestion_with_applicability (
2015+ sp,
2016+ "must have an integer part" ,
2017+ format ! ( "0.{}{}" , val, suffix) ,
2018+ Applicability :: MachineApplicable ,
2019+ ) ;
2020+ err. emit ( ) ;
2021+ return Ok ( match suffix {
2022+ "f32" => ast:: LitKind :: Float ( val, ast:: FloatTy :: F32 ) ,
2023+ "f64" => ast:: LitKind :: Float ( val, ast:: FloatTy :: F64 ) ,
2024+ _ => ast:: LitKind :: FloatUnsuffixed ( val) ,
2025+ } ) ;
2026+ } else {
2027+ unreachable ! ( ) ;
2028+ } ;
2029+ }
19912030 _ => { return self . unexpected_last ( & self . token ) ; }
19922031 } ;
19932032
@@ -2656,8 +2695,24 @@ impl<'a> Parser<'a> {
26562695 break ;
26572696 }
26582697
2698+ let mut recovery_field = None ;
2699+ if let token:: Ident ( ident, _) = self . token {
2700+ if !self . token . is_reserved_ident ( ) && self . look_ahead ( 1 , |t| * t == token:: Colon ) {
2701+ // Use in case of error after field-looking code: `S { foo: () with a }`
2702+ let mut ident = ident. clone ( ) ;
2703+ ident. span = self . span ;
2704+ recovery_field = Some ( ast:: Field {
2705+ ident,
2706+ span : self . span ,
2707+ expr : self . mk_expr ( self . span , ExprKind :: Err , ThinVec :: new ( ) ) ,
2708+ is_shorthand : false ,
2709+ attrs : ThinVec :: new ( ) ,
2710+ } ) ;
2711+ }
2712+ }
2713+ let mut parsed_field = None ;
26592714 match self . parse_field ( ) {
2660- Ok ( f) => fields . push ( f) ,
2715+ Ok ( f) => parsed_field = Some ( f) ,
26612716 Err ( mut e) => {
26622717 e. span_label ( struct_sp, "while parsing this struct" ) ;
26632718 e. emit ( ) ;
@@ -2666,19 +2721,28 @@ impl<'a> Parser<'a> {
26662721 // what comes next as additional fields, rather than
26672722 // bailing out until next `}`.
26682723 if self . token != token:: Comma {
2669- self . recover_stmt ( ) ;
2670- break ;
2724+ self . recover_stmt_ ( SemiColonMode :: Comma , BlockMode :: Ignore ) ;
2725+ if self . token != token:: Comma {
2726+ break ;
2727+ }
26712728 }
26722729 }
26732730 }
26742731
26752732 match self . expect_one_of ( & [ token:: Comma ] ,
26762733 & [ token:: CloseDelim ( token:: Brace ) ] ) {
2677- Ok ( ( ) ) => { }
2734+ Ok ( ( ) ) => if let Some ( f) = parsed_field. or ( recovery_field) {
2735+ // only include the field if there's no parse error for the field name
2736+ fields. push ( f) ;
2737+ }
26782738 Err ( mut e) => {
2739+ if let Some ( f) = recovery_field {
2740+ fields. push ( f) ;
2741+ }
2742+ e. span_label ( struct_sp, "while parsing this struct" ) ;
26792743 e. emit ( ) ;
2680- self . recover_stmt ( ) ;
2681- break ;
2744+ self . recover_stmt_ ( SemiColonMode :: Comma , BlockMode :: Ignore ) ;
2745+ self . eat ( & token :: Comma ) ;
26822746 }
26832747 }
26842748 }
@@ -4542,13 +4606,13 @@ impl<'a> Parser<'a> {
45424606 token:: CloseDelim ( token:: DelimToken :: Brace ) => {
45434607 if brace_depth == 0 {
45444608 debug ! ( "recover_stmt_ return - close delim {:?}" , self . token) ;
4545- return ;
4609+ break ;
45464610 }
45474611 brace_depth -= 1 ;
45484612 self . bump ( ) ;
45494613 if in_block && bracket_depth == 0 && brace_depth == 0 {
45504614 debug ! ( "recover_stmt_ return - block end {:?}" , self . token) ;
4551- return ;
4615+ break ;
45524616 }
45534617 }
45544618 token:: CloseDelim ( token:: DelimToken :: Bracket ) => {
@@ -4560,15 +4624,25 @@ impl<'a> Parser<'a> {
45604624 }
45614625 token:: Eof => {
45624626 debug ! ( "recover_stmt_ return - Eof" ) ;
4563- return ;
4627+ break ;
45644628 }
45654629 token:: Semi => {
45664630 self . bump ( ) ;
45674631 if break_on_semi == SemiColonMode :: Break &&
45684632 brace_depth == 0 &&
45694633 bracket_depth == 0 {
45704634 debug ! ( "recover_stmt_ return - Semi" ) ;
4571- return ;
4635+ break ;
4636+ }
4637+ }
4638+ token:: Comma => {
4639+ if break_on_semi == SemiColonMode :: Comma &&
4640+ brace_depth == 0 &&
4641+ bracket_depth == 0 {
4642+ debug ! ( "recover_stmt_ return - Semi" ) ;
4643+ break ;
4644+ } else {
4645+ self . bump ( ) ;
45724646 }
45734647 }
45744648 _ => {
0 commit comments