@@ -2,7 +2,7 @@ use std::panic::{catch_unwind, AssertUnwindSafe};
2
2
3
3
use rustc_ast:: ast;
4
4
use rustc_ast:: token:: { DelimToken , 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,32 +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
- // Inner attributes are not actually syntactically permitted here, but we don't
38
- // care about inner vs outer attributes in this position. Our purpose with this
39
- // special case parsing of cfg_if macros is to ensure we can correctly resolve
40
- // imported modules that may have a custom `path` defined.
41
- //
42
- // As such, we just need to advance the parser past the attribute and up to
43
- // to the opening brace.
44
- // See also https://github.com/rust-lang/rust/pull/79433
45
- parser
46
- . parse_attribute ( rustc_parse:: parser:: attr:: InnerAttrPolicy :: Permitted )
47
- . map_err ( |_| "Failed to parse attributes" ) ?;
48
- }
49
-
50
- if !parser. eat ( & TokenKind :: OpenDelim ( DelimToken :: Brace ) ) {
51
- return Err ( "Expected an opening brace" ) ;
34
+ eat_if ( & mut parser) ?;
52
35
}
53
36
54
37
while parser. token != TokenKind :: CloseDelim ( DelimToken :: Brace )
55
38
&& parser. token . kind != TokenKind :: Eof
56
39
{
57
40
let item = match parser. parse_item ( ForceCollect :: No ) {
58
41
Ok ( Some ( item_ptr) ) => item_ptr. into_inner ( ) ,
59
- 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
+ }
60
53
Err ( err) => {
61
54
err. cancel ( ) ;
62
55
parser. sess . span_diagnostic . reset_err_count ( ) ;
@@ -74,16 +67,41 @@ fn parse_cfg_if_inner<'a>(
74
67
return Err ( "Expected a closing brace" ) ;
75
68
}
76
69
77
- if parser. eat ( & TokenKind :: Eof ) {
78
- 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 ( DelimToken :: Brace ) ) ;
79
75
}
80
76
81
- if ! parser. eat_keyword ( kw :: Else ) {
82
- return Err ( "Expected `else`" ) ;
77
+ if parser. eat ( & TokenKind :: Eof ) {
78
+ break ;
83
79
}
84
80
85
81
process_if_cfg = parser. token . is_keyword ( kw:: If ) ;
86
82
}
87
83
88
84
Ok ( items)
89
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
+ // Inner attributes are not actually syntactically permitted here, but we don't
92
+ // care about inner vs outer attributes in this position. Our purpose with this
93
+ // special case parsing of cfg_if macros is to ensure we can correctly resolve
94
+ // imported modules that may have a custom `path` defined.
95
+ //
96
+ // As such, we just need to advance the parser past the attribute and up to
97
+ // to the opening brace.
98
+ // See also https://github.com/rust-lang/rust/pull/79433
99
+ parser
100
+ . parse_attribute ( rustc_parse:: parser:: attr:: InnerAttrPolicy :: Permitted )
101
+ . map_err ( |_| "Failed to parse attributes" ) ?;
102
+
103
+ if !parser. eat ( & TokenKind :: OpenDelim ( DelimToken :: Brace ) ) {
104
+ return Err ( "Expected an opening brace" ) ;
105
+ }
106
+ Ok ( ( ) )
107
+ }
0 commit comments