diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 7dbbd4c34ea7d..48e2f897d5ed5 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -23,6 +23,7 @@ // - `check_crate` finally emits the diagnostics based on the data generated // in the last step +use crate::fluent_generated as fluent; use crate::imports::ImportKind; use crate::module_to_string; use crate::Resolver; @@ -487,4 +488,20 @@ impl Resolver<'_, '_> { ); } } + + pub(crate) fn check_no_reexports(&mut self) { + for import in &self.no_reexports_imports { + let ImportKind::Glob { id, .. } = import.kind else { + unreachable!(); + }; + if !import.used.get() { + self.lint_buffer.buffer_lint( + UNUSED_IMPORTS, + id, + import.span, + fluent::resolve_glob_import_doesnt_reexport, + ); + } + } + } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 820ac9ef61b02..e94c4d7563fea 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -8,7 +8,7 @@ use crate::errors::{ ItemsInTraitsAreNotImportable, }; use crate::Determinacy::{self, *}; -use crate::{fluent_generated as fluent, Namespace::*}; +use crate::Namespace::*; use crate::{module_to_string, names_to_string, ImportSuggestion}; use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet}; @@ -965,7 +965,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { id, .. } => (source, target, source_bindings, target_bindings, type_ns_only, id), - ImportKind::Glob { is_prelude, ref max_vis, id } => { + ImportKind::Glob { is_prelude, ref max_vis, .. } => { if import.module_path.len() <= 1 { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. @@ -992,7 +992,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && let Some(max_vis) = max_vis.get() && !max_vis.is_at_least(import.expect_vis(), self.tcx) { - self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, fluent::resolve_glob_import_doesnt_reexport); + self.no_reexports_imports.push(import); } return None; } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 949c6ab5ac0c1..50bd63dd832be 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -954,6 +954,8 @@ pub struct Resolver<'a, 'tcx> { /// All non-determined imports. indeterminate_imports: Vec>, + no_reexports_imports: Vec>, + // Spans for local variables found during pattern resolution. // Used for suggestions during error reporting. pat_span_map: NodeMap, @@ -1336,6 +1338,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { determined_imports: Vec::new(), indeterminate_imports: Vec::new(), + no_reexports_imports: Vec::new(), + pat_span_map: Default::default(), partial_res_map: Default::default(), import_res_map: Default::default(), @@ -1605,6 +1609,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.tcx.sess.time("late_resolve_crate", || self.late_resolve_crate(krate)); self.tcx.sess.time("resolve_main", || self.resolve_main()); self.tcx.sess.time("resolve_check_unused", || self.check_unused(krate)); + self.tcx.sess.time("resolve_check_no_reexports", || self.check_no_reexports()); self.tcx.sess.time("resolve_report_errors", || self.report_errors(krate)); self.tcx .sess diff --git a/tests/ui/imports/reexports-macros.rs b/tests/ui/imports/reexports-macros.rs new file mode 100644 index 0000000000000..f8cf221e70ae1 --- /dev/null +++ b/tests/ui/imports/reexports-macros.rs @@ -0,0 +1,14 @@ +// check-pass + +#![deny(unused_imports)] + +mod a { + mod b { + pub(crate) const C: &str = "123"; + } + pub use self::b::*; +} + +fn main() { + let _ = a::C; +}