@@ -35,7 +35,7 @@ use syntax::ast::{Name, Ident};
3535use syntax:: attr;
3636
3737use 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 } ;
3939use syntax:: ext:: base:: { MacroKind , SyntaxExtension } ;
4040use syntax:: ext:: base:: Determinacy :: Undetermined ;
4141use syntax:: ext:: hygiene:: Mark ;
@@ -83,12 +83,6 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, IsMacroExport)
8383 }
8484}
8585
86- #[ derive( Default , PartialEq , Eq ) ]
87- struct LegacyMacroImports {
88- import_all : Option < Span > ,
89- imports : Vec < ( Name , Span ) > ,
90- }
91-
9286impl < ' a , ' cl > Resolver < ' a , ' cl > {
9387 /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
9488 /// otherwise, reports an error.
@@ -117,23 +111,23 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
117111
118112 fn build_reduced_graph_for_use_tree (
119113 & mut self ,
120- root_use_tree : & ast:: UseTree ,
121- root_id : NodeId ,
114+ // This particular use tree
122115 use_tree : & ast:: UseTree ,
123116 id : NodeId ,
124- vis : ty:: Visibility ,
125117 parent_prefix : & [ Segment ] ,
126- mut uniform_paths_canary_emitted : bool ,
127118 nested : bool ,
119+ mut uniform_paths_canary_emitted : bool ,
120+ // The whole `use` item
121+ parent_scope : ParentScope < ' a > ,
128122 item : & Item ,
129- expansion : Mark ,
123+ vis : ty:: Visibility ,
124+ root_span : Span ,
130125 ) {
131126 debug ! ( "build_reduced_graph_for_use_tree(parent_prefix={:?}, \
132127 uniform_paths_canary_emitted={}, \
133128 use_tree={:?}, nested={})",
134129 parent_prefix, uniform_paths_canary_emitted, use_tree, nested) ;
135130
136- let is_prelude = attr:: contains_name ( & item. attrs , "prelude_import" ) ;
137131 let uniform_paths =
138132 self . session . rust_2018 ( ) &&
139133 self . session . features_untracked ( ) . uniform_paths ;
@@ -221,10 +215,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
221215 subclass,
222216 source. ident . span ,
223217 id,
224- root_use_tree . span ,
225- root_id ,
218+ root_span ,
219+ item . id ,
226220 ty:: Visibility :: Invisible ,
227- expansion ,
221+ parent_scope . clone ( ) ,
228222 true , // is_uniform_paths_canary
229223 ) ;
230224 } ;
@@ -259,6 +253,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
259253 uniform_paths_canary_emitted = true ;
260254 }
261255
256+ let empty_for_self = |prefix : & [ Segment ] | {
257+ prefix. is_empty ( ) ||
258+ prefix. len ( ) == 1 && prefix[ 0 ] . ident . name == keywords:: CrateRoot . name ( )
259+ } ;
262260 match use_tree. kind {
263261 ast:: UseTreeKind :: Simple ( rename, ..) => {
264262 let mut ident = use_tree. ident ( ) ;
@@ -271,10 +269,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
271269 if source. ident . name == keywords:: SelfValue . name ( ) {
272270 type_ns_only = true ;
273271
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) {
278273 resolve_error (
279274 self ,
280275 use_tree. span ,
@@ -351,27 +346,27 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
351346 subclass,
352347 use_tree. span ,
353348 id,
354- root_use_tree . span ,
355- root_id ,
349+ root_span ,
350+ item . id ,
356351 vis,
357- expansion ,
352+ parent_scope ,
358353 false , // is_uniform_paths_canary
359354 ) ;
360355 }
361356 ast:: UseTreeKind :: Glob => {
362357 let subclass = GlobImport {
363- is_prelude,
358+ is_prelude : attr :: contains_name ( & item . attrs , "prelude_import" ) ,
364359 max_vis : Cell :: new ( ty:: Visibility :: Invisible ) ,
365360 } ;
366361 self . add_import_directive (
367362 prefix,
368363 subclass,
369364 use_tree. span ,
370365 id,
371- root_use_tree . span ,
372- root_id ,
366+ root_span ,
367+ item . id ,
373368 vis,
374- expansion ,
369+ parent_scope ,
375370 false , // is_uniform_paths_canary
376371 ) ;
377372 }
@@ -400,42 +395,55 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
400395
401396 for & ( ref tree, id) in items {
402397 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,
413426 ) ;
414427 }
415428 }
416429 }
417430 }
418431
419432 /// 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 ;
422436 let ident = item. ident ;
423437 let sp = item. span ;
424438 let vis = self . resolve_visibility ( & item. vis ) ;
425439
426440 match item. node {
427441 ItemKind :: Use ( ref use_tree) => {
428442 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 ,
439447 ) ;
440448 }
441449
@@ -448,7 +456,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
448456 self . injected_crate = Some ( module) ;
449457 }
450458
451- let used = self . process_legacy_macro_imports ( item, module, expansion ) ;
459+ let used = self . process_legacy_macro_imports ( item, module, & parent_scope ) ;
452460 let binding =
453461 ( module, ty:: Visibility :: Public , sp, expansion) . to_name_binding ( self . arenas ) ;
454462 if ptr:: eq ( self . current_module , self . graph_root ) {
@@ -473,7 +481,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
473481 let directive = self . arenas . alloc_import_directive ( ImportDirective {
474482 root_id : item. id ,
475483 id : item. id ,
476- parent ,
484+ parent_scope ,
477485 imported_module : Cell :: new ( Some ( ModuleOrUniformRoot :: Module ( module) ) ) ,
478486 subclass : ImportDirectiveSubclass :: ExternCrate {
479487 source : orig_name,
@@ -483,7 +491,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
483491 span : item. span ,
484492 module_path : Vec :: new ( ) ,
485493 vis : Cell :: new ( vis) ,
486- expansion,
487494 used : Cell :: new ( used) ,
488495 is_uniform_paths_canary : false ,
489496 } ) ;
@@ -856,43 +863,61 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
856863 }
857864
858865 // 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+ }
869894 }
870895
871- let ( graph_root , arenas) = ( self . graph_root , self . arenas ) ;
896+ let arenas = self . arenas ;
872897 let macro_use_directive = |span| arenas. alloc_import_directive ( ImportDirective {
873898 root_id : item. id ,
874899 id : item. id ,
875- parent : graph_root ,
900+ parent_scope : parent_scope . clone ( ) ,
876901 imported_module : Cell :: new ( Some ( ModuleOrUniformRoot :: Module ( module) ) ) ,
877902 subclass : ImportDirectiveSubclass :: MacroUse ,
878903 root_span : span,
879904 span,
880905 module_path : Vec :: new ( ) ,
881906 vis : Cell :: new ( ty:: Visibility :: Restricted ( DefId :: local ( CRATE_DEF_INDEX ) ) ) ,
882- expansion,
883907 used : Cell :: new ( false ) ,
884908 is_uniform_paths_canary : false ,
885909 } ) ;
886910
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 {
888913 let directive = macro_use_directive ( span) ;
889914 self . potentially_unused_imports . push ( directive) ;
890915 module. for_each_child ( |ident, ns, binding| if ns == MacroNS {
891916 let imported_binding = self . import ( binding, directive) ;
892917 self . legacy_import_macro ( ident. name , imported_binding, span, allow_shadowing) ;
893918 } ) ;
894919 } else {
895- for ( name, span) in legacy_imports . imports {
920+ for ( name, span) in single_imports . iter ( ) . cloned ( ) {
896921 let ident = Ident :: with_empty_ctxt ( name) ;
897922 let result = self . resolve_ident_in_module (
898923 ModuleOrUniformRoot :: Module ( module) ,
@@ -911,7 +936,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
911936 }
912937 }
913938 }
914- used
939+ import_all . is_some ( ) || !single_imports . is_empty ( )
915940 }
916941
917942 // does this attribute list contain "macro_use"?
@@ -937,25 +962,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
937962
938963 false
939964 }
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- }
959965}
960966
961967pub struct BuildReducedGraphVisitor < ' a , ' b : ' a , ' c : ' b > {
@@ -1010,7 +1016,13 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
10101016
10111017 let orig_current_module = self . resolver . current_module ;
10121018 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) ;
10141026 visit:: walk_item ( self , item) ;
10151027 self . resolver . current_module = orig_current_module;
10161028 if !macro_use {
0 commit comments