@@ -2,7 +2,7 @@ use std::panic::{catch_unwind, AssertUnwindSafe};
2
2
3
3
use rustc_ast:: ast;
4
4
use rustc_ast:: token:: { Delimiter , TokenKind } ;
5
- use rustc_parse:: parser:: ForceCollect ;
5
+ use rustc_parse:: parser:: { ForceCollect , Parser } ;
6
6
use rustc_span:: symbol:: kw;
7
7
8
8
use crate :: parse:: macros:: build_stream_parser;
@@ -31,40 +31,25 @@ fn parse_cfg_if_inner<'a>(
31
31
32
32
while parser. token . kind != TokenKind :: Eof {
33
33
if process_if_cfg {
34
- if !parser. eat_keyword ( kw:: If ) {
35
- return Err ( "Expected `if`" ) ;
36
- }
37
-
38
- if !matches ! ( parser. token. kind, TokenKind :: Pound ) {
39
- return Err ( "Failed to parse attributes" ) ;
40
- }
41
-
42
- // Inner attributes are not actually syntactically permitted here, but we don't
43
- // care about inner vs outer attributes in this position. Our purpose with this
44
- // special case parsing of cfg_if macros is to ensure we can correctly resolve
45
- // imported modules that may have a custom `path` defined.
46
- //
47
- // As such, we just need to advance the parser past the attribute and up to
48
- // to the opening brace.
49
- // See also https://github.com/rust-lang/rust/pull/79433
50
- parser
51
- . parse_attribute ( rustc_parse:: parser:: attr:: InnerAttrPolicy :: Permitted )
52
- . map_err ( |e| {
53
- e. cancel ( ) ;
54
- "Failed to parse attributes"
55
- } ) ?;
56
- }
57
-
58
- if !parser. eat ( & TokenKind :: OpenDelim ( Delimiter :: Brace ) ) {
59
- return Err ( "Expected an opening brace" ) ;
34
+ eat_if ( & mut parser) ?;
60
35
}
61
36
62
37
while parser. token != TokenKind :: CloseDelim ( Delimiter :: Brace )
63
38
&& parser. token . kind != TokenKind :: Eof
64
39
{
65
40
let item = match parser. parse_item ( ForceCollect :: No ) {
66
41
Ok ( Some ( item_ptr) ) => item_ptr. into_inner ( ) ,
67
- Ok ( None ) => continue ,
42
+ Ok ( None ) => {
43
+ if matches ! ( parser. token. kind, TokenKind :: Ident ( symbol, ..) if symbol == kw:: If )
44
+ {
45
+ // eat a nested if
46
+ eat_if ( & mut parser) ?;
47
+ } else {
48
+ // Not sure what token we're on. To prevent infinite loops bump the parser
49
+ parser. bump ( ) ;
50
+ }
51
+ continue ;
52
+ }
68
53
Err ( err) => {
69
54
err. cancel ( ) ;
70
55
parser. psess . dcx . reset_err_count ( ) ;
@@ -82,16 +67,49 @@ fn parse_cfg_if_inner<'a>(
82
67
return Err ( "Expected a closing brace" ) ;
83
68
}
84
69
85
- if parser. eat ( & TokenKind :: Eof ) {
86
- break ;
70
+ if matches ! ( parser. token. kind, TokenKind :: Ident ( symbol, ..) if symbol == kw:: Else ) {
71
+ // there might be an `else` after the `if`
72
+ parser. eat_keyword ( kw:: Else ) ;
73
+ // there might be an opening brace after the `else`, but it might also be an `else if`
74
+ parser. eat ( & TokenKind :: OpenDelim ( Delimiter :: Brace ) ) ;
87
75
}
88
76
89
- if ! parser. eat_keyword ( kw :: Else ) {
90
- return Err ( "Expected `else`" ) ;
77
+ if parser. eat ( & TokenKind :: Eof ) {
78
+ break ;
91
79
}
92
80
93
81
process_if_cfg = parser. token . is_keyword ( kw:: If ) ;
94
82
}
95
83
96
84
Ok ( items)
97
85
}
86
+
87
+ fn eat_if ( parser : & mut Parser < ' _ > ) -> Result < ( ) , & ' static str > {
88
+ if !parser. eat_keyword ( kw:: If ) {
89
+ return Err ( "Expected `if`" ) ;
90
+ }
91
+
92
+ if !matches ! ( parser. token. kind, TokenKind :: Pound ) {
93
+ return Err ( "Failed to parse attributes" ) ;
94
+ }
95
+
96
+ // Inner attributes are not actually syntactically permitted here, but we don't
97
+ // care about inner vs outer attributes in this position. Our purpose with this
98
+ // special case parsing of cfg_if macros is to ensure we can correctly resolve
99
+ // imported modules that may have a custom `path` defined.
100
+ //
101
+ // As such, we just need to advance the parser past the attribute and up to
102
+ // to the opening brace.
103
+ // See also https://github.com/rust-lang/rust/pull/79433
104
+ parser
105
+ . parse_attribute ( rustc_parse:: parser:: attr:: InnerAttrPolicy :: Permitted )
106
+ . map_err ( |e| {
107
+ e. cancel ( ) ;
108
+ "Failed to parse attributes"
109
+ } ) ?;
110
+
111
+ if !parser. eat ( & TokenKind :: OpenDelim ( Delimiter :: Brace ) ) {
112
+ return Err ( "Expected an opening brace" ) ;
113
+ }
114
+ Ok ( ( ) )
115
+ }
0 commit comments