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