@@ -13,7 +13,7 @@ use rustc_ast::util::classify;
1313use  rustc_ast:: util:: literal:: LitError ; 
1414use  rustc_ast:: util:: parser:: { prec_let_scrutinee_needs_par,  AssocOp ,  Fixity } ; 
1515use  rustc_ast_pretty:: pprust; 
16- use  rustc_errors:: { Applicability ,  PResult } ; 
16+ use  rustc_errors:: { Applicability ,  DiagnosticBuilder ,   PResult } ; 
1717use  rustc_span:: source_map:: { self ,  Span ,  Spanned } ; 
1818use  rustc_span:: symbol:: { kw,  sym,  Symbol } ; 
1919use  std:: mem; 
@@ -1068,8 +1068,8 @@ impl<'a> Parser<'a> {
10681068    } 
10691069
10701070    fn  parse_path_start_expr ( & mut  self ,  attrs :  AttrVec )  -> PResult < ' a ,  P < Expr > >  { 
1071-         let  lo = self . token . span ; 
10721071        let  path = self . parse_path ( PathStyle :: Expr ) ?; 
1072+         let  lo = path. span ; 
10731073
10741074        // `!`, as an operator, is prefix, so we know this isn't that. 
10751075        let  ( hi,  kind)  = if  self . eat ( & token:: Not )  { 
@@ -1081,7 +1081,7 @@ impl<'a> Parser<'a> {
10811081            } ; 
10821082            ( self . prev_token . span ,  ExprKind :: MacCall ( mac) ) 
10831083        }  else  if  self . check ( & token:: OpenDelim ( token:: Brace ) )  { 
1084-             if  let  Some ( expr)  = self . maybe_parse_struct_expr ( lo ,   & path,  & attrs)  { 
1084+             if  let  Some ( expr)  = self . maybe_parse_struct_expr ( & path,  & attrs)  { 
10851085                return  expr; 
10861086            }  else  { 
10871087                ( path. span ,  ExprKind :: Path ( None ,  path) ) 
@@ -1895,16 +1895,15 @@ impl<'a> Parser<'a> {
18951895
18961896    fn  maybe_parse_struct_expr ( 
18971897        & mut  self , 
1898-         lo :  Span , 
18991898        path :  & ast:: Path , 
19001899        attrs :  & AttrVec , 
19011900    )  -> Option < PResult < ' a ,  P < Expr > > >  { 
19021901        let  struct_allowed = !self . restrictions . contains ( Restrictions :: NO_STRUCT_LITERAL ) ; 
19031902        if  struct_allowed || self . is_certainly_not_a_block ( )  { 
19041903            // This is a struct literal, but we don't can't accept them here. 
1905-             let  expr = self . parse_struct_expr ( lo ,   path. clone ( ) ,  attrs. clone ( ) ) ; 
1904+             let  expr = self . parse_struct_expr ( path. clone ( ) ,  attrs. clone ( ) ) ; 
19061905            if  let  ( Ok ( expr) ,  false )  = ( & expr,  struct_allowed)  { 
1907-                 self . error_struct_lit_not_allowed_here ( lo ,  expr. span ) ; 
1906+                 self . error_struct_lit_not_allowed_here ( path . span ,  expr. span ) ; 
19081907            } 
19091908            return  Some ( expr) ; 
19101909        } 
@@ -1923,17 +1922,23 @@ impl<'a> Parser<'a> {
19231922
19241923    pub ( super )  fn  parse_struct_expr ( 
19251924        & mut  self , 
1926-         lo :  Span , 
19271925        pth :  ast:: Path , 
19281926        mut  attrs :  AttrVec , 
19291927    )  -> PResult < ' a ,  P < Expr > >  { 
1930-         let  struct_sp = lo. to ( self . prev_token . span ) ; 
19311928        self . bump ( ) ; 
19321929        let  mut  fields = Vec :: new ( ) ; 
19331930        let  mut  base = None ; 
1931+         let  mut  recover_async = false ; 
19341932
19351933        attrs. extend ( self . parse_inner_attributes ( ) ?) ; 
19361934
1935+         let  mut  async_block_err = |e :  & mut  DiagnosticBuilder < ' _ > ,  span :  Span | { 
1936+             recover_async = true ; 
1937+             e. span_label ( span,  "`async` blocks are only allowed in the 2018 edition" ) ; 
1938+             e. help ( "set `edition = \" 2018\" ` in `Cargo.toml`" ) ; 
1939+             e. note ( "for more on editions, read https://doc.rust-lang.org/edition-guide" ) ; 
1940+         } ; 
1941+ 
19371942        while  self . token  != token:: CloseDelim ( token:: Brace )  { 
19381943            if  self . eat ( & token:: DotDot )  { 
19391944                let  exp_span = self . prev_token . span ; 
@@ -1952,7 +1957,11 @@ impl<'a> Parser<'a> {
19521957            let  parsed_field = match  self . parse_field ( )  { 
19531958                Ok ( f)  => Some ( f) , 
19541959                Err ( mut  e)  => { 
1955-                     e. span_label ( struct_sp,  "while parsing this struct" ) ; 
1960+                     if  pth == kw:: Async  { 
1961+                         async_block_err ( & mut  e,  pth. span ) ; 
1962+                     }  else  { 
1963+                         e. span_label ( pth. span ,  "while parsing this struct" ) ; 
1964+                     } 
19561965                    e. emit ( ) ; 
19571966
19581967                    // If the next token is a comma, then try to parse 
@@ -1976,15 +1985,19 @@ impl<'a> Parser<'a> {
19761985                    } 
19771986                } 
19781987                Err ( mut  e)  => { 
1979-                     e. span_label ( struct_sp,  "while parsing this struct" ) ; 
1980-                     if  let  Some ( f)  = recovery_field { 
1981-                         fields. push ( f) ; 
1982-                         e. span_suggestion ( 
1983-                             self . prev_token . span . shrink_to_hi ( ) , 
1984-                             "try adding a comma" , 
1985-                             "," . into ( ) , 
1986-                             Applicability :: MachineApplicable , 
1987-                         ) ; 
1988+                     if  pth == kw:: Async  { 
1989+                         async_block_err ( & mut  e,  pth. span ) ; 
1990+                     }  else  { 
1991+                         e. span_label ( pth. span ,  "while parsing this struct" ) ; 
1992+                         if  let  Some ( f)  = recovery_field { 
1993+                             fields. push ( f) ; 
1994+                             e. span_suggestion ( 
1995+                                 self . prev_token . span . shrink_to_hi ( ) , 
1996+                                 "try adding a comma" , 
1997+                                 "," . into ( ) , 
1998+                                 Applicability :: MachineApplicable , 
1999+                             ) ; 
2000+                         } 
19882001                    } 
19892002                    e. emit ( ) ; 
19902003                    self . recover_stmt_ ( SemiColonMode :: Comma ,  BlockMode :: Ignore ) ; 
@@ -1993,9 +2006,10 @@ impl<'a> Parser<'a> {
19932006            } 
19942007        } 
19952008
1996-         let  span = lo . to ( self . token . span ) ; 
2009+         let  span = pth . span . to ( self . token . span ) ; 
19972010        self . expect ( & token:: CloseDelim ( token:: Brace ) ) ?; 
1998-         Ok ( self . mk_expr ( span,  ExprKind :: Struct ( pth,  fields,  base) ,  attrs) ) 
2011+         let  expr = if  recover_async {  ExprKind :: Err  }  else  {  ExprKind :: Struct ( pth,  fields,  base)  } ; 
2012+         Ok ( self . mk_expr ( span,  expr,  attrs) ) 
19992013    } 
20002014
20012015    /// Use in case of error after field-looking code: `S { foo: () with a }`. 
0 commit comments