@@ -81,6 +81,8 @@ type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
81
81
pub enum PathParsingMode {
82
82
/// A path with no type parameters; e.g. `foo::bar::Baz`
83
83
NoTypesAllowed ,
84
+ /// Same as `NoTypesAllowed`, but may end with `::{` or `::*`, which are left unparsed
85
+ ImportPrefix ,
84
86
/// A path with a lifetime and type parameters, with no double colons
85
87
/// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`
86
88
LifetimeAndTypesWithoutColons ,
@@ -591,20 +593,6 @@ impl<'a> Parser<'a> {
591
593
}
592
594
}
593
595
594
- pub fn parse_path_list_item ( & mut self ) -> PResult < ' a , ast:: PathListItem > {
595
- let lo = self . span . lo ;
596
- let node = if self . eat_keyword ( keywords:: SelfValue ) {
597
- let rename = self . parse_rename ( ) ?;
598
- ast:: PathListItemKind :: Mod { id : ast:: DUMMY_NODE_ID , rename : rename }
599
- } else {
600
- let ident = self . parse_ident ( ) ?;
601
- let rename = self . parse_rename ( ) ?;
602
- ast:: PathListItemKind :: Ident { name : ident, rename : rename, id : ast:: DUMMY_NODE_ID }
603
- } ;
604
- let hi = self . last_span . hi ;
605
- Ok ( spanned ( lo, hi, node) )
606
- }
607
-
608
596
/// Check if the next token is `tok`, and return `true` if so.
609
597
///
610
598
/// This method will automatically add `tok` to `expected_tokens` if `tok` is not
@@ -1763,8 +1751,8 @@ impl<'a> Parser<'a> {
1763
1751
LifetimeAndTypesWithColons => {
1764
1752
self . parse_path_segments_with_colons ( ) ?
1765
1753
}
1766
- NoTypesAllowed => {
1767
- self . parse_path_segments_without_types ( ) ?
1754
+ NoTypesAllowed | ImportPrefix => {
1755
+ self . parse_path_segments_without_types ( mode == ImportPrefix ) ?
1768
1756
}
1769
1757
} ;
1770
1758
path. segments . extend ( segments) ;
@@ -1801,8 +1789,8 @@ impl<'a> Parser<'a> {
1801
1789
LifetimeAndTypesWithColons => {
1802
1790
self . parse_path_segments_with_colons ( ) ?
1803
1791
}
1804
- NoTypesAllowed => {
1805
- self . parse_path_segments_without_types ( ) ?
1792
+ NoTypesAllowed | ImportPrefix => {
1793
+ self . parse_path_segments_without_types ( mode == ImportPrefix ) ?
1806
1794
}
1807
1795
} ;
1808
1796
@@ -1920,7 +1908,8 @@ impl<'a> Parser<'a> {
1920
1908
1921
1909
/// Examples:
1922
1910
/// - `a::b::c`
1923
- pub fn parse_path_segments_without_types ( & mut self ) -> PResult < ' a , Vec < ast:: PathSegment > > {
1911
+ pub fn parse_path_segments_without_types ( & mut self , import_prefix : bool )
1912
+ -> PResult < ' a , Vec < ast:: PathSegment > > {
1924
1913
let mut segments = Vec :: new ( ) ;
1925
1914
loop {
1926
1915
// First, parse an identifier.
@@ -1932,9 +1921,11 @@ impl<'a> Parser<'a> {
1932
1921
parameters : ast:: PathParameters :: none ( )
1933
1922
} ) ;
1934
1923
1935
- // If we do not see a `::`, stop.
1936
- if !self . eat ( & token:: ModSep ) {
1924
+ // If we do not see a `::` or see `::{`/`::*` , stop.
1925
+ if !self . check ( & token:: ModSep ) || import_prefix && self . is_import_coupler ( ) {
1937
1926
return Ok ( segments) ;
1927
+ } else {
1928
+ self . bump ( ) ;
1938
1929
}
1939
1930
}
1940
1931
}
@@ -6127,106 +6118,67 @@ impl<'a> Parser<'a> {
6127
6118
self . parse_item_ ( attrs, true , false )
6128
6119
}
6129
6120
6121
+ fn parse_path_list_items ( & mut self ) -> PResult < ' a , Vec < ast:: PathListItem > > {
6122
+ self . parse_unspanned_seq ( & token:: OpenDelim ( token:: Brace ) ,
6123
+ & token:: CloseDelim ( token:: Brace ) ,
6124
+ SeqSep :: trailing_allowed ( token:: Comma ) , |this| {
6125
+ let lo = this. span . lo ;
6126
+ let node = if this. eat_keyword ( keywords:: SelfValue ) {
6127
+ let rename = this. parse_rename ( ) ?;
6128
+ ast:: PathListItemKind :: Mod { id : ast:: DUMMY_NODE_ID , rename : rename }
6129
+ } else {
6130
+ let ident = this. parse_ident ( ) ?;
6131
+ let rename = this. parse_rename ( ) ?;
6132
+ ast:: PathListItemKind :: Ident { name : ident, rename : rename, id : ast:: DUMMY_NODE_ID }
6133
+ } ;
6134
+ let hi = this. last_span . hi ;
6135
+ Ok ( spanned ( lo, hi, node) )
6136
+ } )
6137
+ }
6138
+
6139
+ /// `::{` or `::*`
6140
+ fn is_import_coupler ( & mut self ) -> bool {
6141
+ self . check ( & token:: ModSep ) &&
6142
+ self . look_ahead ( 1 , |t| * t == token:: OpenDelim ( token:: Brace ) ||
6143
+ * t == token:: BinOp ( token:: Star ) )
6144
+ }
6130
6145
6131
- /// Matches view_path : MOD? non_global_path as IDENT
6132
- /// | MOD? non_global_path MOD_SEP LBRACE RBRACE
6133
- /// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
6134
- /// | MOD? non_global_path MOD_SEP STAR
6135
- /// | MOD? non_global_path
6146
+ /// Matches ViewPath:
6147
+ /// MOD_SEP? non_global_path
6148
+ /// MOD_SEP? non_global_path as IDENT
6149
+ /// MOD_SEP? non_global_path MOD_SEP STAR
6150
+ /// MOD_SEP? non_global_path MOD_SEP LBRACE item_seq RBRACE
6151
+ /// MOD_SEP? LBRACE item_seq RBRACE
6136
6152
fn parse_view_path ( & mut self ) -> PResult < ' a , P < ViewPath > > {
6137
6153
let lo = self . span . lo ;
6138
-
6139
- // Allow a leading :: because the paths are absolute either way.
6140
- // This occurs with "use $crate::..." in macros.
6141
- let is_global = self . eat ( & token:: ModSep ) ;
6142
-
6143
- if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
6144
- // use {foo,bar}
6145
- let idents = self . parse_unspanned_seq (
6146
- & token:: OpenDelim ( token:: Brace ) ,
6147
- & token:: CloseDelim ( token:: Brace ) ,
6148
- SeqSep :: trailing_allowed ( token:: Comma ) ,
6149
- |p| p. parse_path_list_item ( ) ) ?;
6150
- let path = ast:: Path {
6154
+ if self . check ( & token:: OpenDelim ( token:: Brace ) ) || self . is_import_coupler ( ) {
6155
+ // `{foo, bar}` or `::{foo, bar}`
6156
+ let prefix = ast:: Path {
6157
+ global : self . eat ( & token:: ModSep ) ,
6158
+ segments : Vec :: new ( ) ,
6151
6159
span : mk_sp ( lo, self . span . hi ) ,
6152
- global : is_global,
6153
- segments : Vec :: new ( )
6154
6160
} ;
6155
- return Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( path, idents) ) ) ) ;
6156
- }
6157
-
6158
- let first_ident = self . parse_ident ( ) ?;
6159
- let mut path = vec ! ( first_ident) ;
6160
- if let token:: ModSep = self . token {
6161
- // foo::bar or foo::{a,b,c} or foo::*
6162
- while self . check ( & token:: ModSep ) {
6161
+ let items = self . parse_path_list_items ( ) ?;
6162
+ Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( prefix, items) ) ) )
6163
+ } else {
6164
+ let prefix = self . parse_path ( ImportPrefix ) ?;
6165
+ if self . is_import_coupler ( ) {
6166
+ // `foo::bar::{a, b}` or `foo::bar::*`
6163
6167
self . bump ( ) ;
6164
-
6165
- match self . token {
6166
- token:: Ident ( ..) => {
6167
- let ident = self . parse_ident ( ) ?;
6168
- path. push ( ident) ;
6169
- }
6170
-
6171
- // foo::bar::{a,b,c}
6172
- token:: OpenDelim ( token:: Brace ) => {
6173
- let idents = self . parse_unspanned_seq (
6174
- & token:: OpenDelim ( token:: Brace ) ,
6175
- & token:: CloseDelim ( token:: Brace ) ,
6176
- SeqSep :: trailing_allowed ( token:: Comma ) ,
6177
- |p| p. parse_path_list_item ( )
6178
- ) ?;
6179
- let path = ast:: Path {
6180
- span : mk_sp ( lo, self . span . hi ) ,
6181
- global : is_global,
6182
- segments : path. into_iter ( ) . map ( |identifier| {
6183
- ast:: PathSegment {
6184
- identifier : identifier,
6185
- parameters : ast:: PathParameters :: none ( ) ,
6186
- }
6187
- } ) . collect ( )
6188
- } ;
6189
- return Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( path, idents) ) ) ) ;
6190
- }
6191
-
6192
- // foo::bar::*
6193
- token:: BinOp ( token:: Star ) => {
6168
+ if self . check ( & token:: BinOp ( token:: Star ) ) {
6194
6169
self . bump ( ) ;
6195
- let path = ast:: Path {
6196
- span : mk_sp ( lo, self . span . hi ) ,
6197
- global : is_global,
6198
- segments : path. into_iter ( ) . map ( |identifier| {
6199
- ast:: PathSegment {
6200
- identifier : identifier,
6201
- parameters : ast:: PathParameters :: none ( ) ,
6202
- }
6203
- } ) . collect ( )
6204
- } ;
6205
- return Ok ( P ( spanned ( lo, self . span . hi , ViewPathGlob ( path) ) ) ) ;
6206
- }
6207
-
6208
- // fall-through for case foo::bar::;
6209
- token:: Semi => {
6210
- self . span_err ( self . span , "expected identifier or `{` or `*`, found `;`" ) ;
6211
- }
6212
-
6213
- _ => break
6170
+ Ok ( P ( spanned ( lo, self . span . hi , ViewPathGlob ( prefix) ) ) )
6171
+ } else {
6172
+ let items = self . parse_path_list_items ( ) ?;
6173
+ Ok ( P ( spanned ( lo, self . span . hi , ViewPathList ( prefix, items) ) ) )
6214
6174
}
6175
+ } else {
6176
+ // `foo::bar` or `foo::bar as baz`
6177
+ let rename = self . parse_rename ( ) ?.
6178
+ unwrap_or ( prefix. segments . last ( ) . unwrap ( ) . identifier ) ;
6179
+ Ok ( P ( spanned ( lo, self . last_span . hi , ViewPathSimple ( rename, prefix) ) ) )
6215
6180
}
6216
6181
}
6217
- let mut rename_to = path[ path. len ( ) - 1 ] ;
6218
- let path = ast:: Path {
6219
- span : mk_sp ( lo, self . last_span . hi ) ,
6220
- global : is_global,
6221
- segments : path. into_iter ( ) . map ( |identifier| {
6222
- ast:: PathSegment {
6223
- identifier : identifier,
6224
- parameters : ast:: PathParameters :: none ( ) ,
6225
- }
6226
- } ) . collect ( )
6227
- } ;
6228
- rename_to = self . parse_rename ( ) ?. unwrap_or ( rename_to) ;
6229
- Ok ( P ( spanned ( lo, self . last_span . hi , ViewPathSimple ( rename_to, path) ) ) )
6230
6182
}
6231
6183
6232
6184
fn parse_rename ( & mut self ) -> PResult < ' a , Option < Ident > > {
0 commit comments