@@ -11,7 +11,7 @@ use rustc_span::symbol::{kw, sym, Symbol};
11
11
use rustc_span:: BytePos ;
12
12
use syntax:: ast:: { self , AttrKind , AttrStyle , AttrVec , Attribute , Ident , DUMMY_NODE_ID } ;
13
13
use 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 } ;
15
15
use syntax:: ast:: { BindingMode , Block , FnDecl , FnSig , Mac , MacArgs , MacDelimiter , Param , SelfKind } ;
16
16
use syntax:: ast:: { EnumDef , Generics , StructField , TraitRef , Ty , TyKind , Variant , VariantData } ;
17
17
use syntax:: ast:: { FnHeader , ForeignItem , ForeignItemKind , Mutability , Visibility , VisibilityKind } ;
@@ -96,53 +96,30 @@ impl<'a> Parser<'a> {
96
96
return Ok ( Some ( item) ) ;
97
97
}
98
98
99
+ if self . is_fn_front_matter ( ) {
100
+ // FUNCTION ITEM
101
+ return self . parse_item_fn ( lo, vis, attrs) ;
102
+ }
103
+
99
104
if self . eat_keyword ( kw:: Extern ) {
100
105
if self . eat_keyword ( kw:: Crate ) {
106
+ // EXTERN CRATE
101
107
return Ok ( Some ( self . parse_item_extern_crate ( lo, vis, attrs) ?) ) ;
102
108
}
103
-
109
+ // EXTERN BLOCK
104
110
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) ?) ) ;
120
112
}
121
113
122
114
if self . is_static_global ( ) {
123
- self . bump ( ) ;
124
115
// STATIC ITEM
116
+ self . bump ( ) ;
125
117
let m = self . parse_mutability ( ) ;
126
118
let info = self . parse_item_const ( Some ( m) ) ?;
127
119
return self . mk_item_with_info ( attrs, lo, vis, info) ;
128
120
}
129
121
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 ( ) {
146
123
// CONST ITEM
147
124
if self . eat_keyword ( kw:: Mut ) {
148
125
let prev_span = self . prev_span ;
@@ -161,21 +138,6 @@ impl<'a> Parser<'a> {
161
138
return self . mk_item_with_info ( attrs, lo, vis, info) ;
162
139
}
163
140
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
-
179
141
if self . check_keyword ( kw:: Unsafe ) && self . is_keyword_ahead ( 1 , & [ kw:: Trait , kw:: Auto ] ) {
180
142
// UNSAFE TRAIT ITEM
181
143
let unsafety = self . parse_unsafety ( ) ;
@@ -195,26 +157,6 @@ impl<'a> Parser<'a> {
195
157
return self . mk_item_with_info ( attrs, lo, vis, info) ;
196
158
}
197
159
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
-
218
160
if self . eat_keyword ( kw:: Mod ) {
219
161
// MODULE ITEM
220
162
let info = self . parse_item_mod ( & attrs[ ..] ) ?;
@@ -1662,9 +1604,9 @@ impl<'a> Parser<'a> {
1662
1604
lo : Span ,
1663
1605
vis : Visibility ,
1664
1606
mut attrs : Vec < Attribute > ,
1665
- header : FnHeader ,
1666
1607
) -> PResult < ' a , Option < P < Item > > > {
1667
1608
let cfg = ParamCfg { is_name_required : |_| true } ;
1609
+ let header = self . parse_fn_front_matter ( ) ?;
1668
1610
let ( ident, decl, generics) = self . parse_fn_sig ( & cfg) ?;
1669
1611
let body = self . parse_fn_body ( & mut false , & mut attrs) ?;
1670
1612
let kind = ItemKind :: Fn ( FnSig { decl, header } , generics, body) ;
@@ -1730,27 +1672,24 @@ impl<'a> Parser<'a> {
1730
1672
Ok ( body)
1731
1673
}
1732
1674
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 ?
1734
1676
fn is_fn_front_matter ( & mut self ) -> bool {
1735
1677
// We use an over-approximation here.
1736
1678
// `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 ] ;
1749
1680
self . check_keyword ( kw:: Fn ) // Definitely an `fn`.
1750
1681
// `$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 ) )
1754
1693
}
1755
1694
1756
1695
/// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
0 commit comments