resolve: Factor out reporting of "cannot reexport" errors into a separate function

This commit is contained in:
Vadim Petrochenkov
2026-04-30 21:38:02 +03:00
parent 1d72d7e813
commit cf636ec649
+61 -56
View File
@@ -9,7 +9,9 @@
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diagnostic, MultiSpan, pluralize, struct_span_code_err};
use rustc_errors::{
Applicability, BufferedEarlyLint, Diagnostic, MultiSpan, pluralize, struct_span_code_err,
};
use rustc_hir::Attribute;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs};
@@ -19,6 +21,7 @@
use rustc_middle::span_bug;
use rustc_middle::ty::{TyCtxt, Visibility};
use rustc_session::errors::feature_err;
use rustc_session::lint::LintId;
use rustc_session::lint::builtin::{
AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS,
PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS,
@@ -1515,7 +1518,6 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
let mut reexport_error = None;
let mut any_successful_reexport = false;
let mut crate_private_reexport = false;
self.per_ns(|this, ns| {
let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) else {
return;
@@ -1523,11 +1525,6 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
if import.vis.greater_than(binding.vis(), this.tcx) {
reexport_error = Some((ns, binding));
if let Visibility::Restricted(binding_def_id) = binding.vis()
&& binding_def_id.is_top_level_module()
{
crate_private_reexport = true;
}
} else {
any_successful_reexport = true;
}
@@ -1536,55 +1533,8 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
// All namespaces must be re-exported with extra visibility for an error to occur.
if !any_successful_reexport {
let (ns, binding) = reexport_error.unwrap();
if let Some(extern_crate_id) =
pub_use_of_private_extern_crate_hack(import.summary(), binding)
{
let extern_crate_sp = self.tcx.source_span(self.local_def_id(extern_crate_id));
self.lint_buffer.buffer_lint(
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
import_id,
import.span,
crate::errors::PrivateExternCrateReexport {
ident,
sugg: extern_crate_sp.shrink_to_lo(),
},
);
} else if ns == TypeNS {
let err = if crate_private_reexport {
self.dcx()
.create_err(CannotBeReexportedCratePublicNS { span: import.span, ident })
} else {
self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
};
err.emit();
} else {
let mut err = if crate_private_reexport {
self.dcx()
.create_err(CannotBeReexportedCratePublic { span: import.span, ident })
} else {
self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident })
};
match binding.kind {
DeclKind::Def(Res::Def(DefKind::Macro(_), def_id))
// exclude decl_macro
if self.get_macro_by_def_id(def_id).macro_rules =>
{
err.subdiagnostic( ConsiderAddingMacroExport {
span: binding.span,
});
err.subdiagnostic( ConsiderMarkingAsPubCrate {
vis_span: import.vis_span,
});
}
_ => {
err.subdiagnostic( ConsiderMarkingAsPub {
span: import.span,
ident,
});
}
}
err.emit();
if let Some(lint) = self.report_cannot_reexport(import, binding, ident, ns) {
self.lint_buffer.add_early_lint(lint);
}
}
@@ -1613,6 +1563,61 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
None
}
fn report_cannot_reexport(
&self,
import: Import<'ra>,
decl: Decl<'ra>,
ident: Ident,
ns: Namespace,
) -> Option<BufferedEarlyLint> {
let crate_private_reexport = match decl.vis() {
Visibility::Restricted(def_id) if def_id.is_top_level_module() => true,
_ => false,
};
if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import.summary(), decl)
{
let ImportKind::Single { id, .. } = import.kind else { unreachable!() };
let sugg = self.tcx.source_span(self.local_def_id(extern_crate_id)).shrink_to_lo();
let diagnostic = crate::errors::PrivateExternCrateReexport { ident, sugg };
return Some(BufferedEarlyLint {
lint_id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE),
node_id: id,
span: Some(import.span.into()),
diagnostic: diagnostic.into(),
});
} else if ns == TypeNS {
let err = if crate_private_reexport {
self.dcx().create_err(CannotBeReexportedCratePublicNS { span: import.span, ident })
} else {
self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
};
err.emit();
} else {
let mut err = if crate_private_reexport {
self.dcx().create_err(CannotBeReexportedCratePublic { span: import.span, ident })
} else {
self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident })
};
match decl.kind {
// exclude decl_macro
DeclKind::Def(Res::Def(DefKind::Macro(_), def_id))
if self.get_macro_by_def_id(def_id).macro_rules =>
{
err.subdiagnostic(ConsiderAddingMacroExport { span: decl.span });
err.subdiagnostic(ConsiderMarkingAsPubCrate { vis_span: import.vis_span });
}
_ => {
err.subdiagnostic(ConsiderMarkingAsPub { span: import.span, ident });
}
}
err.emit();
}
None
}
pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool {
// This function is only called for single imports.
let ImportKind::Single { source, target, ref decls, id, .. } = import.kind else {