diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index 64353461e90e0..e4cc44c41ddec 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -69,9 +69,6 @@ pub enum AnnotationType { /// Annotation under a single line of code Singleline, - /// Annotation enclosing the first and last character of a multiline span - Multiline(MultilineAnnotation), - // The Multiline type above is replaced with the following three in order // to reuse the current label drawing code. // diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c7823032b0c23..c6145ae0d510b 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -92,7 +92,8 @@ use unused::*; /// Useful for other parts of the compiler / Clippy. pub use builtin::SoftLints; -pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore}; +pub use context::{CheckLintNameResult, FindLintError, LintStore}; +pub use context::{EarlyContext, LateContext, LintContext}; pub use early::check_ast_crate; pub use late::check_crate; pub use passes::{EarlyLintPass, LateLintPass}; diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index f33bd3438b968..ff993ac392cf7 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -28,7 +28,7 @@ pub enum AccessLevel { } /// Holds a map of accessibility levels for reachable HIR nodes. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AccessLevels { pub map: FxHashMap, } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f5f55dcf38cf4..16adf93b69a36 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -20,6 +20,7 @@ pub use generics::*; pub use vtable::*; use crate::metadata::ModChild; +use crate::middle::privacy::AccessLevels; use crate::mir::{Body, GeneratorLayout}; use crate::traits::{self, Reveal}; use crate::ty; @@ -123,6 +124,7 @@ pub struct ResolverOutputs { pub definitions: rustc_hir::definitions::Definitions, pub cstore: Box, pub visibilities: FxHashMap, + pub access_levels: AccessLevels, pub extern_crate_map: FxHashMap, pub maybe_unused_trait_imports: FxHashSet, pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 16418e627f2dc..e93cd813db53e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -11,8 +11,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet}; -use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor}; use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind}; use rustc_middle::bug; @@ -26,7 +25,7 @@ use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::hygiene::Transparency; -use rustc_span::symbol::{kw, sym, Ident}; +use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; use rustc_trait_selection::traits::const_evaluatable::{self, AbstractConst}; @@ -436,6 +435,15 @@ impl<'tcx> EmbargoVisitor<'tcx> { self.access_levels.map.get(&def_id).copied() } + fn update_with_hir_id( + &mut self, + hir_id: hir::HirId, + level: Option, + ) -> Option { + let def_id = self.tcx.hir().local_def_id(hir_id); + self.update(def_id, level) + } + /// Updates node level and returns the updated level. fn update(&mut self, def_id: LocalDefId, level: Option) -> Option { let old_level = self.get(def_id); @@ -623,54 +631,6 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::Generator => (), } } - - /// Given the path segments of an `ItemKind::Use`, then we need - /// to update the visibility of the intermediate use so that it isn't linted - /// by `unreachable_pub`. - /// - /// This isn't trivial as `path.res` has the `DefId` of the eventual target - /// of the use statement not of the next intermediate use statement. - /// - /// To do this, consider the last two segments of the path to our intermediate - /// use statement. We expect the penultimate segment to be a module and the - /// last segment to be the name of the item we are exporting. We can then - /// look at the items contained in the module for the use statement with that - /// name and update that item's visibility. - /// - /// FIXME: This solution won't work with glob imports and doesn't respect - /// namespaces. See . - fn update_visibility_of_intermediate_use_statements( - &mut self, - segments: &[hir::PathSegment<'_>], - ) { - if let [.., module, segment] = segments { - if let Some(item) = module - .res - .and_then(|res| res.mod_def_id()) - // If the module is `self`, i.e. the current crate, - // there will be no corresponding item. - .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE) - .and_then(|def_id| def_id.as_local()) - .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id)) - { - if let hir::ItemKind::Mod(m) = &item.kind { - for &item_id in m.item_ids { - let item = self.tcx.hir().item(item_id); - if !self.tcx.hygienic_eq( - segment.ident, - item.ident, - item_id.def_id.to_def_id(), - ) { - continue; - } - if let hir::ItemKind::Use(..) = item.kind { - self.update(item.def_id, Some(AccessLevel::Exported)); - } - } - } - } - } - } } impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { @@ -683,120 +643,22 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let inherited_item_level = match item.kind { + let item_level = match item.kind { hir::ItemKind::Impl { .. } => { - Option::::of_impl(item.def_id, self.tcx, &self.access_levels) - } - // Only exported `macro_rules!` items are public, but they always are. - hir::ItemKind::Macro(MacroDef { macro_rules: true, .. }) => { - let def_id = item.def_id.to_def_id(); - let is_macro_export = self.tcx.has_attr(def_id, sym::macro_export); - if is_macro_export { Some(AccessLevel::Public) } else { None } - } - // Foreign modules inherit level from parents. - hir::ItemKind::ForeignMod { .. } => self.prev_level, - // Other `pub` items inherit levels from parents. - hir::ItemKind::Const(..) - | hir::ItemKind::Enum(..) - | hir::ItemKind::ExternCrate(..) - | hir::ItemKind::GlobalAsm(..) - | hir::ItemKind::Fn(..) - | hir::ItemKind::Macro(..) - | hir::ItemKind::Mod(..) - | hir::ItemKind::Static(..) - | hir::ItemKind::Struct(..) - | hir::ItemKind::Trait(..) - | hir::ItemKind::TraitAlias(..) - | hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::TyAlias(..) - | hir::ItemKind::Union(..) - | hir::ItemKind::Use(..) => { - if item.vis.node.is_pub() { - self.prev_level - } else { - None - } + let impl_level = + Option::::of_impl(item.def_id, self.tcx, &self.access_levels); + self.update(item.def_id, impl_level) } + _ => self.get(item.def_id), }; - // Update level of the item itself. - let item_level = self.update(item.def_id, inherited_item_level); - - // Update levels of nested things. - match item.kind { - hir::ItemKind::Enum(ref def, _) => { - for variant in def.variants { - let variant_level = - self.update(self.tcx.hir().local_def_id(variant.id), item_level); - if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { - self.update(self.tcx.hir().local_def_id(ctor_hir_id), item_level); - } - for field in variant.data.fields() { - self.update(self.tcx.hir().local_def_id(field.hir_id), variant_level); - } - } - } - hir::ItemKind::Impl(ref impl_) => { - for impl_item_ref in impl_.items { - if impl_.of_trait.is_some() - || self.tcx.visibility(impl_item_ref.id.def_id) == ty::Visibility::Public - { - self.update(impl_item_ref.id.def_id, item_level); - } - } - } - hir::ItemKind::Trait(.., trait_item_refs) => { - for trait_item_ref in trait_item_refs { - self.update(trait_item_ref.id.def_id, item_level); - } - } - hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { - if let Some(ctor_hir_id) = def.ctor_hir_id() { - self.update(self.tcx.hir().local_def_id(ctor_hir_id), item_level); - } - for field in def.fields() { - if field.vis.node.is_pub() { - self.update(self.tcx.hir().local_def_id(field.hir_id), item_level); - } - } - } - hir::ItemKind::Macro(ref macro_def) => { - self.update_reachability_from_macro(item.def_id, macro_def); - } - hir::ItemKind::ForeignMod { items, .. } => { - for foreign_item in items { - if self.tcx.visibility(foreign_item.id.def_id) == ty::Visibility::Public { - self.update(foreign_item.id.def_id, item_level); - } - } - } - - hir::ItemKind::OpaqueTy(..) - | hir::ItemKind::Use(..) - | hir::ItemKind::Static(..) - | hir::ItemKind::Const(..) - | hir::ItemKind::GlobalAsm(..) - | hir::ItemKind::TyAlias(..) - | hir::ItemKind::Mod(..) - | hir::ItemKind::TraitAlias(..) - | hir::ItemKind::Fn(..) - | hir::ItemKind::ExternCrate(..) => {} - } - // Mark all items in interfaces of reachable items as reachable. match item.kind { // The interface is empty. - hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {} + hir::ItemKind::ExternCrate(..) => {} // All nested items are checked by `visit_item`. hir::ItemKind::Mod(..) => {} - // Re-exports are handled in `visit_mod`. However, in order to avoid looping over - // all of the items of a mod in `visit_mod` looking for use statements, we handle - // making sure that intermediate use statements have their visibilities updated here. - hir::ItemKind::Use(path, _) => { - if item_level.is_some() { - self.update_visibility_of_intermediate_use_statements(path.segments.as_ref()); - } - } + hir::ItemKind::Use(..) => {} // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} hir::ItemKind::OpaqueTy(..) => { @@ -847,6 +709,14 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } // Visit everything except for private impl items. hir::ItemKind::Impl(ref impl_) => { + for impl_item_ref in impl_.items { + if impl_.of_trait.is_some() + || self.tcx.visibility(impl_item_ref.id.def_id) == ty::Visibility::Public + { + self.update(impl_item_ref.id.def_id, item_level); + } + } + if item_level.is_some() { self.reach(item.def_id, item_level).generics().predicates().ty().trait_ref(); @@ -861,15 +731,21 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } - // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { self.reach(item.def_id, item_level).generics().predicates(); } + + let enum_level = self.get(item.def_id); for variant in def.variants { - let variant_level = self.get(self.tcx.hir().local_def_id(variant.id)); + let variant_level = self.update_with_hir_id(variant.id, enum_level); + if variant_level.is_some() { + if let Some(ctor_id) = variant.data.ctor_hir_id() { + self.update_with_hir_id(ctor_id, variant_level); + } + for field in variant.data.fields() { self.reach(self.tcx.hir().local_def_id(field.hir_id), variant_level) .ty(); @@ -880,6 +756,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } + hir::ItemKind::Macro(ref macro_def) => { + self.update_reachability_from_macro(item.def_id, macro_def); + } // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { @@ -920,27 +799,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { intravisit::walk_block(self, b); self.prev_level = orig_level; } - - fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _sp: Span, id: hir::HirId) { - // This code is here instead of in visit_item so that the - // crate module gets processed as well. - if self.prev_level.is_some() { - let def_id = self.tcx.hir().local_def_id(id); - if let Some(exports) = self.tcx.module_reexports(def_id) { - for export in exports.iter() { - if export.vis.is_public() { - if let Some(def_id) = export.res.opt_def_id() { - if let Some(def_id) = def_id.as_local() { - self.update(def_id, Some(AccessLevel::Exported)); - } - } - } - } - } - } - - intravisit::walk_mod(self, m, id); - } } impl ReachEverythingInTheInterfaceVisitor<'_, '_> { @@ -2166,11 +2024,12 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { // items which are reachable from external crates based on visibility. let mut visitor = EmbargoVisitor { tcx, - access_levels: Default::default(), + access_levels: tcx.resolutions(()).access_levels.clone(), macro_reachable: Default::default(), prev_level: Some(AccessLevel::Public), changed: false, }; + loop { tcx.hir().walk_toplevel_module(&mut visitor); if visitor.changed { @@ -2179,7 +2038,6 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { break; } } - visitor.update(CRATE_DEF_ID, Some(AccessLevel::Public)); tcx.arena.alloc(visitor.access_levels) } diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs new file mode 100644 index 0000000000000..60cc4248edc9d --- /dev/null +++ b/compiler/rustc_resolve/src/access_levels.rs @@ -0,0 +1,237 @@ +use rustc_ast::ast; +use rustc_ast::visit; +use rustc_ast::visit::Visitor; +use rustc_ast::Crate; +use rustc_ast::EnumDef; +use rustc_ast::ForeignMod; +use rustc_ast::NodeId; +use rustc_ast_lowering::ResolverAstLowering; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::CRATE_DEF_ID; +use rustc_middle::middle::privacy::AccessLevel; +use rustc_middle::ty::Visibility; +use rustc_span::sym; + +use crate::imports::ImportKind; +use crate::BindingKey; +use crate::NameBinding; +use crate::NameBindingKind; +use crate::Resolver; + +pub struct AccessLevelsVisitor<'r, 'a> { + r: &'r mut Resolver<'a>, + prev_level: Option, + changed: bool, +} + +impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { + /// Fills the `Resolver::access_levels` table with public & exported items + /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we + /// need access to a TyCtxt for that. + pub fn compute_access_levels<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) { + let mut visitor = + AccessLevelsVisitor { r, changed: false, prev_level: Some(AccessLevel::Public) }; + + visitor.set_access_level_def_id(CRATE_DEF_ID, Some(AccessLevel::Public)); + visitor.set_exports_access_level(CRATE_DEF_ID); + + while visitor.changed { + visitor.reset(); + visit::walk_crate(&mut visitor, krate); + } + + tracing::info!("resolve::access_levels: {:#?}", r.access_levels); + } + + fn reset(&mut self) { + self.changed = false; + self.prev_level = Some(AccessLevel::Public); + } + + /// Update the access level of the exports of the given module accordingly. The module access + /// level has to be Exported or Public. + /// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level). + fn set_exports_access_level(&mut self, module_id: LocalDefId) { + assert!(self.r.module_map.contains_key(&&module_id.to_def_id())); + + // Set the given binding access level to `AccessLevel::Public` and + // sets the rest of the `use` chain to `AccessLevel::Exported` until + // we hit the actual exported item. + let set_import_binding_access_level = + |this: &mut Self, mut binding: &NameBinding<'a>, mut access_level| { + while let NameBindingKind::Import { binding: nested_binding, import, .. } = + binding.kind + { + this.set_access_level(import.id, access_level); + if let ImportKind::Single { additional_ids, .. } = import.kind { + this.set_access_level(additional_ids.0, access_level); + this.set_access_level(additional_ids.1, access_level); + } + + access_level = Some(AccessLevel::Exported); + binding = nested_binding; + } + }; + + let module_level = self.r.access_levels.map.get(&module_id).copied(); + assert!(module_level >= Some(AccessLevel::Exported)); + + if let Some(exports) = self.r.reexport_map.get(&module_id) { + let pub_exports = exports + .iter() + .filter(|ex| ex.vis == Visibility::Public) + .cloned() + .collect::>(); + + let module = self.r.get_module(module_id.to_def_id()).unwrap(); + for export in pub_exports.into_iter() { + if let Some(export_def_id) = export.res.opt_def_id().and_then(|id| id.as_local()) { + self.set_access_level_def_id(export_def_id, Some(AccessLevel::Exported)); + } + + if let Some(ns) = export.res.ns() { + let key = BindingKey { ident: export.ident, ns, disambiguator: 0 }; + let name_res = self.r.resolution(module, key); + if let Some(binding) = name_res.borrow().binding() { + set_import_binding_access_level(self, binding, module_level) + } + } + } + } + } + + /// Sets the access level of the `LocalDefId` corresponding to the given `NodeId`. + /// This function will panic if the `NodeId` does not have a `LocalDefId` + fn set_access_level( + &mut self, + node_id: NodeId, + access_level: Option, + ) -> Option { + self.set_access_level_def_id(self.r.local_def_id(node_id), access_level) + } + + fn set_access_level_def_id( + &mut self, + def_id: LocalDefId, + access_level: Option, + ) -> Option { + let old_level = self.r.access_levels.map.get(&def_id).copied(); + if old_level < access_level { + self.r.access_levels.map.insert(def_id, access_level.unwrap()); + self.changed = true; + access_level + } else { + old_level + } + } +} + +impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> { + fn visit_item(&mut self, item: &'ast ast::Item) { + let inherited_item_level = match item.kind { + // Resolved in rustc_privacy when types are available + ast::ItemKind::Impl(..) => return, + + // Only exported `macro_rules!` items are public, but they always are + ast::ItemKind::MacroDef(..) => { + let is_macro_export = + item.attrs.iter().any(|attr| attr.has_name(sym::macro_export)); + if is_macro_export { Some(AccessLevel::Public) } else { None } + } + + // Foreign modules inherit level from parents. + ast::ItemKind::ForeignMod(..) => self.prev_level, + + // Other `pub` items inherit levels from parents. + ast::ItemKind::ExternCrate(..) + | ast::ItemKind::Use(..) + | ast::ItemKind::Static(..) + | ast::ItemKind::Const(..) + | ast::ItemKind::Fn(..) + | ast::ItemKind::Mod(..) + | ast::ItemKind::GlobalAsm(..) + | ast::ItemKind::TyAlias(..) + | ast::ItemKind::Enum(..) + | ast::ItemKind::Struct(..) + | ast::ItemKind::Union(..) + | ast::ItemKind::Trait(..) + | ast::ItemKind::TraitAlias(..) => { + if item.vis.kind.is_pub() { + self.prev_level + } else { + None + } + } + + // Should be unreachable at this stage + ast::ItemKind::MacCall(..) => panic!( + "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage" + ), + }; + + let access_level = self.set_access_level(item.id, inherited_item_level); + + // Set access level of nested items. + // If it's a mod, also make the visitor walk all of its items + match item.kind { + ast::ItemKind::Mod(..) => { + if access_level.is_some() { + self.set_exports_access_level(self.r.local_def_id(item.id)); + } + + let orig_level = std::mem::replace(&mut self.prev_level, access_level); + visit::walk_item(self, item); + self.prev_level = orig_level; + } + + ast::ItemKind::ForeignMod(ForeignMod { ref items, .. }) => { + for nested in items { + if nested.vis.kind.is_pub() { + self.set_access_level(nested.id, access_level); + } + } + } + ast::ItemKind::Enum(EnumDef { ref variants }, _) => { + for variant in variants { + let variant_level = self.set_access_level(variant.id, access_level); + if let Some(ctor_id) = variant.data.ctor_id() { + self.set_access_level(ctor_id, access_level); + } + + for field in variant.data.fields() { + self.set_access_level(field.id, variant_level); + } + } + } + ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => { + if let Some(ctor_id) = def.ctor_id() { + self.set_access_level(ctor_id, access_level); + } + + for field in def.fields() { + if field.vis.kind.is_pub() { + self.set_access_level(field.id, access_level); + } + } + } + ast::ItemKind::Trait(ref trait_kind) => { + for nested in trait_kind.items.iter() { + self.set_access_level(nested.id, access_level); + } + } + + ast::ItemKind::ExternCrate(..) + | ast::ItemKind::Use(..) + | ast::ItemKind::Static(..) + | ast::ItemKind::Const(..) + | ast::ItemKind::GlobalAsm(..) + | ast::ItemKind::TyAlias(..) + | ast::ItemKind::TraitAlias(..) + | ast::ItemKind::MacroDef(..) + | ast::ItemKind::Fn(..) => return, + + // Unreachable kinds + ast::ItemKind::Impl(..) | ast::ItemKind::MacCall(..) => unreachable!(), + } + } +} diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 944e71851840c..052770b201a5b 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -383,8 +383,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { used: Cell::new(false), }); - debug!("add_import({:?})", import); - self.r.indeterminate_imports.push(import); match import.kind { // Don't add unresolved underscore imports to modules @@ -455,7 +453,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { prefix.is_empty() || prefix.len() == 1 && prefix[0].ident.name == kw::PathRoot }; match use_tree.kind { - ast::UseTreeKind::Simple(rename, ..) => { + ast::UseTreeKind::Simple(rename, id1, id2) => { let mut ident = use_tree.ident(); let mut module_path = prefix; let mut source = module_path.pop().unwrap(); @@ -565,7 +563,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }, type_ns_only, nested, + additional_ids: (id1, id2), }; + self.add_import( module_path, kind, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 2832f59a5efc6..e7f76a18ad31a 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -48,6 +48,9 @@ pub enum ImportKind<'a> { type_ns_only: bool, /// Did this import result from a nested import? ie. `use foo::{bar, baz};` nested: bool, + /// Additional `NodeId`s allocated to a `ast::UseTree` for automatically generated `use` statement + /// (eg. implicit struct constructors) + additional_ids: (NodeId, NodeId), }, Glob { is_prelude: bool, @@ -834,7 +837,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { import.span, ); import.vis.set(orig_vis); - source_bindings[ns].set(binding); } else { return; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 37be0e228d27a..2843774275883 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -50,6 +50,7 @@ use rustc_hir::TraitCandidate; use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; +use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::span_bug; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, MainDefinition, ResolverOutputs}; @@ -77,8 +78,11 @@ use imports::{Import, ImportKind, ImportResolver, NameResolution}; use late::{ConstantItemKind, HasGenericParams, PathSource, Rib, RibKind::*}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; +use crate::access_levels::AccessLevelsVisitor; + type Res = def::Res; +mod access_levels; mod build_reduced_graph; mod check_unused; mod def_collector; @@ -1052,6 +1056,8 @@ pub struct Resolver<'a> { /// they are declared in the static array generated by proc_macro_harness. proc_macros: Vec, confused_type_with_std_module: FxHashMap, + + access_levels: AccessLevels, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1407,6 +1413,7 @@ impl<'a> Resolver<'a> { trait_impls: Default::default(), proc_macros: Default::default(), confused_type_with_std_module: Default::default(), + access_levels: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); @@ -1452,10 +1459,12 @@ impl<'a> Resolver<'a> { let glob_map = self.glob_map; let main_def = self.main_def; let confused_type_with_std_module = self.confused_type_with_std_module; + let access_levels = self.access_levels; ResolverOutputs { definitions, cstore: Box::new(self.crate_loader.into_cstore()), visibilities, + access_levels, extern_crate_map, reexport_map, glob_map, @@ -1477,6 +1486,7 @@ impl<'a> Resolver<'a> { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); ResolverOutputs { definitions: self.definitions.clone(), + access_levels: self.access_levels.clone(), cstore: Box::new(self.cstore().clone()), visibilities: self.visibilities.clone(), extern_crate_map: self.extern_crate_map.clone(), @@ -1532,6 +1542,9 @@ impl<'a> Resolver<'a> { pub fn resolve_crate(&mut self, krate: &Crate) { self.session.time("resolve_crate", || { self.session.time("finalize_imports", || ImportResolver { r: self }.finalize_imports()); + self.session.time("resolve_access_levels", || { + AccessLevelsVisitor::compute_access_levels(self, krate) + }); self.session.time("finalize_macro_resolutions", || self.finalize_macro_resolutions()); self.session.time("late_resolve_crate", || self.late_resolve_crate(krate)); self.session.time("resolve_main", || self.resolve_main()); diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 199c05dc5df3e..62153efbb393b 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -16,7 +16,10 @@ use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root}; use super::search::SearchResult::*; mod entry; + +#[stable(feature = "rust1", since = "1.0.0")] pub use entry::{Entry, OccupiedEntry, OccupiedError, VacantEntry}; + use Entry::*; /// Minimum number of elements in a node that is not a root. diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index b1b917775c3fa..db8776ac7418d 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -24,6 +24,7 @@ mod take; mod take_while; mod zip; +#[stable(feature = "rust1", since = "1.0.0")] pub use self::{ chain::Chain, cycle::Cycle, enumerate::Enumerate, filter::Filter, filter_map::FilterMap, flatten::FlatMap, fuse::Fuse, inspect::Inspect, map::Map, peekable::Peekable, rev::Rev, diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs index de0663141e252..37b6f2e2565b2 100644 --- a/library/core/src/iter/sources.rs +++ b/library/core/src/iter/sources.rs @@ -6,6 +6,7 @@ mod repeat; mod repeat_with; mod successors; +#[stable(feature = "rust1", since = "1.0.0")] pub use self::repeat::{repeat, Repeat}; #[stable(feature = "iter_empty", since = "1.2.0")] diff --git a/library/core/src/iter/traits/mod.rs b/library/core/src/iter/traits/mod.rs index ffd745a46b12c..ed0fb634dbf05 100644 --- a/library/core/src/iter/traits/mod.rs +++ b/library/core/src/iter/traits/mod.rs @@ -5,15 +5,17 @@ mod exact_size; mod iterator; mod marker; -pub use self::accum::{Product, Sum}; -pub use self::collect::{Extend, FromIterator, IntoIterator}; -pub use self::double_ended::DoubleEndedIterator; -pub use self::exact_size::ExactSizeIterator; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::iterator::Iterator; +pub use self::{ + accum::{Product, Sum}, + collect::{Extend, FromIterator, IntoIterator}, + double_ended::DoubleEndedIterator, + exact_size::ExactSizeIterator, + iterator::Iterator, + marker::{FusedIterator, TrustedLen}, +}; + #[unstable(issue = "none", feature = "inplace_iteration")] pub use self::marker::InPlaceIterable; #[unstable(feature = "trusted_step", issue = "85731")] pub use self::marker::TrustedStep; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::marker::{FusedIterator, TrustedLen}; diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs index 179bdf7fe553a..100dab1e2493c 100644 --- a/library/std/src/io/buffered/mod.rs +++ b/library/std/src/io/buffered/mod.rs @@ -12,12 +12,12 @@ use crate::error; use crate::fmt; use crate::io::Error; -pub use bufreader::BufReader; -pub use bufwriter::BufWriter; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::{bufreader::BufReader, bufwriter::BufWriter, linewriter::LineWriter}; +use linewritershim::LineWriterShim; + #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] pub use bufwriter::WriterPanicked; -pub use linewriter::LineWriter; -use linewritershim::LineWriterShim; /// An error returned by [`BufWriter::into_inner`] which combines an error that /// happened while writing out the buffer, and the buffered writer object diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index ecc9e91b6bdb2..358ef22e708d7 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -261,31 +261,24 @@ use crate::str; use crate::sys; use crate::sys_common::memchr; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::buffered::IntoInnerError; #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] pub use self::buffered::WriterPanicked; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::buffered::{BufReader, BufWriter, LineWriter}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::copy::copy; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::cursor::Cursor; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::error::{Error, ErrorKind, Result}; #[unstable(feature = "internal_output_capture", issue = "none")] #[doc(no_inline, hidden)] pub use self::stdio::set_output_capture; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout}; -#[unstable(feature = "stdio_locked", issue = "86845")] -pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::stdio::{StderrLock, StdinLock, StdoutLock}; #[unstable(feature = "print_internals", issue = "none")] pub use self::stdio::{_eprint, _print}; +#[unstable(feature = "stdio_locked", issue = "86845")] +pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked}; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::util::{empty, repeat, sink, Empty, Repeat, Sink}; +pub use self::{ + buffered::{BufReader, BufWriter, IntoInnerError, LineWriter}, + copy::copy, + cursor::Cursor, + error::{Error, ErrorKind, Result}, + stdio::{stderr, stdin, stdout, Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock}, + util::{empty, repeat, sink, Empty, Repeat, Sink}, +}; #[unstable(feature = "read_buf", issue = "78485")] pub use self::readbuf::ReadBuf; diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs index cd92dcabdf520..d78049bce24c2 100644 --- a/library/std/src/os/linux/raw.rs +++ b/library/std/src/os/linux/raw.rs @@ -239,6 +239,7 @@ mod arch { target_arch = "riscv32" ))] mod arch { + #[stable(feature = "raw_ext", since = "1.1.0")] pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; } diff --git a/library/std/src/os/unix/io/raw.rs b/library/std/src/os/unix/io/raw.rs index 6317e31747119..a4d2ba797d9c4 100644 --- a/library/std/src/os/unix/io/raw.rs +++ b/library/std/src/os/unix/io/raw.rs @@ -2,4 +2,5 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "rust1", since = "1.0.0")] pub use crate::os::fd::raw::*; diff --git a/src/test/ui/lint/lint-pub-unreachable-for-nested-glob.rs b/src/test/ui/lint/lint-pub-unreachable-for-nested-glob.rs new file mode 100644 index 0000000000000..2df6d08e7aeb6 --- /dev/null +++ b/src/test/ui/lint/lint-pub-unreachable-for-nested-glob.rs @@ -0,0 +1,28 @@ +// check-pass + +#![deny(unreachable_pub)] + +pub use self::m1::*; + +mod m1 { + pub use self::m2::*; + + mod m2 { + pub struct Item1; + pub struct Item2; + } +} + + +pub use self::o1::{ Item42, Item24 }; + +mod o1 { + pub use self::o2::{ Item42, Item24 }; + + mod o2 { + pub struct Item42; + pub struct Item24; + } +} + +fn main() {} diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index ad23b16e02ec1..fae8080c02e41 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -3,6 +3,7 @@ #![warn(unreachable_pub)] #![recursion_limit = "256"] #![allow(clippy::match_like_matches_macro)] +#![allow(unreachable_pub)] #[macro_use] extern crate derive_new;