@@ -204,25 +204,7 @@ impl<'a> Parser<'a> {
204
204
let mut def = || mem:: replace ( def, Defaultness :: Final ) ;
205
205
206
206
let info = if self . eat_keyword ( kw:: Use ) {
207
- // USE ITEM
208
- let tree = self . parse_use_tree ( ) ?;
209
-
210
- // If wildcard or glob-like brace syntax doesn't have `;`,
211
- // the user may not know `*` or `{}` should be the last.
212
- if let Err ( mut e) = self . expect_semi ( ) {
213
- match tree. kind {
214
- UseTreeKind :: Glob => {
215
- e. note ( "the wildcard token must be last on the path" ) ;
216
- }
217
- UseTreeKind :: Nested ( ..) => {
218
- e. note ( "glob-like brace syntax must be last on the path" ) ;
219
- }
220
- _ => ( ) ,
221
- }
222
- return Err ( e) ;
223
- }
224
-
225
- ( Ident :: empty ( ) , ItemKind :: Use ( tree) )
207
+ self . parse_use_item ( ) ?
226
208
} else if self . check_fn_front_matter ( def_final) {
227
209
// FUNCTION ITEM
228
210
let ( ident, sig, generics, body) = self . parse_fn ( attrs, fn_parse_mode, lo, vis) ?;
@@ -288,7 +270,12 @@ impl<'a> Parser<'a> {
288
270
} else if let IsMacroRulesItem :: Yes { has_bang } = self . is_macro_rules_item ( ) {
289
271
// MACRO_RULES ITEM
290
272
self . parse_item_macro_rules ( vis, has_bang) ?
291
- } else if vis. kind . is_pub ( ) && self . isnt_macro_invocation ( ) {
273
+ } else if self . isnt_macro_invocation ( )
274
+ && ( self . token . is_ident_named ( Symbol :: intern ( "import" ) )
275
+ || self . token . is_ident_named ( Symbol :: intern ( "using" ) ) )
276
+ {
277
+ return self . recover_import_as_use ( ) ;
278
+ } else if self . isnt_macro_invocation ( ) && vis. kind . is_pub ( ) {
292
279
self . recover_missing_kw_before_item ( ) ?;
293
280
return Ok ( None ) ;
294
281
} else if macros_allowed && self . check_path ( ) {
@@ -300,6 +287,48 @@ impl<'a> Parser<'a> {
300
287
Ok ( Some ( info) )
301
288
}
302
289
290
+ fn recover_import_as_use ( & mut self ) -> PResult < ' a , Option < ( Ident , ItemKind ) > > {
291
+ let span = self . token . span ;
292
+ let token_name = super :: token_descr ( & self . token ) ;
293
+ let snapshot = self . create_snapshot_for_diagnostic ( ) ;
294
+ self . bump ( ) ;
295
+ match self . parse_use_item ( ) {
296
+ Ok ( u) => {
297
+ self . struct_span_err ( span, format ! ( "expected item, found {token_name}" ) )
298
+ . span_suggestion_short (
299
+ span,
300
+ "items are imported using the `use` keyword" ,
301
+ "use" . to_owned ( ) ,
302
+ Applicability :: MachineApplicable ,
303
+ )
304
+ . emit ( ) ;
305
+ Ok ( Some ( u) )
306
+ }
307
+ Err ( e) => {
308
+ e. cancel ( ) ;
309
+ self . restore_snapshot ( snapshot) ;
310
+ Ok ( None )
311
+ }
312
+ }
313
+ }
314
+
315
+ fn parse_use_item ( & mut self ) -> PResult < ' a , ( Ident , ItemKind ) > {
316
+ let tree = self . parse_use_tree ( ) ?;
317
+ if let Err ( mut e) = self . expect_semi ( ) {
318
+ match tree. kind {
319
+ UseTreeKind :: Glob => {
320
+ e. note ( "the wildcard token must be last on the path" ) ;
321
+ }
322
+ UseTreeKind :: Nested ( ..) => {
323
+ e. note ( "glob-like brace syntax must be last on the path" ) ;
324
+ }
325
+ _ => ( ) ,
326
+ }
327
+ return Err ( e) ;
328
+ }
329
+ Ok ( ( Ident :: empty ( ) , ItemKind :: Use ( tree) ) )
330
+ }
331
+
303
332
/// When parsing a statement, would the start of a path be an item?
304
333
pub ( super ) fn is_path_start_item ( & mut self ) -> bool {
305
334
self . is_kw_followed_by_ident ( kw:: Union ) // no: `union::b`, yes: `union U { .. }`
0 commit comments