@@ -436,6 +436,43 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
436
436
ev : self ,
437
437
}
438
438
}
439
+
440
+
441
+ /// Given the path segments of a `ItemKind::Use`, then we need
442
+ /// to update the visibility of the intermediate use so that it isn't linted
443
+ /// by `unreachable_pub`.
444
+ ///
445
+ /// This isn't trivial as `path.def` has the `DefId` of the eventual target
446
+ /// of the use statement not of the next intermediate use statement.
447
+ ///
448
+ /// To do this, consider the last two segments of the path to our intermediate
449
+ /// use statement. We expect the penultimate segment to be a module and the
450
+ /// last segment to be the name of the item we are exporting. We can then
451
+ /// look at the items contained in the module for the use statement with that
452
+ /// name and update that item's visibility.
453
+ ///
454
+ /// FIXME: This solution won't work with glob imports and doesn't respect
455
+ /// namespaces. See <https://github.com/rust-lang/rust/pull/57922#discussion_r251234202>.
456
+ fn update_visibility_of_intermediate_use_statements ( & mut self , segments : & [ hir:: PathSegment ] ) {
457
+ if let Some ( [ module, segment] ) = segments. rchunks_exact ( 2 ) . next ( ) {
458
+ if let Some ( item) = module. def
459
+ . and_then ( |def| def. mod_def_id ( ) )
460
+ . and_then ( |def_id| self . tcx . hir ( ) . as_local_node_id ( def_id) )
461
+ . map ( |module_node_id| self . tcx . hir ( ) . expect_item ( module_node_id) )
462
+ {
463
+ if let hir:: ItemKind :: Mod ( m) = & item. node {
464
+ for item_id in m. item_ids . as_ref ( ) {
465
+ let item = self . tcx . hir ( ) . expect_item ( item_id. id ) ;
466
+ let def_id = self . tcx . hir ( ) . local_def_id ( item_id. id ) ;
467
+ if !self . tcx . hygienic_eq ( segment. ident , item. ident , def_id) { continue ; }
468
+ if let hir:: ItemKind :: Use ( ..) = item. node {
469
+ self . update ( item. id , Some ( AccessLevel :: Exported ) ) ;
470
+ }
471
+ }
472
+ }
473
+ }
474
+ }
475
+ }
439
476
}
440
477
441
478
impl < ' a , ' tcx > Visitor < ' tcx > for EmbargoVisitor < ' a , ' tcx > {
@@ -522,8 +559,14 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
522
559
hir:: ItemKind :: ExternCrate ( ..) => { }
523
560
// All nested items are checked by `visit_item`.
524
561
hir:: ItemKind :: Mod ( ..) => { }
525
- // Re-exports are handled in `visit_mod`.
526
- hir:: ItemKind :: Use ( ..) => { }
562
+ // Re-exports are handled in `visit_mod`. However, in order to avoid looping over
563
+ // all of the items of a mod in `visit_mod` looking for use statements, we handle
564
+ // making sure that intermediate use statements have their visibilities updated here.
565
+ hir:: ItemKind :: Use ( ref path, _) => {
566
+ if item_level. is_some ( ) {
567
+ self . update_visibility_of_intermediate_use_statements ( path. segments . as_ref ( ) ) ;
568
+ }
569
+ }
527
570
// The interface is empty.
528
571
hir:: ItemKind :: GlobalAsm ( ..) => { }
529
572
hir:: ItemKind :: Existential ( ..) => {
0 commit comments