Auto merge of #87487 - lambinoo:I-64762_unreachable_pub_lint, r=petrochenkov

Fixes wrong unreachable_pub lints on nested and glob public reexport

Linked issues: #64762 & #82064
This commit is contained in:
bors 2022-01-10 08:55:53 +00:00
commit df035a33b2
19 changed files with 359 additions and 218 deletions

View file

@ -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.
//

View file

@ -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};

View file

@ -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<Id = LocalDefId> {
pub map: FxHashMap<Id, AccessLevel>,
}

View file

@ -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<CrateStoreDyn>,
pub visibilities: FxHashMap<LocalDefId, Visibility>,
pub access_levels: AccessLevels,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,

View file

@ -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<AccessLevel>,
) -> Option<AccessLevel> {
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<AccessLevel>) -> Option<AccessLevel> {
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 <https://github.com/rust-lang/rust/pull/57922#discussion_r251234202>.
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::<AccessLevel>::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::<AccessLevel>::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)
}

View file

@ -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<AccessLevel>,
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::<Vec<_>>();
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<AccessLevel>,
) -> Option<AccessLevel> {
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<AccessLevel>,
) -> Option<AccessLevel> {
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!(),
}
}
}

View file

@ -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,

View file

@ -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;

View file

@ -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<NodeId>;
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<NodeId>,
confused_type_with_std_module: FxHashMap<Span, Span>,
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());

View file

@ -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.

View file

@ -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,

View file

@ -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")]

View file

@ -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};

View file

@ -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

View file

@ -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 = "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::stdio::{StderrLock, StdinLock, StdoutLock};
#[unstable(feature = "print_internals", issue = "none")]
pub use self::stdio::{_eprint, _print};
#[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;

View file

@ -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};
}

View file

@ -2,4 +2,5 @@
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::os::fd::raw::*;

View file

@ -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() {}

View file

@ -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;