@@ -13,7 +13,7 @@ use rustc_ast::util::classify;
13
13
use rustc_ast:: util:: literal:: LitError ;
14
14
use rustc_ast:: util:: parser:: { prec_let_scrutinee_needs_par, AssocOp , Fixity } ;
15
15
use rustc_ast_pretty:: pprust;
16
- use rustc_errors:: { Applicability , PResult } ;
16
+ use rustc_errors:: { Applicability , DiagnosticBuilder , PResult } ;
17
17
use rustc_span:: source_map:: { self , Span , Spanned } ;
18
18
use rustc_span:: symbol:: { kw, sym, Symbol } ;
19
19
use std:: mem;
@@ -1068,8 +1068,8 @@ impl<'a> Parser<'a> {
1068
1068
}
1069
1069
1070
1070
fn parse_path_start_expr ( & mut self , attrs : AttrVec ) -> PResult < ' a , P < Expr > > {
1071
- let lo = self . token . span ;
1072
1071
let path = self . parse_path ( PathStyle :: Expr ) ?;
1072
+ let lo = path. span ;
1073
1073
1074
1074
// `!`, as an operator, is prefix, so we know this isn't that.
1075
1075
let ( hi, kind) = if self . eat ( & token:: Not ) {
@@ -1081,7 +1081,7 @@ impl<'a> Parser<'a> {
1081
1081
} ;
1082
1082
( self . prev_token . span , ExprKind :: MacCall ( mac) )
1083
1083
} 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) {
1085
1085
return expr;
1086
1086
} else {
1087
1087
( path. span , ExprKind :: Path ( None , path) )
@@ -1895,16 +1895,15 @@ impl<'a> Parser<'a> {
1895
1895
1896
1896
fn maybe_parse_struct_expr (
1897
1897
& mut self ,
1898
- lo : Span ,
1899
1898
path : & ast:: Path ,
1900
1899
attrs : & AttrVec ,
1901
1900
) -> Option < PResult < ' a , P < Expr > > > {
1902
1901
let struct_allowed = !self . restrictions . contains ( Restrictions :: NO_STRUCT_LITERAL ) ;
1903
1902
if struct_allowed || self . is_certainly_not_a_block ( ) {
1904
1903
// 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 ( ) ) ;
1906
1905
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 ) ;
1908
1907
}
1909
1908
return Some ( expr) ;
1910
1909
}
@@ -1923,17 +1922,23 @@ impl<'a> Parser<'a> {
1923
1922
1924
1923
pub ( super ) fn parse_struct_expr (
1925
1924
& mut self ,
1926
- lo : Span ,
1927
1925
pth : ast:: Path ,
1928
1926
mut attrs : AttrVec ,
1929
1927
) -> PResult < ' a , P < Expr > > {
1930
- let struct_sp = lo. to ( self . prev_token . span ) ;
1931
1928
self . bump ( ) ;
1932
1929
let mut fields = Vec :: new ( ) ;
1933
1930
let mut base = None ;
1931
+ let mut recover_async = false ;
1934
1932
1935
1933
attrs. extend ( self . parse_inner_attributes ( ) ?) ;
1936
1934
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
+
1937
1942
while self . token != token:: CloseDelim ( token:: Brace ) {
1938
1943
if self . eat ( & token:: DotDot ) {
1939
1944
let exp_span = self . prev_token . span ;
@@ -1952,7 +1957,11 @@ impl<'a> Parser<'a> {
1952
1957
let parsed_field = match self . parse_field ( ) {
1953
1958
Ok ( f) => Some ( f) ,
1954
1959
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
+ }
1956
1965
e. emit ( ) ;
1957
1966
1958
1967
// If the next token is a comma, then try to parse
@@ -1976,15 +1985,19 @@ impl<'a> Parser<'a> {
1976
1985
}
1977
1986
}
1978
1987
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
+ }
1988
2001
}
1989
2002
e. emit ( ) ;
1990
2003
self . recover_stmt_ ( SemiColonMode :: Comma , BlockMode :: Ignore ) ;
@@ -1993,9 +2006,10 @@ impl<'a> Parser<'a> {
1993
2006
}
1994
2007
}
1995
2008
1996
- let span = lo . to ( self . token . span ) ;
2009
+ let span = pth . span . to ( self . token . span ) ;
1997
2010
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) )
1999
2013
}
2000
2014
2001
2015
/// Use in case of error after field-looking code: `S { foo: () with a }`.
0 commit comments