diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 0be4c8243d632..a37f0f7be6221 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -7,6 +7,7 @@ use std::hash::Hash; use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def::DefKind; +use rustc_hir::{ItemKind, Node, UseKind}; use rustc_macros::HashStable; use rustc_span::def_id::{CRATE_DEF_ID, LocalDefId}; @@ -152,9 +153,9 @@ impl EffectiveVisibilities { } pub fn check_invariants(&self, tcx: TyCtxt<'_>) { - if !cfg!(debug_assertions) { - return; - } + // if !cfg!(debug_assertions) { + // return; + // } for (&def_id, ev) in &self.map { // More direct visibility levels can never go farther than less direct ones, // and all effective visibilities are larger or equal than private visibility. @@ -184,13 +185,20 @@ impl EffectiveVisibilities { if !is_impl && tcx.trait_impl_of_assoc(def_id.to_def_id()).is_none() { let nominal_vis = tcx.visibility(def_id); if !nominal_vis.is_at_least(ev.reachable, tcx) { - span_bug!( - span, - "{:?}: reachable {:?} > nominal {:?}", - def_id, - ev.reachable, - nominal_vis, - ); + if let Node::Item(item) = tcx.hir_node_by_def_id(def_id) + && let ItemKind::Use(_, UseKind::Glob) = item.kind + { + // Glob import visibilities can be increasee by other + // more public glob imports in cases of ambiguity. + } else { + span_bug!( + span, + "{:?}: reachable {:?} > nominal {:?}", + def_id, + ev.reachable, + nominal_vis, + ); + } } } } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 50977ba6cff5f..c377079f01436 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -95,7 +95,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ambiguity: CmCell::new(ambiguity), // External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment. warn_ambiguity: CmCell::new(true), - vis: CmCell::new(vis), + initial_vis: vis, + ambiguity_vis_max: CmCell::new(None), + ambiguity_vis_min: CmCell::new(None), span, expansion, parent_module: Some(parent), @@ -250,16 +252,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn build_reduced_graph_external(&self, module: Module<'ra>) { let def_id = module.def_id(); let children = self.tcx.module_children(def_id); - let parent_scope = ParentScope::module(module, self.arenas); for (i, child) in children.iter().enumerate() { - self.build_reduced_graph_for_external_crate_res(child, parent_scope, i, None) + self.build_reduced_graph_for_external_crate_res(child, module, i, None) } for (i, child) in self.cstore().ambig_module_children_untracked(self.tcx, def_id).enumerate() { self.build_reduced_graph_for_external_crate_res( &child.main, - parent_scope, + module, children.len() + i, Some(&child.second), ) @@ -270,11 +271,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn build_reduced_graph_for_external_crate_res( &self, child: &ModChild, - parent_scope: ParentScope<'ra>, + parent: Module<'ra>, child_index: usize, ambig_child: Option<&ModChild>, ) { - let parent = parent_scope.module; let child_span = |this: &Self, reexport_chain: &[Reexport], res: def::Res<_>| { this.def_span( reexport_chain @@ -287,7 +287,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let ident = IdentKey::new(orig_ident); let span = child_span(self, reexport_chain, res); let res = res.expect_non_local(); - let expansion = parent_scope.expansion; + let expansion = LocalExpnId::ROOT; let ambig = ambig_child.map(|ambig_child| { let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child; let span = child_span(self, reexport_chain, res); diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 55518276a4f0f..d0efbf62cc9a8 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -182,6 +182,10 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { parent_id.level(), tcx, ); + if let Some(max_vis_decl) = decl.ambiguity_vis_max.get() { + // Avoid the most visible import in an ambiguous glob set being reported as unused. + self.update_import(max_vis_decl, parent_id); + } } fn update_def( diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 46b4a3aa25864..40a58fab89ded 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -5,7 +5,6 @@ use Namespace::*; use rustc_ast::{self as ast, NodeId}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS}; -use rustc_middle::ty::Visibility; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; use rustc_session::parse::feature_err; @@ -24,9 +23,9 @@ use crate::late::{ use crate::macros::{MacroRulesScope, sub_namespace_match}; use crate::{ AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver, Decl, DeclKind, - Determinacy, Finalize, IdentKey, ImportKind, LateDecl, Module, ModuleKind, ModuleOrUniformRoot, - ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, - Segment, Stage, Symbol, Used, errors, + Determinacy, Finalize, IdentKey, ImportKind, ImportSummary, LateDecl, Module, ModuleKind, + ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, + Scope, ScopeSet, Segment, Stage, Symbol, Used, errors, }; #[derive(Copy, Clone)] @@ -491,6 +490,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } Some(Finalize { import_vis, .. }) => import_vis, }; + this.get_mut().maybe_push_glob_vs_glob_vis_ambiguity( + ident, + orig_ident_span, + decl, + import_vis, + ); if let Some(&(innermost_decl, _)) = innermost_results.first() { // Found another solution, if the first one was "weak", report an error. @@ -780,6 +785,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ret.map_err(ControlFlow::Continue) } + fn maybe_push_glob_vs_glob_vis_ambiguity( + &mut self, + ident: IdentKey, + orig_ident_span: Span, + decl: Decl<'ra>, + import_vis: Option, + ) { + let Some(import) = import_vis else { return }; + let min1 = self.import_decl_vis(decl, import); + let min2 = self.import_decl_vis_ext(decl, import, true); + if min1 != min2 { + self.ambiguity_errors.push(AmbiguityError { + kind: AmbiguityKind::GlobVsGlob, + ambig_vis: Some((min1, min2)), + ident: ident.orig(orig_ident_span), + b1: decl.ambiguity_vis_max.get().unwrap_or(decl), + b2: decl.ambiguity_vis_min.get().unwrap_or(decl), + scope1: Scope::ModuleGlobs(decl.parent_module.unwrap(), None), + scope2: Scope::ModuleGlobs(decl.parent_module.unwrap(), None), + warning: Some(AmbiguityWarning::GlobImport), + }); + } + } + fn maybe_push_ambiguity( &mut self, ident: IdentKey, @@ -790,16 +819,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { decl: Decl<'ra>, scope: Scope<'ra>, innermost_results: &[(Decl<'ra>, Scope<'ra>)], - import_vis: Option, + import_vis: Option, ) -> bool { let (innermost_decl, innermost_scope) = innermost_results[0]; let (res, innermost_res) = (decl.res(), innermost_decl.res()); let ambig_vis = if res != innermost_res { None - } else if let Some(import_vis) = import_vis - && let min = - (|d: Decl<'_>| d.vis().min(import_vis.to_def_id(), self.tcx).expect_local()) - && let (min1, min2) = (min(decl), min(innermost_decl)) + } else if let Some(import) = import_vis + && let min1 = self.import_decl_vis(decl, import) + && let min2 = self.import_decl_vis(innermost_decl, import) && min1 != min2 { Some((min1, min2)) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index e24e65d55c00f..81799fff63333 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -37,8 +37,9 @@ use crate::errors::{ use crate::ref_mut::CmCell; use crate::{ AmbiguityError, BindingKey, CmResolver, Decl, DeclData, DeclKind, Determinacy, Finalize, - IdentKey, ImportSuggestion, Module, ModuleOrUniformRoot, ParentScope, PathResult, PerNS, - ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string, + IdentKey, ImportSuggestion, ImportSummary, Module, ModuleOrUniformRoot, ParentScope, + PathResult, PerNS, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, + names_to_string, }; type Res = def::Res; @@ -269,6 +270,15 @@ impl<'ra> ImportData<'ra> { ImportKind::MacroExport => Reexport::MacroExport, } } + + fn summary(&self) -> ImportSummary { + ImportSummary { + vis: self.vis, + nearest_parent_mod: self.parent_scope.module.nearest_parent_mod().expect_local(), + is_single: matches!(self.kind, ImportKind::Single { .. }), + is_priv_macro_use: matches!(self.kind, ImportKind::MacroUse { warn_private: true }), + } + } } /// Records information about the resolution of a name in a namespace of a module. @@ -322,9 +332,9 @@ struct UnresolvedImportError { // Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;` // are permitted for backward-compatibility under a deprecation lint. -fn pub_use_of_private_extern_crate_hack(import: Import<'_>, decl: Decl<'_>) -> Option { - match (&import.kind, &decl.kind) { - (ImportKind::Single { .. }, DeclKind::Import { import: decl_import, .. }) +fn pub_use_of_private_extern_crate_hack(import: ImportSummary, decl: Decl<'_>) -> Option { + match (import.is_single, decl.kind) { + (true, DeclKind::Import { import: decl_import, .. }) if let ImportKind::ExternCrate { id, .. } = decl_import.kind && import.vis.is_public() => { @@ -356,23 +366,53 @@ fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra } impl<'ra, 'tcx> Resolver<'ra, 'tcx> { + pub(crate) fn import_decl_vis(&self, decl: Decl<'ra>, import: ImportSummary) -> Visibility { + self.import_decl_vis_ext(decl, import, false) + } + + pub(crate) fn import_decl_vis_ext( + &self, + decl: Decl<'ra>, + import: ImportSummary, + min: bool, + ) -> Visibility { + let decl_vis = if min { decl.min_vis() } else { decl.vis() }; + if decl_vis.is_at_least(import.vis, self.tcx) { + // Ordered, import is less visible than the binding, use the import's visibility. + import.vis + } else if decl_vis.is_accessible_from(import.nearest_parent_mod, self.tcx) { + // Ordered, binding is less visible than the import, but is still visible from the + // current module, use the binding's visibility. + assert!(import.vis.is_at_least(decl_vis, self.tcx)); + if pub_use_of_private_extern_crate_hack(import, decl).is_some() { + import.vis + } else { + decl_vis.expect_local() + } + } else { + // The binding is too private for the current module, use private visibility. + if !min && !import.is_priv_macro_use { + // self.dcx().span_delayed_bug(import.span, "tralala"); + } + import.vis + } + } + /// Given an import and the declaration that it points to, /// create the corresponding import declaration. pub(crate) fn new_import_decl(&self, decl: Decl<'ra>, import: Import<'ra>) -> Decl<'ra> { - let import_vis = import.vis.to_def_id(); - let vis = if decl.vis().is_at_least(import_vis, self.tcx) - || pub_use_of_private_extern_crate_hack(import, decl).is_some() - { - import_vis - } else { - decl.vis() - }; + if let crate::ModuleKind::Def(_, def_id, _) = import.parent_scope.module.kind { + assert!(def_id.is_local()); + } + assert!(self.is_accessible_from(import.vis, import.parent_scope.module)); + let vis = self.import_decl_vis(decl, import.summary()); + assert!(self.is_accessible_from(vis, import.parent_scope.module)); if let ImportKind::Glob { ref max_vis, .. } = import.kind - && (vis == import_vis + && (vis == import.vis || max_vis.get().is_none_or(|max_vis| vis.is_at_least(max_vis, self.tcx))) { - max_vis.set_unchecked(Some(vis.expect_local())) + max_vis.set_unchecked(Some(vis)) } self.arenas.alloc_decl(DeclData { @@ -380,7 +420,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ambiguity: CmCell::new(None), warn_ambiguity: CmCell::new(false), span: import.span, - vis: CmCell::new(vis), + initial_vis: vis.to_def_id(), + ambiguity_vis_max: CmCell::new(None), + ambiguity_vis_min: CmCell::new(None), expansion: import.parent_scope.expansion, parent_module: Some(import.parent_scope.module), }) @@ -405,8 +447,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // - A glob decl is overwritten by its clone after setting ambiguity in it. // FIXME: avoid this by removing `warn_ambiguity`, or by triggering glob re-fetch // with the same decl in some way. - // - A glob decl is overwritten by a glob decl with larger visibility. - // FIXME: avoid this by updating this visibility in place. // - A glob decl is overwritten by a glob decl re-fetching an // overwritten decl from other module (the recursive case). // Here we are detecting all such re-fetches and overwrite old decls @@ -420,8 +460,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // FIXME: reenable the asserts when `warn_ambiguity` is removed (#149195). // assert_ne!(old_deep_decl, deep_decl); // assert!(old_deep_decl.is_glob_import()); - // FIXME: reenable the assert when visibility is updated in place. - // assert!(!deep_decl.is_glob_import()); + assert!(!deep_decl.is_glob_import()); if old_glob_decl.ambiguity.get().is_some() && glob_decl.ambiguity.get().is_none() { // Do not lose glob ambiguities when re-fetching the glob. glob_decl.ambiguity.set_unchecked(old_glob_decl.ambiguity.get()); @@ -441,11 +480,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // FIXME: remove this when `warn_ambiguity` is removed (#149195). self.arenas.alloc_decl((*old_glob_decl).clone()) } - } else if !old_glob_decl.vis().is_at_least(glob_decl.vis(), self.tcx) { - // We are glob-importing the same item but with greater visibility. - // FIXME: Update visibility in place, but without regressions - // (#152004, #151124, #152347). - glob_decl + } else if let old_vis = old_glob_decl.vis() + && let vis = glob_decl.vis() + && old_vis != vis + { + // We are glob-importing the same item but with a different visibility. + // All visibilities here are ordered because all of them are ancestors of `module`. + if vis.is_at_least(old_vis, self.tcx) { + old_glob_decl.ambiguity_vis_max.set_unchecked(Some(glob_decl)); + } else if let old_min_vis = old_glob_decl.min_vis() + && old_min_vis != vis + && old_min_vis.is_at_least(vis, self.tcx) + { + old_glob_decl.ambiguity_vis_min.set_unchecked(Some(glob_decl)); + } + old_glob_decl } else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() { // Overwriting a non-ambiguous glob import with an ambiguous glob import. old_glob_decl.ambiguity.set_unchecked(Some(glob_decl)); @@ -466,7 +515,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { decl: Decl<'ra>, warn_ambiguity: bool, ) -> Result<(), Decl<'ra>> { + assert!(!decl.warn_ambiguity.get()); + assert!(decl.ambiguity.get().is_none()); + assert!(decl.ambiguity_vis_max.get().is_none()); + assert!(decl.ambiguity_vis_min.get().is_none()); let module = decl.parent_module.unwrap(); + assert!(self.is_accessible_from(decl.vis(), module)); let res = decl.res(); self.check_reserved_macro_name(ident.name, orig_ident_span, res); // Even if underscore names cannot be looked up, we still need to add them to modules, @@ -484,7 +538,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { |this, resolution| { if let Some(old_decl) = resolution.best_decl() { assert_ne!(decl, old_decl); - assert!(!decl.warn_ambiguity.get()); if res == Res::Err && old_decl.res() != Res::Err { // Do not override real declarations with `Res::Err`s from error recovery. return Ok(()); @@ -544,11 +597,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .resolution_or_default(module, key, orig_ident_span) .borrow_mut_unchecked(); let old_decl = resolution.binding(); + let old_vis = old_decl.map(|d| d.vis()); let t = f(self, resolution); if let Some(binding) = resolution.binding() - && old_decl != Some(binding) + && (old_decl != Some(binding) || old_vis != Some(binding.vis())) { (binding, t, warn_ambiguity || old_decl.is_some()) } else { @@ -1275,7 +1329,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &import.parent_scope, Some(Finalize { report_private: false, - import_vis: Some(import.vis), + import_vis: Some(import.summary()), ..finalize }), bindings[ns].get().decl(), @@ -1475,7 +1529,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // 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, binding) { + 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, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index d75f2981a7724..1352b8bcd654f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -860,7 +860,13 @@ struct DeclData<'ra> { warn_ambiguity: CmCell, expansion: LocalExpnId, span: Span, - vis: CmCell>, + initial_vis: Visibility, + /// If the declaration refers to an ambiguous glob set, then this is the most visible binding + /// from the set, if its visibility is different from `initial_vis`. + ambiguity_vis_max: CmCell>>, + /// If the declaration refers to an ambiguous glob set, then this is the least visible binding + /// from the set, if its visibility is different from `initial_vis`. + ambiguity_vis_min: CmCell>>, parent_module: Option>, } @@ -980,7 +986,13 @@ struct AmbiguityError<'ra> { impl<'ra> DeclData<'ra> { fn vis(&self) -> Visibility { - self.vis.get() + // Select the maximum visibility if there are multiple ambiguous glob imports. + self.ambiguity_vis_max.get().map(|d| d.vis()).unwrap_or_else(|| self.initial_vis) + } + + fn min_vis(&self) -> Visibility { + // Select the minimum visibility if there are multiple ambiguous glob imports. + self.ambiguity_vis_min.get().map(|d| d.vis()).unwrap_or_else(|| self.initial_vis) } fn res(&self) -> Res { @@ -1439,7 +1451,9 @@ impl<'ra> ResolverArenas<'ra> { kind: DeclKind::Def(res), ambiguity: CmCell::new(None), warn_ambiguity: CmCell::new(false), - vis: CmCell::new(vis), + initial_vis: vis, + ambiguity_vis_max: CmCell::new(None), + ambiguity_vis_min: CmCell::new(None), span, expansion, parent_module, @@ -2639,6 +2653,16 @@ enum Stage { Late, } +/// Parts of import data required for finalizing import resolution. +/// Does not carry a lifetime, so it can be stored in `Finalize`. +#[derive(Copy, Clone, Debug)] +struct ImportSummary { + vis: Visibility, + nearest_parent_mod: LocalDefId, + is_single: bool, + is_priv_macro_use: bool, +} + /// Invariant: if `Finalize` is used, expansion and import resolution must be complete. #[derive(Copy, Clone, Debug)] struct Finalize { @@ -2658,7 +2682,7 @@ struct Finalize { /// Finalizing early or late resolution. stage: Stage = Stage::Early, /// Nominal visibility of the import item, in case we are resolving an import's final segment. - import_vis: Option = None, + import_vis: Option = None, } impl Finalize { diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-priv-pass.rs b/tests/ui/imports/ambiguous-import-visibility-globglob-priv-pass.rs new file mode 100644 index 0000000000000..08d6bb05f0bb3 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob-priv-pass.rs @@ -0,0 +1,23 @@ +//@ check-pass + +mod m { + pub struct S {} +} + +mod one_private { + use crate::m::*; + pub use crate::m::*; +} + +// One of the ambiguous imports is not visible from here, +// but it still contributes to the ambiguity. +use crate::one_private::S; + +// Separate module to make visibilities `in crate::inner` and `in crate::one_private` unordered. +mod inner { + // One of the ambiguous imports is not visible from here, + // but it still contributes to the ambiguity. + use crate::one_private::S; +} + +fn main() {} diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-priv.rs b/tests/ui/imports/ambiguous-import-visibility-globglob-priv.rs new file mode 100644 index 0000000000000..ac1a7d5182af5 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob-priv.rs @@ -0,0 +1,21 @@ +mod m { + pub struct S {} +} + +mod both { + pub mod private { + use crate::m::*; + pub(super) use crate::m::*; + } +} + +use crate::both::private::S; +//~^ ERROR struct import `S` is private + +// Separate module to make visibilities `in crate::inner` and `in crate::both::private` unordered. +mod inner { + use crate::both::private::S; + //~^ ERROR struct import `S` is private +} + +fn main() {} diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-priv.stderr b/tests/ui/imports/ambiguous-import-visibility-globglob-priv.stderr new file mode 100644 index 0000000000000..4485f5ac96481 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob-priv.stderr @@ -0,0 +1,47 @@ +error[E0603]: struct import `S` is private + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:12:27 + | +LL | use crate::both::private::S; + | ^ private struct import + | +note: the struct import `S` is defined here... + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:7:13 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ +note: ...and refers to the struct `S` which is defined here + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:2:5 + | +LL | pub struct S {} + | ^^^^^^^^^^^^ you could import this directly +help: import `S` through the re-export + | +LL - use crate::both::private::S; +LL + use m::S; + | + +error[E0603]: struct import `S` is private + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:17:31 + | +LL | use crate::both::private::S; + | ^ private struct import + | +note: the struct import `S` is defined here... + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:7:13 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ +note: ...and refers to the struct `S` which is defined here + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:2:5 + | +LL | pub struct S {} + | ^^^^^^^^^^^^ you could import this directly +help: import `S` through the re-export + | +LL - use crate::both::private::S; +LL + use m::S; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob.rs b/tests/ui/imports/ambiguous-import-visibility-globglob.rs new file mode 100644 index 0000000000000..5c8b6f4766835 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob.rs @@ -0,0 +1,49 @@ +//@ check-pass + +mod m { + pub struct S {} +} + +mod min_vis_first { + use crate::m::*; + pub(crate) use crate::m::*; + pub use crate::m::*; + + pub use self::S as S1; + //~^ WARN ambiguous import visibility + //~| WARN this was previously accepted + pub(crate) use self::S as S2; + //~^ WARN ambiguous import visibility + //~| WARN this was previously accepted + use self::S as S3; // OK +} + +mod mid_vis_first { + pub(crate) use crate::m::*; + use crate::m::*; + pub use crate::m::*; + + pub use self::S as S1; + //~^ WARN ambiguous import visibility + //~| WARN this was previously accepted + pub(crate) use self::S as S2; + //~^ WARN ambiguous import visibility + //~| WARN this was previously accepted + use self::S as S3; // OK +} + +mod max_vis_first { + pub use crate::m::*; + use crate::m::*; + pub(crate) use crate::m::*; + + pub use self::S as S1; + //~^ WARN ambiguous import visibility + //~| WARN this was previously accepted + pub(crate) use self::S as S2; + //~^ WARN ambiguous import visibility + //~| WARN this was previously accepted + use self::S as S3; // OK +} + +fn main() {} diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob.stderr b/tests/ui/imports/ambiguous-import-visibility-globglob.stderr new file mode 100644 index 0000000000000..d15282cc436cd --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob.stderr @@ -0,0 +1,135 @@ +warning: ambiguous import visibility: pub or pub(in crate::min_vis_first) + --> $DIR/ambiguous-import-visibility-globglob.rs:12:19 + | +LL | pub use self::S as S1; + | ^ + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `S` could refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:10:13 + | +LL | pub use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate +note: `S` could also refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:8:9 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #149145 + = note: `#[warn(ambiguous_import_visibilities)]` (part of `#[warn(future_incompatible)]`) on by default + +warning: ambiguous import visibility: pub(crate) or pub(in crate::min_vis_first) + --> $DIR/ambiguous-import-visibility-globglob.rs:15:26 + | +LL | pub(crate) use self::S as S2; + | ^ + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `S` could refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:10:13 + | +LL | pub use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate +note: `S` could also refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:8:9 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #149145 + +warning: ambiguous import visibility: pub or pub(in crate::mid_vis_first) + --> $DIR/ambiguous-import-visibility-globglob.rs:26:19 + | +LL | pub use self::S as S1; + | ^ + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `S` could refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:24:13 + | +LL | pub use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate +note: `S` could also refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:23:9 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #149145 + +warning: ambiguous import visibility: pub(crate) or pub(in crate::mid_vis_first) + --> $DIR/ambiguous-import-visibility-globglob.rs:29:26 + | +LL | pub(crate) use self::S as S2; + | ^ + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `S` could refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:24:13 + | +LL | pub use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate +note: `S` could also refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:23:9 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #149145 + +warning: ambiguous import visibility: pub or pub(in crate::max_vis_first) + --> $DIR/ambiguous-import-visibility-globglob.rs:40:19 + | +LL | pub use self::S as S1; + | ^ + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `S` could refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:36:13 + | +LL | pub use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate +note: `S` could also refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:37:9 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #149145 + +warning: ambiguous import visibility: pub(crate) or pub(in crate::max_vis_first) + --> $DIR/ambiguous-import-visibility-globglob.rs:43:26 + | +LL | pub(crate) use self::S as S2; + | ^ + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `S` could refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:36:13 + | +LL | pub use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate +note: `S` could also refer to the struct imported here + --> $DIR/ambiguous-import-visibility-globglob.rs:37:9 + | +LL | use crate::m::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #149145 + +warning: 6 warnings emitted + diff --git a/tests/ui/imports/overwrite-vis-unused.rs b/tests/ui/imports/overwrite-vis-unused.rs index 0217fb6250837..6361c71f6639e 100644 --- a/tests/ui/imports/overwrite-vis-unused.rs +++ b/tests/ui/imports/overwrite-vis-unused.rs @@ -1,12 +1,12 @@ // Regression test for issues #152004 and #151124. - +//@ check-pass #![deny(unused)] mod m { pub struct S {} } -use m::*; //~ ERROR unused import: `m::*` +use m::*; pub use m::*; fn main() {} diff --git a/tests/ui/imports/overwrite-vis-unused.stderr b/tests/ui/imports/overwrite-vis-unused.stderr deleted file mode 100644 index a38aa4d5f070a..0000000000000 --- a/tests/ui/imports/overwrite-vis-unused.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: unused import: `m::*` - --> $DIR/overwrite-vis-unused.rs:9:5 - | -LL | use m::*; - | ^^^^ - | -note: the lint level is defined here - --> $DIR/overwrite-vis-unused.rs:3:9 - | -LL | #![deny(unused)] - | ^^^^^^ - = note: `#[deny(unused_imports)]` implied by `#[deny(unused)]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/imports/private-from-decl-macro.fail.stderr b/tests/ui/imports/private-from-decl-macro.fail.stderr new file mode 100644 index 0000000000000..e09c193f5e6ba --- /dev/null +++ b/tests/ui/imports/private-from-decl-macro.fail.stderr @@ -0,0 +1,27 @@ +error[E0423]: expected value, found struct `S` + --> $DIR/private-from-decl-macro.rs:27:17 + | +LL | pub struct S {} + | --------------- `S` defined here +... +LL | let s = S; + | ^ + | +note: constant `m::S` exists but is inaccessible + --> $DIR/private-from-decl-macro.rs:10:5 + | +LL | const S: u8 = 0; + | ^^^^^^^^^^^^^^^^ not accessible +help: use struct literal syntax instead + | +LL | let s = S {}; + | ++ +help: a local variable with a similar name exists (notice the capitalization) + | +LL - let s = S; +LL + let s = s; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/imports/private-from-decl-macro.rs b/tests/ui/imports/private-from-decl-macro.rs new file mode 100644 index 0000000000000..cdb3bb40ef7b5 --- /dev/null +++ b/tests/ui/imports/private-from-decl-macro.rs @@ -0,0 +1,35 @@ +//@ revisions: pass fail +//@[pass] check-pass + +#![feature(decl_macro)] + +mod m { + // Name in two namespaces, one public, one private. + // The private name is filtered away when importing, even from a macro 2.0 + pub struct S {} + const S: u8 = 0; + + pub macro mac_single($S:ident) { + use crate::m::$S; + } + + pub macro mac_glob() { + use crate::m::*; + } +} + +mod single { + crate::m::mac_single!(S); + + fn check() { + let s = S {}; + #[cfg(fail)] + let s = S; //[fail]~ ERROR expected value, found struct `S` + } +} + +mod glob { + crate::m::mac_glob!(); +} + +fn main() {} diff --git a/tests/ui/privacy/restricted/decl-macros.rs b/tests/ui/privacy/restricted/decl-macros.rs new file mode 100644 index 0000000000000..2e4dbddc8a872 --- /dev/null +++ b/tests/ui/privacy/restricted/decl-macros.rs @@ -0,0 +1,15 @@ +#![feature(decl_macro)] + +mod m { + pub macro mac() { + struct A {} + pub(self) struct B {} //~ ERROR visibilities can only be restricted to ancestor modules + pub(in crate::m) struct C {} //~ ERROR visibilities can only be restricted to ancestor modules + } +} + +mod n { + crate::m::mac!(); +} + +fn main() {} diff --git a/tests/ui/privacy/restricted/decl-macros.stderr b/tests/ui/privacy/restricted/decl-macros.stderr new file mode 100644 index 0000000000000..c932bb5fe9416 --- /dev/null +++ b/tests/ui/privacy/restricted/decl-macros.stderr @@ -0,0 +1,25 @@ +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/decl-macros.rs:6:13 + | +LL | pub(self) struct B {} + | ^^^^ +... +LL | crate::m::mac!(); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `crate::m::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/decl-macros.rs:7:16 + | +LL | pub(in crate::m) struct C {} + | ^^^^^^^^ +... +LL | crate::m::mac!(); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `crate::m::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0742`. diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.rs b/tests/ui/pub/pub-reexport-priv-extern-crate.rs index 9d615be30f450..bc91cf4bc7551 100644 --- a/tests/ui/pub/pub-reexport-priv-extern-crate.rs +++ b/tests/ui/pub/pub-reexport-priv-extern-crate.rs @@ -4,6 +4,8 @@ pub use core as reexported_core; //~ ERROR `core` is private and cannot be re-ex mod foo1 { extern crate core; + pub use self::core as core2; //~ ERROR extern crate `core` is private and cannot be re-exported + //~^ WARN this was previously accepted } mod foo2 { @@ -17,4 +19,7 @@ mod baz { pub use crate::foo2::bar::core; //~ ERROR crate import `core` is private } -fn main() {} +fn main() { + // Check that `foo1::core2` has the reexport's visibility and is accessible. + foo1::core2::mem::drop(()); +} diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr index dbb080e1b0940..1b8279c643318 100644 --- a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr +++ b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr @@ -1,5 +1,5 @@ error[E0603]: crate import `core` is private - --> $DIR/pub-reexport-priv-extern-crate.rs:10:22 + --> $DIR/pub-reexport-priv-extern-crate.rs:12:22 | LL | use crate::foo1::core; | ^^^^ private crate import @@ -11,13 +11,13 @@ LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ error[E0603]: crate import `core` is private - --> $DIR/pub-reexport-priv-extern-crate.rs:17:31 + --> $DIR/pub-reexport-priv-extern-crate.rs:19:31 | LL | pub use crate::foo2::bar::core; | ^^^^ private crate import | note: the crate import `core` is defined here - --> $DIR/pub-reexport-priv-extern-crate.rs:12:9 + --> $DIR/pub-reexport-priv-extern-crate.rs:14:9 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,20 @@ help: consider making the `extern crate` item publicly accessible LL | pub extern crate core; | +++ -error: aborting due to 3 previous errors +error[E0365]: extern crate `core` is private and cannot be re-exported + --> $DIR/pub-reexport-priv-extern-crate.rs:7:13 + | +LL | pub use self::core as core2; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #127909 +help: consider making the `extern crate` item publicly accessible + | +LL | pub extern crate core; + | +++ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0365, E0603. For more information about an error, try `rustc --explain E0365`. @@ -55,3 +68,18 @@ help: consider making the `extern crate` item publicly accessible LL | pub extern crate core; | +++ +Future breakage diagnostic: +error[E0365]: extern crate `core` is private and cannot be re-exported + --> $DIR/pub-reexport-priv-extern-crate.rs:7:13 + | +LL | pub use self::core as core2; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #127909 + = note: `#[deny(pub_use_of_private_extern_crate)]` (part of `#[deny(future_incompatible)]`) on by default +help: consider making the `extern crate` item publicly accessible + | +LL | pub extern crate core; + | +++ + diff --git a/tests/ui/resolve/decl-macro-use-no-ice.rs b/tests/ui/resolve/decl-macro-use-no-ice.rs index 39b9cb03fea0d..ec103ab3b2080 100644 --- a/tests/ui/resolve/decl-macro-use-no-ice.rs +++ b/tests/ui/resolve/decl-macro-use-no-ice.rs @@ -11,7 +11,7 @@ mod foo { pub macro m() { use f; //~ ERROR `f` is private, and cannot be re-exported - f!(); //~ ERROR macro import `f` is private + f!(); } } diff --git a/tests/ui/resolve/decl-macro-use-no-ice.stderr b/tests/ui/resolve/decl-macro-use-no-ice.stderr index 9fb75b48b428c..619a5737090e0 100644 --- a/tests/ui/resolve/decl-macro-use-no-ice.stderr +++ b/tests/ui/resolve/decl-macro-use-no-ice.stderr @@ -17,31 +17,6 @@ LL | foo::m!(); | --------- in this macro invocation = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0603]: macro import `f` is private - --> $DIR/decl-macro-use-no-ice.rs:14:9 - | -LL | f!(); - | ^ private macro import -... -LL | foo::m!(); - | --------- in this macro invocation - | -note: the macro import `f` is defined here... - --> $DIR/decl-macro-use-no-ice.rs:13:13 - | -LL | use f; - | ^ -... -LL | foo::m!(); - | --------- in this macro invocation -note: ...and refers to the macro `f` which is defined here - --> $DIR/decl-macro-use-no-ice.rs:10:5 - | -LL | macro f() {} - | ^^^^^^^^^ - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0364, E0603. -For more information about an error, try `rustc --explain E0364`. +For more information about this error, try `rustc --explain E0364`.