@@ -35,7 +35,7 @@ use syntax::ast::{Name, Ident};
35
35
use syntax:: attr;
36
36
37
37
use syntax:: ast:: { self , Block , ForeignItem , ForeignItemKind , Item , ItemKind , NodeId } ;
38
- use syntax:: ast:: { Mutability , StmtKind , TraitItem , TraitItemKind , Variant } ;
38
+ use syntax:: ast:: { MetaItemKind , Mutability , StmtKind , TraitItem , TraitItemKind , Variant } ;
39
39
use syntax:: ext:: base:: { MacroKind , SyntaxExtension } ;
40
40
use syntax:: ext:: base:: Determinacy :: Undetermined ;
41
41
use syntax:: ext:: hygiene:: Mark ;
@@ -83,12 +83,6 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, IsMacroExport)
83
83
}
84
84
}
85
85
86
- #[ derive( Default , PartialEq , Eq ) ]
87
- struct LegacyMacroImports {
88
- import_all : Option < Span > ,
89
- imports : Vec < ( Name , Span ) > ,
90
- }
91
-
92
86
impl < ' a , ' cl > Resolver < ' a , ' cl > {
93
87
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
94
88
/// otherwise, reports an error.
@@ -117,23 +111,23 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
117
111
118
112
fn build_reduced_graph_for_use_tree (
119
113
& mut self ,
120
- root_use_tree : & ast:: UseTree ,
121
- root_id : NodeId ,
114
+ // This particular use tree
122
115
use_tree : & ast:: UseTree ,
123
116
id : NodeId ,
124
- vis : ty:: Visibility ,
125
117
parent_prefix : & [ Segment ] ,
126
- mut uniform_paths_canary_emitted : bool ,
127
118
nested : bool ,
119
+ mut uniform_paths_canary_emitted : bool ,
120
+ // The whole `use` item
121
+ parent_scope : ParentScope < ' a > ,
128
122
item : & Item ,
129
- expansion : Mark ,
123
+ vis : ty:: Visibility ,
124
+ root_span : Span ,
130
125
) {
131
126
debug ! ( "build_reduced_graph_for_use_tree(parent_prefix={:?}, \
132
127
uniform_paths_canary_emitted={}, \
133
128
use_tree={:?}, nested={})",
134
129
parent_prefix, uniform_paths_canary_emitted, use_tree, nested) ;
135
130
136
- let is_prelude = attr:: contains_name ( & item. attrs , "prelude_import" ) ;
137
131
let uniform_paths =
138
132
self . session . rust_2018 ( ) &&
139
133
self . session . features_untracked ( ) . uniform_paths ;
@@ -221,10 +215,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
221
215
subclass,
222
216
source. ident . span ,
223
217
id,
224
- root_use_tree . span ,
225
- root_id ,
218
+ root_span ,
219
+ item . id ,
226
220
ty:: Visibility :: Invisible ,
227
- expansion ,
221
+ parent_scope . clone ( ) ,
228
222
true , // is_uniform_paths_canary
229
223
) ;
230
224
} ;
@@ -259,6 +253,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
259
253
uniform_paths_canary_emitted = true ;
260
254
}
261
255
256
+ let empty_for_self = |prefix : & [ Segment ] | {
257
+ prefix. is_empty ( ) ||
258
+ prefix. len ( ) == 1 && prefix[ 0 ] . ident . name == keywords:: CrateRoot . name ( )
259
+ } ;
262
260
match use_tree. kind {
263
261
ast:: UseTreeKind :: Simple ( rename, ..) => {
264
262
let mut ident = use_tree. ident ( ) ;
@@ -271,10 +269,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
271
269
if source. ident . name == keywords:: SelfValue . name ( ) {
272
270
type_ns_only = true ;
273
271
274
- let empty_prefix = module_path. last ( ) . map_or ( true , |seg| {
275
- seg. ident . name == keywords:: CrateRoot . name ( )
276
- } ) ;
277
- if empty_prefix {
272
+ if empty_for_self ( & module_path) {
278
273
resolve_error (
279
274
self ,
280
275
use_tree. span ,
@@ -351,27 +346,27 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
351
346
subclass,
352
347
use_tree. span ,
353
348
id,
354
- root_use_tree . span ,
355
- root_id ,
349
+ root_span ,
350
+ item . id ,
356
351
vis,
357
- expansion ,
352
+ parent_scope ,
358
353
false , // is_uniform_paths_canary
359
354
) ;
360
355
}
361
356
ast:: UseTreeKind :: Glob => {
362
357
let subclass = GlobImport {
363
- is_prelude,
358
+ is_prelude : attr :: contains_name ( & item . attrs , "prelude_import" ) ,
364
359
max_vis : Cell :: new ( ty:: Visibility :: Invisible ) ,
365
360
} ;
366
361
self . add_import_directive (
367
362
prefix,
368
363
subclass,
369
364
use_tree. span ,
370
365
id,
371
- root_use_tree . span ,
372
- root_id ,
366
+ root_span ,
367
+ item . id ,
373
368
vis,
374
- expansion ,
369
+ parent_scope ,
375
370
false , // is_uniform_paths_canary
376
371
) ;
377
372
}
@@ -400,42 +395,55 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
400
395
401
396
for & ( ref tree, id) in items {
402
397
self . build_reduced_graph_for_use_tree (
403
- root_use_tree,
404
- root_id,
405
- tree,
406
- id,
407
- vis,
408
- & prefix,
409
- uniform_paths_canary_emitted,
410
- true ,
411
- item,
412
- expansion,
398
+ // This particular use tree
399
+ tree, id, & prefix, true , uniform_paths_canary_emitted,
400
+ // The whole `use` item
401
+ parent_scope. clone ( ) , item, vis, root_span,
402
+ ) ;
403
+ }
404
+
405
+ // Empty groups `a::b::{}` are turned into synthetic `self` imports
406
+ // `a::b::c::{self as _}`, so that their prefixes are correctly
407
+ // resolved and checked for privacy/stability/etc.
408
+ if items. is_empty ( ) && !empty_for_self ( & prefix) {
409
+ let new_span = prefix[ prefix. len ( ) - 1 ] . ident . span ;
410
+ let tree = ast:: UseTree {
411
+ prefix : ast:: Path :: from_ident (
412
+ Ident :: new ( keywords:: SelfValue . name ( ) , new_span)
413
+ ) ,
414
+ kind : ast:: UseTreeKind :: Simple (
415
+ Some ( Ident :: new ( keywords:: Underscore . name ( ) . gensymed ( ) , new_span) ) ,
416
+ ast:: DUMMY_NODE_ID ,
417
+ ast:: DUMMY_NODE_ID ,
418
+ ) ,
419
+ span : use_tree. span ,
420
+ } ;
421
+ self . build_reduced_graph_for_use_tree (
422
+ // This particular use tree
423
+ & tree, id, & prefix, true , uniform_paths_canary_emitted,
424
+ // The whole `use` item
425
+ parent_scope. clone ( ) , item, ty:: Visibility :: Invisible , root_span,
413
426
) ;
414
427
}
415
428
}
416
429
}
417
430
}
418
431
419
432
/// Constructs the reduced graph for one item.
420
- fn build_reduced_graph_for_item ( & mut self , item : & Item , expansion : Mark ) {
421
- let parent = self . current_module ;
433
+ fn build_reduced_graph_for_item ( & mut self , item : & Item , parent_scope : ParentScope < ' a > ) {
434
+ let parent = parent_scope. module ;
435
+ let expansion = parent_scope. expansion ;
422
436
let ident = item. ident ;
423
437
let sp = item. span ;
424
438
let vis = self . resolve_visibility ( & item. vis ) ;
425
439
426
440
match item. node {
427
441
ItemKind :: Use ( ref use_tree) => {
428
442
self . build_reduced_graph_for_use_tree (
429
- use_tree,
430
- item. id ,
431
- use_tree,
432
- item. id ,
433
- vis,
434
- & [ ] ,
435
- false , // uniform_paths_canary_emitted
436
- false ,
437
- item,
438
- expansion,
443
+ // This particular use tree
444
+ use_tree, item. id , & [ ] , false , false ,
445
+ // The whole `use` item
446
+ parent_scope, item, vis, use_tree. span ,
439
447
) ;
440
448
}
441
449
@@ -448,7 +456,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
448
456
self . injected_crate = Some ( module) ;
449
457
}
450
458
451
- let used = self . process_legacy_macro_imports ( item, module, expansion ) ;
459
+ let used = self . process_legacy_macro_imports ( item, module, & parent_scope ) ;
452
460
let binding =
453
461
( module, ty:: Visibility :: Public , sp, expansion) . to_name_binding ( self . arenas ) ;
454
462
if ptr:: eq ( self . current_module , self . graph_root ) {
@@ -473,7 +481,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
473
481
let directive = self . arenas . alloc_import_directive ( ImportDirective {
474
482
root_id : item. id ,
475
483
id : item. id ,
476
- parent ,
484
+ parent_scope ,
477
485
imported_module : Cell :: new ( Some ( ModuleOrUniformRoot :: Module ( module) ) ) ,
478
486
subclass : ImportDirectiveSubclass :: ExternCrate {
479
487
source : orig_name,
@@ -483,7 +491,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
483
491
span : item. span ,
484
492
module_path : Vec :: new ( ) ,
485
493
vis : Cell :: new ( vis) ,
486
- expansion,
487
494
used : Cell :: new ( used) ,
488
495
is_uniform_paths_canary : false ,
489
496
} ) ;
@@ -856,43 +863,61 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
856
863
}
857
864
858
865
// This returns true if we should consider the underlying `extern crate` to be used.
859
- fn process_legacy_macro_imports ( & mut self , item : & Item , module : Module < ' a > , expansion : Mark )
860
- -> bool {
861
- let allow_shadowing = expansion == Mark :: root ( ) ;
862
- let legacy_imports = self . legacy_macro_imports ( & item. attrs ) ;
863
- let used = legacy_imports != LegacyMacroImports :: default ( ) ;
864
-
865
- // `#[macro_use]` is only allowed at the crate root.
866
- if self . current_module . parent . is_some ( ) && used {
867
- span_err ! ( self . session, item. span, E0468 ,
868
- "an `extern crate` loading macros must be at the crate root" ) ;
866
+ fn process_legacy_macro_imports ( & mut self , item : & Item , module : Module < ' a > ,
867
+ parent_scope : & ParentScope < ' a > ) -> bool {
868
+ let mut import_all = None ;
869
+ let mut single_imports = Vec :: new ( ) ;
870
+ for attr in & item. attrs {
871
+ if attr. check_name ( "macro_use" ) {
872
+ if self . current_module . parent . is_some ( ) {
873
+ span_err ! ( self . session, item. span, E0468 ,
874
+ "an `extern crate` loading macros must be at the crate root" ) ;
875
+ }
876
+ let ill_formed = |span| span_err ! ( self . session, span, E0466 , "bad macro import" ) ;
877
+ match attr. meta ( ) {
878
+ Some ( meta) => match meta. node {
879
+ MetaItemKind :: Word => {
880
+ import_all = Some ( meta. span ) ;
881
+ break ;
882
+ }
883
+ MetaItemKind :: List ( nested_metas) => for nested_meta in nested_metas {
884
+ match nested_meta. word ( ) {
885
+ Some ( word) => single_imports. push ( ( word. name ( ) , word. span ) ) ,
886
+ None => ill_formed ( nested_meta. span ) ,
887
+ }
888
+ }
889
+ MetaItemKind :: NameValue ( ..) => ill_formed ( meta. span ) ,
890
+ }
891
+ None => ill_formed ( attr. span ( ) ) ,
892
+ }
893
+ }
869
894
}
870
895
871
- let ( graph_root , arenas) = ( self . graph_root , self . arenas ) ;
896
+ let arenas = self . arenas ;
872
897
let macro_use_directive = |span| arenas. alloc_import_directive ( ImportDirective {
873
898
root_id : item. id ,
874
899
id : item. id ,
875
- parent : graph_root ,
900
+ parent_scope : parent_scope . clone ( ) ,
876
901
imported_module : Cell :: new ( Some ( ModuleOrUniformRoot :: Module ( module) ) ) ,
877
902
subclass : ImportDirectiveSubclass :: MacroUse ,
878
903
root_span : span,
879
904
span,
880
905
module_path : Vec :: new ( ) ,
881
906
vis : Cell :: new ( ty:: Visibility :: Restricted ( DefId :: local ( CRATE_DEF_INDEX ) ) ) ,
882
- expansion,
883
907
used : Cell :: new ( false ) ,
884
908
is_uniform_paths_canary : false ,
885
909
} ) ;
886
910
887
- if let Some ( span) = legacy_imports. import_all {
911
+ let allow_shadowing = parent_scope. expansion == Mark :: root ( ) ;
912
+ if let Some ( span) = import_all {
888
913
let directive = macro_use_directive ( span) ;
889
914
self . potentially_unused_imports . push ( directive) ;
890
915
module. for_each_child ( |ident, ns, binding| if ns == MacroNS {
891
916
let imported_binding = self . import ( binding, directive) ;
892
917
self . legacy_import_macro ( ident. name , imported_binding, span, allow_shadowing) ;
893
918
} ) ;
894
919
} else {
895
- for ( name, span) in legacy_imports . imports {
920
+ for ( name, span) in single_imports . iter ( ) . cloned ( ) {
896
921
let ident = Ident :: with_empty_ctxt ( name) ;
897
922
let result = self . resolve_ident_in_module (
898
923
ModuleOrUniformRoot :: Module ( module) ,
@@ -911,7 +936,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
911
936
}
912
937
}
913
938
}
914
- used
939
+ import_all . is_some ( ) || !single_imports . is_empty ( )
915
940
}
916
941
917
942
// does this attribute list contain "macro_use"?
@@ -937,25 +962,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
937
962
938
963
false
939
964
}
940
-
941
- fn legacy_macro_imports ( & mut self , attrs : & [ ast:: Attribute ] ) -> LegacyMacroImports {
942
- let mut imports = LegacyMacroImports :: default ( ) ;
943
- for attr in attrs {
944
- if attr. check_name ( "macro_use" ) {
945
- match attr. meta_item_list ( ) {
946
- Some ( names) => for attr in names {
947
- if let Some ( word) = attr. word ( ) {
948
- imports. imports . push ( ( word. name ( ) , attr. span ( ) ) ) ;
949
- } else {
950
- span_err ! ( self . session, attr. span( ) , E0466 , "bad macro import" ) ;
951
- }
952
- } ,
953
- None => imports. import_all = Some ( attr. span ) ,
954
- }
955
- }
956
- }
957
- imports
958
- }
959
965
}
960
966
961
967
pub struct BuildReducedGraphVisitor < ' a , ' b : ' a , ' c : ' b > {
@@ -1010,7 +1016,13 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
1010
1016
1011
1017
let orig_current_module = self . resolver . current_module ;
1012
1018
let orig_current_legacy_scope = self . current_legacy_scope ;
1013
- self . resolver . build_reduced_graph_for_item ( item, self . expansion ) ;
1019
+ let parent_scope = ParentScope {
1020
+ module : self . resolver . current_module ,
1021
+ expansion : self . expansion ,
1022
+ legacy : self . current_legacy_scope ,
1023
+ derives : Vec :: new ( ) ,
1024
+ } ;
1025
+ self . resolver . build_reduced_graph_for_item ( item, parent_scope) ;
1014
1026
visit:: walk_item ( self , item) ;
1015
1027
self . resolver . current_module = orig_current_module;
1016
1028
if !macro_use {
0 commit comments