@@ -11,7 +11,7 @@ use rustc_span::symbol::{kw, sym, Symbol};
1111use rustc_span:: BytePos ;
1212use syntax:: ast:: { self , AttrKind , AttrStyle , AttrVec , Attribute , Ident , DUMMY_NODE_ID } ;
1313use syntax:: ast:: { AssocItem , AssocItemKind , Item , ItemKind , UseTree , UseTreeKind } ;
14- use syntax:: ast:: { Async , Const , Defaultness , Extern , IsAuto , PathSegment , StrLit , Unsafe } ;
14+ use syntax:: ast:: { Async , Const , Defaultness , IsAuto , PathSegment , StrLit , Unsafe } ;
1515use syntax:: ast:: { BindingMode , Block , FnDecl , FnSig , Mac , MacArgs , MacDelimiter , Param , SelfKind } ;
1616use syntax:: ast:: { EnumDef , Generics , StructField , TraitRef , Ty , TyKind , Variant , VariantData } ;
1717use syntax:: ast:: { FnHeader , ForeignItem , ForeignItemKind , Mutability , Visibility , VisibilityKind } ;
@@ -96,53 +96,30 @@ impl<'a> Parser<'a> {
9696 return Ok ( Some ( item) ) ;
9797 }
9898
99+ if self . is_fn_front_matter ( ) {
100+ // FUNCTION ITEM
101+ return self . parse_item_fn ( lo, vis, attrs) ;
102+ }
103+
99104 if self . eat_keyword ( kw:: Extern ) {
100105 if self . eat_keyword ( kw:: Crate ) {
106+ // EXTERN CRATE
101107 return Ok ( Some ( self . parse_item_extern_crate ( lo, vis, attrs) ?) ) ;
102108 }
103-
109+ // EXTERN BLOCK
104110 let abi = self . parse_abi ( ) ;
105-
106- if self . eat_keyword ( kw:: Fn ) {
107- // EXTERN FUNCTION ITEM
108- let header = FnHeader {
109- unsafety : Unsafe :: No ,
110- asyncness : Async :: No ,
111- constness : Const :: No ,
112- ext : Extern :: from_abi ( abi) ,
113- } ;
114- return self . parse_item_fn ( lo, vis, attrs, header) ;
115- } else if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
116- return Ok ( Some ( self . parse_item_foreign_mod ( lo, abi, vis, attrs) ?) ) ;
117- }
118-
119- self . unexpected ( ) ?;
111+ return Ok ( Some ( self . parse_item_foreign_mod ( lo, abi, vis, attrs) ?) ) ;
120112 }
121113
122114 if self . is_static_global ( ) {
123- self . bump ( ) ;
124115 // STATIC ITEM
116+ self . bump ( ) ;
125117 let m = self . parse_mutability ( ) ;
126118 let info = self . parse_item_const ( Some ( m) ) ?;
127119 return self . mk_item_with_info ( attrs, lo, vis, info) ;
128120 }
129121
130- let constness = self . parse_constness ( ) ;
131- if let Const :: Yes ( const_span) = constness {
132- if [ kw:: Fn , kw:: Unsafe , kw:: Extern ] . iter ( ) . any ( |k| self . check_keyword ( * k) ) {
133- // CONST FUNCTION ITEM
134- let unsafety = self . parse_unsafety ( ) ;
135-
136- if self . check_keyword ( kw:: Extern ) {
137- self . sess . gated_spans . gate ( sym:: const_extern_fn, lo. to ( self . token . span ) ) ;
138- }
139- let ext = self . parse_extern ( ) ?;
140- self . expect_keyword ( kw:: Fn ) ?;
141-
142- let header = FnHeader { unsafety, asyncness : Async :: No , constness, ext } ;
143- return self . parse_item_fn ( lo, vis, attrs, header) ;
144- }
145-
122+ if let Const :: Yes ( const_span) = self . parse_constness ( ) {
146123 // CONST ITEM
147124 if self . eat_keyword ( kw:: Mut ) {
148125 let prev_span = self . prev_span ;
@@ -161,21 +138,6 @@ impl<'a> Parser<'a> {
161138 return self . mk_item_with_info ( attrs, lo, vis, info) ;
162139 }
163140
164- // Parses `async unsafe? fn`.
165- if self . check_keyword ( kw:: Async ) {
166- let async_span = self . token . span ;
167- if self . is_keyword_ahead ( 1 , & [ kw:: Fn ] ) || self . is_keyword_ahead ( 2 , & [ kw:: Fn ] ) {
168- // ASYNC FUNCTION ITEM
169- let asyncness = self . parse_asyncness ( ) ; // `async`
170- let unsafety = self . parse_unsafety ( ) ; // `unsafe`?
171- self . expect_keyword ( kw:: Fn ) ?; // `fn`
172- self . ban_async_in_2015 ( async_span) ;
173- let header =
174- FnHeader { unsafety, asyncness, constness : Const :: No , ext : Extern :: None } ;
175- return self . parse_item_fn ( lo, vis, attrs, header) ;
176- }
177- }
178-
179141 if self . check_keyword ( kw:: Unsafe ) && self . is_keyword_ahead ( 1 , & [ kw:: Trait , kw:: Auto ] ) {
180142 // UNSAFE TRAIT ITEM
181143 let unsafety = self . parse_unsafety ( ) ;
@@ -195,26 +157,6 @@ impl<'a> Parser<'a> {
195157 return self . mk_item_with_info ( attrs, lo, vis, info) ;
196158 }
197159
198- if self . check_keyword ( kw:: Fn ) {
199- // FUNCTION ITEM
200- self . bump ( ) ;
201- let header = FnHeader :: default ( ) ;
202- return self . parse_item_fn ( lo, vis, attrs, header) ;
203- }
204-
205- if self . check_keyword ( kw:: Unsafe )
206- && self . look_ahead ( 1 , |t| * t != token:: OpenDelim ( token:: Brace ) )
207- {
208- // UNSAFE FUNCTION ITEM
209- let unsafety = self . parse_unsafety ( ) ;
210- // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
211- self . check ( & token:: OpenDelim ( token:: Brace ) ) ;
212- let ext = self . parse_extern ( ) ?;
213- self . expect_keyword ( kw:: Fn ) ?;
214- let header = FnHeader { unsafety, asyncness : Async :: No , constness : Const :: No , ext } ;
215- return self . parse_item_fn ( lo, vis, attrs, header) ;
216- }
217-
218160 if self . eat_keyword ( kw:: Mod ) {
219161 // MODULE ITEM
220162 let info = self . parse_item_mod ( & attrs[ ..] ) ?;
@@ -1662,9 +1604,9 @@ impl<'a> Parser<'a> {
16621604 lo : Span ,
16631605 vis : Visibility ,
16641606 mut attrs : Vec < Attribute > ,
1665- header : FnHeader ,
16661607 ) -> PResult < ' a , Option < P < Item > > > {
16671608 let cfg = ParamCfg { is_name_required : |_| true } ;
1609+ let header = self . parse_fn_front_matter ( ) ?;
16681610 let ( ident, decl, generics) = self . parse_fn_sig ( & cfg) ?;
16691611 let body = self . parse_fn_body ( & mut false , & mut attrs) ?;
16701612 let kind = ItemKind :: Fn ( FnSig { decl, header } , generics, body) ;
@@ -1730,27 +1672,24 @@ impl<'a> Parser<'a> {
17301672 Ok ( body)
17311673 }
17321674
1733- /// Is the current token unambiguously the start of an `FnHeader`?
1675+ /// Is the current token the start of an `FnHeader` / not a valid parse ?
17341676 fn is_fn_front_matter ( & mut self ) -> bool {
17351677 // We use an over-approximation here.
17361678 // `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
1737- // This works for `async fn` and similar as `async async` is an invalid
1738- // parse and `async fn` is never a valid parse on previous editions.
1739- const QUALIFIER : [ Symbol ; 4 ] = [ kw:: Const , kw:: Async , kw:: Unsafe , kw:: Extern ] ;
1740-
1741- let check_qual_follow = |this : & mut Self , dist| {
1742- this. look_ahead ( dist, |t| {
1743- // ...qualified and then `fn`, e.g. `const fn`.
1744- t. is_keyword ( kw:: Fn )
1745- // Two qualifiers. This is enough.
1746- || QUALIFIER . iter ( ) . any ( |& kw| t. is_keyword ( kw) )
1747- } )
1748- } ;
1679+ const QUALS : [ Symbol ; 4 ] = [ kw:: Const , kw:: Async , kw:: Unsafe , kw:: Extern ] ;
17491680 self . check_keyword ( kw:: Fn ) // Definitely an `fn`.
17501681 // `$qual fn` or `$qual $qual`:
1751- || QUALIFIER . iter ( ) . any ( |& kw| self . check_keyword ( kw) ) && check_qual_follow ( self , 1 )
1752- // `extern ABI fn` or `extern ABI $qual`; skip 1 for the ABI.
1753- || self . check_keyword ( kw:: Extern ) && check_qual_follow ( self , 2 )
1682+ || QUALS . iter ( ) . any ( |& kw| self . check_keyword ( kw) )
1683+ && self . look_ahead ( 1 , |t| {
1684+ // ...qualified and then `fn`, e.g. `const fn`.
1685+ t. is_keyword ( kw:: Fn )
1686+ // Two qualifiers. This is enough. Due `async` we need to check that it's reserved.
1687+ || t. is_non_raw_ident_where ( |i| QUALS . contains ( & i. name ) && i. is_reserved ( ) )
1688+ } )
1689+ // `extern ABI fn`
1690+ || self . check_keyword ( kw:: Extern )
1691+ && self . look_ahead ( 1 , |t| t. can_begin_literal_or_bool ( ) )
1692+ && self . look_ahead ( 2 , |t| t. is_keyword ( kw:: Fn ) )
17541693 }
17551694
17561695 /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
0 commit comments