@@ -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 : false } ;
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 (
@@ -1698,25 +1706,82 @@ impl<'a> Parser<'a> {
1698
1706
/// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
1699
1707
///
1700
1708
/// The function decides if, per-parameter `p`, `p` must have a pattern or just a type.
1709
+ ///
1710
+ /// This function pointer accepts an edition, because in edition 2015, trait declarations
1711
+ /// were allowed to omit parameter names. In 2018, they became required.
1701
1712
type ReqName = fn ( Edition ) -> bool ;
1702
1713
1714
+ /// Parsing configuration for functions.
1715
+ ///
1716
+ /// The syntax of function items is slightly different within trait definitions,
1717
+ /// impl blocks, and modules. It is still parsed using the same code, just with
1718
+ /// different flags set, so that even when the input is wrong and produces a parse
1719
+ /// error, it still gets into the AST and the rest of the parser and
1720
+ /// type checker can run.
1721
+ #[ derive( Clone , Copy ) ]
1722
+ pub ( crate ) struct FnParseMode {
1723
+ /// A function pointer that decides if, per-parameter `p`, `p` must have a
1724
+ /// pattern or just a type. This field affects parsing of the parameters list.
1725
+ ///
1726
+ /// ```text
1727
+ /// fn foo(alef: A) -> X { X::new() }
1728
+ /// -----^^ affects parsing this part of the function signature
1729
+ /// |
1730
+ /// if req_name returns false, then this name is optional
1731
+ ///
1732
+ /// fn bar(A) -> X;
1733
+ /// ^
1734
+ /// |
1735
+ /// if req_name returns true, this is an error
1736
+ /// ```
1737
+ ///
1738
+ /// Calling this function pointer should only return false if:
1739
+ ///
1740
+ /// * The item is being parsed inside of a trait definition.
1741
+ /// Within an impl block or a module, it should always evaluate
1742
+ /// to true.
1743
+ /// * The span is from Edition 2015. In particular, you can get a
1744
+ /// 2015 span inside a 2021 crate using macros.
1745
+ pub req_name : ReqName ,
1746
+ /// If this flag is set to `true`, then plain, semicolon-terminated function
1747
+ /// prototypes are not allowed here.
1748
+ ///
1749
+ /// ```text
1750
+ /// fn foo(alef: A) -> X { X::new() }
1751
+ /// ^^^^^^^^^^^^
1752
+ /// |
1753
+ /// this is always allowed
1754
+ ///
1755
+ /// fn bar(alef: A, bet: B) -> X;
1756
+ /// ^
1757
+ /// |
1758
+ /// if req_body is set to true, this is an error
1759
+ /// ```
1760
+ ///
1761
+ /// This field should only be set to false if the item is inside of a trait
1762
+ /// definition or extern block. Within an impl block or a module, it should
1763
+ /// always be set to true.
1764
+ pub req_body : bool ,
1765
+ }
1766
+
1703
1767
/// Parsing of functions and methods.
1704
1768
impl < ' a > Parser < ' a > {
1705
1769
/// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
1706
1770
fn parse_fn (
1707
1771
& mut self ,
1708
1772
attrs : & mut Vec < Attribute > ,
1709
- req_name : ReqName ,
1773
+ fn_parse_mode : FnParseMode ,
1710
1774
sig_lo : Span ,
1711
1775
) -> PResult < ' a , ( Ident , FnSig , Generics , Option < P < Block > > ) > {
1712
1776
let header = self . parse_fn_front_matter ( ) ?; // `const ... fn`
1713
1777
let ident = self . parse_ident ( ) ?; // `foo`
1714
1778
let mut generics = self . parse_generics ( ) ?; // `<'a, T, ...>`
1715
- let decl = self . parse_fn_decl ( req_name, AllowPlus :: Yes , RecoverReturnSign :: Yes ) ?; // `(p: u8, ...)`
1779
+ let decl =
1780
+ self . parse_fn_decl ( fn_parse_mode. req_name , AllowPlus :: Yes , RecoverReturnSign :: Yes ) ?; // `(p: u8, ...)`
1716
1781
generics. where_clause = self . parse_where_clause ( ) ?; // `where T: Ord`
1717
1782
1718
1783
let mut sig_hi = self . prev_token . span ;
1719
- let body = self . parse_fn_body ( attrs, & ident, & mut sig_hi) ?; // `;` or `{ ... }`.
1784
+ let body = self . parse_fn_body ( attrs, & ident, & mut sig_hi, fn_parse_mode . req_body ) ?; // `;` or `{ ... }`.
1720
1785
let fn_sig_span = sig_lo. to ( sig_hi) ;
1721
1786
Ok ( ( ident, FnSig { header, decl, span : fn_sig_span } , generics, body) )
1722
1787
}
@@ -1729,9 +1794,17 @@ impl<'a> Parser<'a> {
1729
1794
attrs : & mut Vec < Attribute > ,
1730
1795
ident : & Ident ,
1731
1796
sig_hi : & mut Span ,
1797
+ req_body : bool ,
1732
1798
) -> PResult < ' a , Option < P < Block > > > {
1733
- let ( inner_attrs, body) = if self . eat ( & token:: Semi ) {
1799
+ let has_semi = if req_body {
1800
+ self . token . kind == TokenKind :: Semi
1801
+ } else {
1802
+ // Only include `;` in list of expected tokens if body is not required
1803
+ self . check ( & TokenKind :: Semi )
1804
+ } ;
1805
+ let ( inner_attrs, body) = if has_semi {
1734
1806
// Include the trailing semicolon in the span of the signature
1807
+ self . expect_semi ( ) ?;
1735
1808
* sig_hi = self . prev_token . span ;
1736
1809
( Vec :: new ( ) , None )
1737
1810
} else if self . check ( & token:: OpenDelim ( token:: Brace ) ) || self . token . is_whole_block ( ) {
@@ -1752,9 +1825,12 @@ impl<'a> Parser<'a> {
1752
1825
. emit ( ) ;
1753
1826
( Vec :: new ( ) , Some ( self . mk_block_err ( span) ) )
1754
1827
} else {
1755
- if let Err ( mut err) =
1756
- self . expected_one_of_not_found ( & [ ] , & [ token:: Semi , token:: OpenDelim ( token:: Brace ) ] )
1757
- {
1828
+ let expected = if req_body {
1829
+ & [ token:: OpenDelim ( token:: Brace ) ] [ ..]
1830
+ } else {
1831
+ & [ token:: Semi , token:: OpenDelim ( token:: Brace ) ]
1832
+ } ;
1833
+ if let Err ( mut err) = self . expected_one_of_not_found ( & [ ] , & expected) {
1758
1834
if self . token . kind == token:: CloseDelim ( token:: Brace ) {
1759
1835
// The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
1760
1836
// the AST for typechecking.
0 commit comments