@@ -78,24 +78,25 @@ pub(super) type ItemInfo = (Ident, ItemKind);
78
78
79
79
impl < ' a > Parser < ' a > {
80
80
pub fn parse_item ( & mut self , force_collect : ForceCollect ) -> PResult < ' a , Option < P < Item > > > {
81
- self . parse_item_ ( |_| true , force_collect) . map ( |i| i. map ( P ) )
81
+ let fn_parse_mode = FnParseMode { req_name : |_| true , req_body : true } ;
82
+ self . parse_item_ ( fn_parse_mode, force_collect) . map ( |i| i. map ( P ) )
82
83
}
83
84
84
85
fn parse_item_ (
85
86
& mut self ,
86
- req_name : ReqName ,
87
+ fn_parse_mode : FnParseMode ,
87
88
force_collect : ForceCollect ,
88
89
) -> PResult < ' a , Option < Item > > {
89
90
let attrs = self . parse_outer_attributes ( ) ?;
90
- self . parse_item_common ( attrs, true , false , req_name , force_collect)
91
+ self . parse_item_common ( attrs, true , false , fn_parse_mode , force_collect)
91
92
}
92
93
93
94
pub ( super ) fn parse_item_common (
94
95
& mut self ,
95
96
attrs : AttrWrapper ,
96
97
mac_allowed : bool ,
97
98
attrs_allowed : bool ,
98
- req_name : ReqName ,
99
+ fn_parse_mode : FnParseMode ,
99
100
force_collect : ForceCollect ,
100
101
) -> PResult < ' a , Option < Item > > {
101
102
// Don't use `maybe_whole` so that we have precise control
@@ -113,7 +114,8 @@ impl<'a> Parser<'a> {
113
114
let mut unclosed_delims = vec ! [ ] ;
114
115
let item =
115
116
self . collect_tokens_trailing_token ( attrs, force_collect, |this : & mut Self , attrs| {
116
- let item = this. parse_item_common_ ( attrs, mac_allowed, attrs_allowed, req_name) ;
117
+ let item =
118
+ this. parse_item_common_ ( attrs, mac_allowed, attrs_allowed, fn_parse_mode) ;
117
119
unclosed_delims. append ( & mut this. unclosed_delims ) ;
118
120
Ok ( ( item?, TrailingToken :: None ) )
119
121
} ) ?;
@@ -127,12 +129,13 @@ impl<'a> Parser<'a> {
127
129
mut attrs : Vec < Attribute > ,
128
130
mac_allowed : bool ,
129
131
attrs_allowed : bool ,
130
- req_name : ReqName ,
132
+ fn_parse_mode : FnParseMode ,
131
133
) -> PResult < ' a , Option < Item > > {
132
134
let lo = self . token . span ;
133
135
let vis = self . parse_visibility ( FollowedByType :: No ) ?;
134
136
let mut def = self . parse_defaultness ( ) ;
135
- let kind = self . parse_item_kind ( & mut attrs, mac_allowed, lo, & vis, & mut def, req_name) ?;
137
+ let kind =
138
+ self . parse_item_kind ( & mut attrs, mac_allowed, lo, & vis, & mut def, fn_parse_mode) ?;
136
139
if let Some ( ( ident, kind) ) = kind {
137
140
self . error_on_unconsumed_default ( def, & kind) ;
138
141
let span = lo. to ( self . prev_token . span ) ;
@@ -192,7 +195,7 @@ impl<'a> Parser<'a> {
192
195
lo : Span ,
193
196
vis : & Visibility ,
194
197
def : & mut Defaultness ,
195
- req_name : ReqName ,
198
+ fn_parse_mode : FnParseMode ,
196
199
) -> PResult < ' a , Option < ItemInfo > > {
197
200
let def_final = def == & Defaultness :: Final ;
198
201
let mut def = || mem:: replace ( def, Defaultness :: Final ) ;
@@ -219,7 +222,7 @@ impl<'a> Parser<'a> {
219
222
( Ident :: empty ( ) , ItemKind :: Use ( tree) )
220
223
} else if self . check_fn_front_matter ( def_final) {
221
224
// FUNCTION ITEM
222
- let ( ident, sig, generics, body) = self . parse_fn ( attrs, req_name , lo) ?;
225
+ let ( ident, sig, generics, body) = self . parse_fn ( attrs, fn_parse_mode , lo) ?;
223
226
( ident, ItemKind :: Fn ( Box :: new ( Fn { defaultness : def ( ) , sig, generics, body } ) ) )
224
227
} else if self . eat_keyword ( kw:: Extern ) {
225
228
if self . eat_keyword ( kw:: Crate ) {
@@ -733,23 +736,26 @@ impl<'a> Parser<'a> {
733
736
& mut self ,
734
737
force_collect : ForceCollect ,
735
738
) -> PResult < ' a , Option < Option < P < AssocItem > > > > {
736
- self . parse_assoc_item ( |_| true , force_collect)
739
+ let fn_parse_mode = FnParseMode { req_name : |_| true , req_body : true } ;
740
+ self . parse_assoc_item ( fn_parse_mode, force_collect)
737
741
}
738
742
739
743
pub fn parse_trait_item (
740
744
& mut self ,
741
745
force_collect : ForceCollect ,
742
746
) -> PResult < ' a , Option < Option < P < AssocItem > > > > {
743
- self . parse_assoc_item ( |edition| edition >= Edition :: Edition2018 , force_collect)
747
+ let fn_parse_mode =
748
+ FnParseMode { req_name : |edition| edition >= Edition :: Edition2018 , req_body : false } ;
749
+ self . parse_assoc_item ( fn_parse_mode, force_collect)
744
750
}
745
751
746
752
/// Parses associated items.
747
753
fn parse_assoc_item (
748
754
& mut self ,
749
- req_name : ReqName ,
755
+ fn_parse_mode : FnParseMode ,
750
756
force_collect : ForceCollect ,
751
757
) -> PResult < ' a , Option < Option < P < AssocItem > > > > {
752
- Ok ( self . parse_item_ ( req_name , force_collect) ?. map (
758
+ Ok ( self . parse_item_ ( fn_parse_mode , force_collect) ?. map (
753
759
|Item { attrs, id, span, vis, ident, kind, tokens } | {
754
760
let kind = match AssocItemKind :: try_from ( kind) {
755
761
Ok ( kind) => kind,
@@ -944,7 +950,8 @@ impl<'a> Parser<'a> {
944
950
& mut self ,
945
951
force_collect : ForceCollect ,
946
952
) -> PResult < ' a , Option < Option < P < ForeignItem > > > > {
947
- Ok ( self . parse_item_ ( |_| true , force_collect) ?. map (
953
+ let fn_parse_mode = FnParseMode { req_name : |_| true , req_body : true } ;
954
+ Ok ( self . parse_item_ ( fn_parse_mode, force_collect) ?. map (
948
955
|Item { attrs, id, span, vis, ident, kind, tokens } | {
949
956
let kind = match ForeignItemKind :: try_from ( kind) {
950
957
Ok ( kind) => kind,
@@ -1484,7 +1491,8 @@ impl<'a> Parser<'a> {
1484
1491
if !is_raw && ident. is_reserved ( ) {
1485
1492
let err = if self . check_fn_front_matter ( false ) {
1486
1493
// We use `parse_fn` to get a span for the function
1487
- if let Err ( mut db) = self . parse_fn ( & mut Vec :: new ( ) , |_| true , lo) {
1494
+ let fn_parse_mode = FnParseMode { req_name : |_| true , req_body : true } ;
1495
+ if let Err ( mut db) = self . parse_fn ( & mut Vec :: new ( ) , fn_parse_mode, lo) {
1488
1496
db. delay_as_bug ( ) ;
1489
1497
}
1490
1498
let mut err = self . struct_span_err (
@@ -1700,23 +1708,33 @@ impl<'a> Parser<'a> {
1700
1708
/// The function decides if, per-parameter `p`, `p` must have a pattern or just a type.
1701
1709
type ReqName = fn ( Edition ) -> bool ;
1702
1710
1711
+ /// Parsing configuration for functions.
1712
+ /// This include the edition-specific name requirements, plus information on whether the
1713
+ /// function is allowed to go without a body.
1714
+ #[ derive( Clone , Copy ) ]
1715
+ pub ( crate ) struct FnParseMode {
1716
+ pub req_name : ReqName ,
1717
+ pub req_body : bool ,
1718
+ }
1719
+
1703
1720
/// Parsing of functions and methods.
1704
1721
impl < ' a > Parser < ' a > {
1705
1722
/// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
1706
1723
fn parse_fn (
1707
1724
& mut self ,
1708
1725
attrs : & mut Vec < Attribute > ,
1709
- req_name : ReqName ,
1726
+ fn_parse_mode : FnParseMode ,
1710
1727
sig_lo : Span ,
1711
1728
) -> PResult < ' a , ( Ident , FnSig , Generics , Option < P < Block > > ) > {
1712
1729
let header = self . parse_fn_front_matter ( ) ?; // `const ... fn`
1713
1730
let ident = self . parse_ident ( ) ?; // `foo`
1714
1731
let mut generics = self . parse_generics ( ) ?; // `<'a, T, ...>`
1715
- let decl = self . parse_fn_decl ( req_name, AllowPlus :: Yes , RecoverReturnSign :: Yes ) ?; // `(p: u8, ...)`
1732
+ let decl =
1733
+ self . parse_fn_decl ( fn_parse_mode. req_name , AllowPlus :: Yes , RecoverReturnSign :: Yes ) ?; // `(p: u8, ...)`
1716
1734
generics. where_clause = self . parse_where_clause ( ) ?; // `where T: Ord`
1717
1735
1718
1736
let mut sig_hi = self . prev_token . span ;
1719
- let body = self . parse_fn_body ( attrs, & ident, & mut sig_hi) ?; // `;` or `{ ... }`.
1737
+ let body = self . parse_fn_body ( attrs, & ident, & mut sig_hi, fn_parse_mode . req_body ) ?; // `;` or `{ ... }`.
1720
1738
let fn_sig_span = sig_lo. to ( sig_hi) ;
1721
1739
Ok ( ( ident, FnSig { header, decl, span : fn_sig_span } , generics, body) )
1722
1740
}
@@ -1729,9 +1747,17 @@ impl<'a> Parser<'a> {
1729
1747
attrs : & mut Vec < Attribute > ,
1730
1748
ident : & Ident ,
1731
1749
sig_hi : & mut Span ,
1750
+ req_body : bool ,
1732
1751
) -> PResult < ' a , Option < P < Block > > > {
1733
- let ( inner_attrs, body) = if self . eat ( & token:: Semi ) {
1752
+ let has_semi = if req_body {
1753
+ self . token . kind == TokenKind :: Semi
1754
+ } else {
1755
+ // Only include `;` in list of expected tokens if body is not required
1756
+ self . check ( & TokenKind :: Semi )
1757
+ } ;
1758
+ let ( inner_attrs, body) = if has_semi {
1734
1759
// Include the trailing semicolon in the span of the signature
1760
+ self . expect_semi ( ) ?;
1735
1761
* sig_hi = self . prev_token . span ;
1736
1762
( Vec :: new ( ) , None )
1737
1763
} else if self . check ( & token:: OpenDelim ( token:: Brace ) ) || self . token . is_whole_block ( ) {
@@ -1752,9 +1778,12 @@ impl<'a> Parser<'a> {
1752
1778
. emit ( ) ;
1753
1779
( Vec :: new ( ) , Some ( self . mk_block_err ( span) ) )
1754
1780
} else {
1755
- if let Err ( mut err) =
1756
- self . expected_one_of_not_found ( & [ ] , & [ token:: Semi , token:: OpenDelim ( token:: Brace ) ] )
1757
- {
1781
+ let expected = if req_body {
1782
+ & [ token:: OpenDelim ( token:: Brace ) ] [ ..]
1783
+ } else {
1784
+ & [ token:: Semi , token:: OpenDelim ( token:: Brace ) ]
1785
+ } ;
1786
+ if let Err ( mut err) = self . expected_one_of_not_found ( & [ ] , & expected) {
1758
1787
if self . token . kind == token:: CloseDelim ( token:: Brace ) {
1759
1788
// The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
1760
1789
// the AST for typechecking.
0 commit comments