about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBryanskiy <ivakin.kir@gmail.com>2022-09-25 14:25:02 +0300
committerBryanskiy <ivakin.kir@gmail.com>2022-10-16 21:47:14 +0300
commit496ccd982ce155d8f4026eb69c6af1a2b6b5628a (patch)
tree8f395156d2a217211f9959f6d4d74aaf8590cd2f
parente20fabb0d04cb25fe3159d58920856533f1b5cf0 (diff)
downloadrust-496ccd982ce155d8f4026eb69c6af1a2b6b5628a.tar.gz
rust-496ccd982ce155d8f4026eb69c6af1a2b6b5628a.zip
Populate effective visibilities in 'rustc_resolve'
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs136
-rw-r--r--compiler/rustc_privacy/src/lib.rs47
-rw-r--r--compiler/rustc_resolve/src/access_levels.rs129
-rw-r--r--src/librustdoc/visit_ast.rs8
-rw-r--r--src/librustdoc/visit_lib.rs10
-rw-r--r--src/test/ui/privacy/access_levels.rs33
-rw-r--r--src/test/ui/privacy/access_levels.stderr40
7 files changed, 240 insertions, 163 deletions
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index c595fbec0dd..556bd24d00f 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -1,12 +1,12 @@
 //! A pass that checks to make sure private fields and methods aren't used
 //! outside their scopes. This pass will also generate a set of exported items
 //! which are available for use externally when compiled as a library.
-use crate::ty::Visibility;
+use crate::ty::{DefIdTree, Visibility};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
-use rustc_span::def_id::LocalDefId;
+use rustc_span::def_id::{DefId, LocalDefId};
 use std::hash::Hash;
 
 /// Represents the levels of accessibility an item can have.
@@ -27,26 +27,36 @@ pub enum AccessLevel {
     Public,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Default)]
+impl AccessLevel {
+    pub fn all_levels() -> [AccessLevel; 4] {
+        [
+            AccessLevel::Public,
+            AccessLevel::Exported,
+            AccessLevel::Reachable,
+            AccessLevel::ReachableFromImplTrait,
+        ]
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
 pub struct EffectiveVisibility {
-    public: Option<Visibility>,
-    exported: Option<Visibility>,
-    reachable: Option<Visibility>,
-    reachable_from_impl_trait: Option<Visibility>,
+    public: Visibility,
+    exported: Visibility,
+    reachable: Visibility,
+    reachable_from_impl_trait: Visibility,
 }
 
 impl EffectiveVisibility {
-    pub fn get(&self, tag: AccessLevel) -> Option<&Visibility> {
+    pub fn get(&self, tag: AccessLevel) -> &Visibility {
         match tag {
             AccessLevel::Public => &self.public,
             AccessLevel::Exported => &self.exported,
             AccessLevel::Reachable => &self.reachable,
             AccessLevel::ReachableFromImplTrait => &self.reachable_from_impl_trait,
         }
-        .as_ref()
     }
 
-    fn get_mut(&mut self, tag: AccessLevel) -> &mut Option<Visibility> {
+    fn get_mut(&mut self, tag: AccessLevel) -> &mut Visibility {
         match tag {
             AccessLevel::Public => &mut self.public,
             AccessLevel::Exported => &mut self.exported,
@@ -56,7 +66,30 @@ impl EffectiveVisibility {
     }
 
     pub fn is_public_at_level(&self, tag: AccessLevel) -> bool {
-        self.get(tag).map_or(false, |vis| vis.is_public())
+        self.get(tag).is_public()
+    }
+
+    fn update(&mut self, vis: Visibility, tag: AccessLevel, tree: impl DefIdTree) -> bool {
+        let mut changed = false;
+        for level in AccessLevel::all_levels() {
+            if level <= tag {
+                let current_effective_vis = self.get_mut(level);
+                if *current_effective_vis != vis && vis.is_at_least(*current_effective_vis, tree) {
+                    changed = true;
+                    *current_effective_vis = vis;
+                }
+            }
+        }
+        changed
+    }
+
+    fn from_vis(vis: Visibility) -> EffectiveVisibility {
+        EffectiveVisibility {
+            public: vis,
+            exported: vis,
+            reachable: vis,
+            reachable_from_impl_trait: vis,
+        }
     }
 }
 
@@ -89,12 +122,7 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
 
     pub fn get_access_level(&self, id: Id) -> Option<AccessLevel> {
         self.get_effective_vis(id).and_then(|effective_vis| {
-            for level in [
-                AccessLevel::Public,
-                AccessLevel::Exported,
-                AccessLevel::Reachable,
-                AccessLevel::ReachableFromImplTrait,
-            ] {
+            for level in AccessLevel::all_levels() {
                 if effective_vis.is_public_at_level(level) {
                     return Some(level);
                 }
@@ -103,21 +131,6 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
         })
     }
 
-    pub fn set_access_level(&mut self, id: Id, tag: AccessLevel) {
-        let mut effective_vis = self.get_effective_vis(id).copied().unwrap_or_default();
-        for level in [
-            AccessLevel::Public,
-            AccessLevel::Exported,
-            AccessLevel::Reachable,
-            AccessLevel::ReachableFromImplTrait,
-        ] {
-            if level <= tag {
-                *effective_vis.get_mut(level) = Some(Visibility::Public);
-            }
-        }
-        self.map.insert(id, effective_vis);
-    }
-
     pub fn get_effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> {
         self.map.get(&id)
     }
@@ -129,6 +142,65 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
     pub fn map_id<OutId: Hash + Eq + Copy>(&self, f: impl Fn(Id) -> OutId) -> AccessLevels<OutId> {
         AccessLevels { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() }
     }
+
+    pub fn set_access_level(
+        &mut self,
+        id: Id,
+        default_vis: impl FnOnce() -> Visibility,
+        tag: AccessLevel,
+    ) {
+        let mut effective_vis = self
+            .get_effective_vis(id)
+            .copied()
+            .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
+        for level in AccessLevel::all_levels() {
+            if level <= tag {
+                *effective_vis.get_mut(level) = Visibility::Public;
+            }
+        }
+        self.map.insert(id, effective_vis);
+    }
+}
+
+impl<Id: Hash + Eq + Copy + Into<DefId>> AccessLevels<Id> {
+    // `parent_id` is not necessarily a parent in source code tree,
+    // it is the node from which the maximum effective visibility is inherited.
+    pub fn update(
+        &mut self,
+        id: Id,
+        nominal_vis: Visibility,
+        default_vis: impl FnOnce() -> Visibility,
+        parent_id: Id,
+        tag: AccessLevel,
+        tree: impl DefIdTree,
+    ) -> Result<bool, ()> {
+        let mut changed = false;
+        let mut current_effective_vis = self
+            .get_effective_vis(id)
+            .copied()
+            .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
+        if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) {
+            for level in AccessLevel::all_levels() {
+                if tag >= level {
+                    let inherited_effective_vis_at_level = *inherited_effective_vis.get(level);
+                    let calculated_effective_vis =
+                        if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {
+                            inherited_effective_vis_at_level
+                        } else {
+                            nominal_vis
+                        };
+                    changed |= current_effective_vis.update(calculated_effective_vis, level, tree);
+                }
+            }
+        } else {
+            if !id.into().is_crate_root() {
+                return Err(());
+            }
+            changed |= current_effective_vis.update(Visibility::Public, AccessLevel::Public, tree);
+        }
+        self.map.insert(id, current_effective_vis);
+        Ok(changed)
+    }
 }
 
 impl<Id> Default for AccessLevels<Id> {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 72867447250..3e5ecd0d401 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -433,7 +433,11 @@ impl<'tcx> EmbargoVisitor<'tcx> {
         let old_level = self.get(def_id);
         // Accessibility levels can only grow.
         if level > old_level {
-            self.access_levels.set_access_level(def_id, level.unwrap());
+            self.access_levels.set_access_level(
+                def_id,
+                || ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)),
+                level.unwrap(),
+            );
             self.changed = true;
             level
         } else {
@@ -921,31 +925,30 @@ pub struct TestReachabilityVisitor<'tcx, 'a> {
 
 impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
     fn access_level_diagnostic(&mut self, def_id: LocalDefId) {
-        let span = self.tcx.def_span(def_id.to_def_id());
         if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) {
-            let mut error_msg = String::new();
-
-            let effective_vis =
-                self.access_levels.get_effective_vis(def_id).copied().unwrap_or_default();
-            for level in [
-                AccessLevel::Public,
-                AccessLevel::Exported,
-                AccessLevel::Reachable,
-                AccessLevel::ReachableFromImplTrait,
-            ] {
-                let vis_str = match effective_vis.get(level) {
-                    Some(ty::Visibility::Restricted(restricted_id)) => {
-                        format!("pub({})", self.tcx.item_name(restricted_id.to_def_id()))
+            if let Some(effective_vis) = self.access_levels.get_effective_vis(def_id) {
+                let mut error_msg = String::new();
+                let span = self.tcx.def_span(def_id.to_def_id());
+                for level in AccessLevel::all_levels() {
+                    let vis_str = match effective_vis.get(level) {
+                        ty::Visibility::Restricted(restricted_id) => {
+                            if restricted_id.is_top_level_module() {
+                                "pub(crate)".to_string()
+                            } else if *restricted_id == self.tcx.parent_module_from_def_id(def_id) {
+                                "pub(self)".to_string()
+                            } else {
+                                format!("pub({})", self.tcx.item_name(restricted_id.to_def_id()))
+                            }
+                        }
+                        ty::Visibility::Public => "pub".to_string(),
+                    };
+                    if level != AccessLevel::Public {
+                        error_msg.push_str(", ");
                     }
-                    Some(ty::Visibility::Public) => "pub".to_string(),
-                    None => "pub(self)".to_string(),
-                };
-                if level != AccessLevel::Public {
-                    error_msg.push_str(", ");
+                    error_msg.push_str(&format!("{:?}: {}", level, vis_str));
                 }
-                error_msg.push_str(&format!("{:?}: {}", level, vis_str));
+                self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg });
             }
-            self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg });
         }
     }
 }
diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs
index d806441716f..1cef60949d8 100644
--- a/compiler/rustc_resolve/src/access_levels.rs
+++ b/compiler/rustc_resolve/src/access_levels.rs
@@ -1,4 +1,3 @@
-use crate::NameBinding;
 use crate::NameBindingKind;
 use crate::Resolver;
 use rustc_ast::ast;
@@ -6,12 +5,10 @@ use rustc_ast::visit;
 use rustc_ast::visit::Visitor;
 use rustc_ast::Crate;
 use rustc_ast::EnumDef;
-use rustc_ast::NodeId;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_middle::middle::privacy::AccessLevel;
-use rustc_middle::ty::DefIdTree;
-use rustc_span::sym;
+use rustc_middle::ty::{DefIdTree, Visibility};
 
 pub struct AccessLevelsVisitor<'r, 'a> {
     r: &'r mut Resolver<'a>,
@@ -25,7 +22,7 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
     pub fn compute_access_levels<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
         let mut visitor = AccessLevelsVisitor { r, changed: false };
 
-        visitor.set_access_level_def_id(CRATE_DEF_ID, Some(AccessLevel::Public));
+        visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, AccessLevel::Public);
         visitor.set_bindings_access_level(CRATE_DEF_ID);
 
         while visitor.changed {
@@ -45,67 +42,72 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
     /// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level).
     fn set_bindings_access_level(&mut self, module_id: LocalDefId) {
         assert!(self.r.module_map.contains_key(&&module_id.to_def_id()));
-        let module_level = self.r.access_levels.get_access_level(module_id);
-        if !module_level.is_some() {
-            return;
-        }
-        // 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, ns| {
-                while let NameBindingKind::Import { binding: nested_binding, import, .. } =
-                    binding.kind
-                {
-                    this.set_access_level(this.r.import_id_for_ns(import, ns), access_level);
-
-                    access_level = Some(AccessLevel::Exported);
-                    binding = nested_binding;
-                }
-            };
-
         let module = self.r.get_module(module_id.to_def_id()).unwrap();
         let resolutions = self.r.resolutions(module);
 
         for (key, name_resolution) in resolutions.borrow().iter() {
-            if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() {
-                let access_level = match binding.is_import() {
-                    true => {
-                        set_import_binding_access_level(self, binding, module_level, key.ns);
-                        Some(AccessLevel::Exported)
-                    },
-                    false => module_level,
-                };
+            if let Some(mut binding) = name_resolution.borrow().binding() && !binding.is_ambiguity() {
+                // 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.
+
+                // FIXME: tag and is_public() condition must be deleted,
+                // but assertion fail occurs in import_id_for_ns
+                let tag = if binding.is_import() { AccessLevel::Exported } else { AccessLevel::Public };
+                if binding.vis.is_public() {
+                    let mut prev_parent_id = module_id;
+                    let mut level = AccessLevel::Public;
+                    while let NameBindingKind::Import { binding: nested_binding, import, .. } =
+                        binding.kind
+                    {
+                        let id = self.r.local_def_id(self.r.import_id_for_ns(import, key.ns));
+                        self.update(
+                            id,
+                            binding.vis.expect_local(),
+                            prev_parent_id,
+                            level,
+                        );
+
+                        level = AccessLevel::Exported;
+                        prev_parent_id = id;
+                        binding = nested_binding;
+                    }
+                }
+
                 if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
-                    self.set_access_level_def_id(def_id, access_level);
+                    self.update(def_id, binding.vis.expect_local(), module_id, tag);
                 }
             }
         }
     }
 
-    /// 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(
+    fn update(
         &mut self,
         def_id: LocalDefId,
-        access_level: Option<AccessLevel>,
-    ) -> Option<AccessLevel> {
-        let old_level = self.r.access_levels.get_access_level(def_id);
-        if old_level < access_level {
-            self.r.access_levels.set_access_level(def_id, access_level.unwrap());
-            self.changed = true;
-            access_level
+        nominal_vis: Visibility,
+        parent_id: LocalDefId,
+        tag: AccessLevel,
+    ) {
+        let mut access_levels = std::mem::take(&mut self.r.access_levels);
+        let module_id =
+            self.r.get_nearest_non_block_module(def_id.to_def_id()).def_id().expect_local();
+        let res = access_levels.update(
+            def_id,
+            nominal_vis,
+            || Visibility::Restricted(module_id),
+            parent_id,
+            tag,
+            &*self.r,
+        );
+        if let Ok(changed) = res {
+            self.changed |= changed;
         } else {
-            old_level
+            self.r.session.delay_span_bug(
+                self.r.opt_span(def_id.to_def_id()).unwrap(),
+                "Can't update effective visibility",
+            );
         }
+        self.r.access_levels = access_levels;
     }
 }
 
@@ -125,16 +127,15 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> {
 
             // Foreign modules inherit level from parents.
             ast::ItemKind::ForeignMod(..) => {
-                let parent_level =
-                    self.r.access_levels.get_access_level(self.r.local_parent(def_id));
-                self.set_access_level(item.id, parent_level);
+                let parent_id = self.r.local_parent(def_id);
+                self.update(def_id, Visibility::Public, parent_id, AccessLevel::Public);
             }
 
             // Only exported `macro_rules!` items are public, but they always are
             ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => {
-                if item.attrs.iter().any(|attr| attr.has_name(sym::macro_export)) {
-                    self.set_access_level(item.id, Some(AccessLevel::Public));
-                }
+                let parent_id = self.r.local_parent(def_id);
+                let vis = self.r.visibilities[&def_id];
+                self.update(def_id, vis, parent_id, AccessLevel::Public);
             }
 
             ast::ItemKind::Mod(..) => {
@@ -146,19 +147,19 @@ impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> {
                 self.set_bindings_access_level(def_id);
                 for variant in variants {
                     let variant_def_id = self.r.local_def_id(variant.id);
-                    let variant_level = self.r.access_levels.get_access_level(variant_def_id);
                     for field in variant.data.fields() {
-                        self.set_access_level(field.id, variant_level);
+                        let field_def_id = self.r.local_def_id(field.id);
+                        let vis = self.r.visibilities[&field_def_id];
+                        self.update(field_def_id, vis, variant_def_id, AccessLevel::Public);
                     }
                 }
             }
 
             ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
-                let inherited_level = self.r.access_levels.get_access_level(def_id);
                 for field in def.fields() {
-                    if field.vis.kind.is_pub() {
-                        self.set_access_level(field.id, inherited_level);
-                    }
+                    let field_def_id = self.r.local_def_id(field.id);
+                    let vis = self.r.visibilities[&field_def_id];
+                    self.update(field_def_id, vis, def_id, AccessLevel::Public);
                 }
             }
 
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index e6cef4a326a..b8522ea5d8f 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::middle::privacy::AccessLevel;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{TyCtxt, Visibility};
 use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
@@ -230,7 +230,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     } else {
                         // All items need to be handled here in case someone wishes to link
                         // to them with intra-doc links
-                        self.cx.cache.access_levels.set_access_level(did, AccessLevel::Public);
+                        self.cx.cache.access_levels.set_access_level(
+                            did,
+                            || Visibility::Restricted(CRATE_DEF_ID),
+                            AccessLevel::Public,
+                        );
                     }
                 }
             }
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index 8221e0998d7..0511494668b 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -1,8 +1,8 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_ID};
 use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{TyCtxt, Visibility};
 
 // FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses
 
@@ -41,7 +41,11 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> {
         let old_level = self.access_levels.get_access_level(did);
         // Accessibility levels can only grow
         if level > old_level && !is_hidden {
-            self.access_levels.set_access_level(did, level.unwrap());
+            self.access_levels.set_access_level(
+                did,
+                || Visibility::Restricted(CRATE_DEF_ID),
+                level.unwrap(),
+            );
             level
         } else {
             old_level
diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs
index bf94d980678..cc074a4f958 100644
--- a/src/test/ui/privacy/access_levels.rs
+++ b/src/test/ui/privacy/access_levels.rs
@@ -1,44 +1,44 @@
 #![feature(rustc_attrs)]
 
 #[rustc_effective_visibility]
-mod outer { //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
+mod outer { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate)
     #[rustc_effective_visibility]
-    pub mod inner1 { //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+    pub mod inner1 { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
 
         #[rustc_effective_visibility]
-        extern "C" {} //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+        extern "C" {} //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
 
         #[rustc_effective_visibility]
-        pub trait PubTrait { //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+        pub trait PubTrait { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
             #[rustc_effective_visibility]
-            const A: i32; //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+            const A: i32; //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
             #[rustc_effective_visibility]
-            type B; //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+            type B; //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
         }
 
         #[rustc_effective_visibility]
         struct PrivStruct; //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
 
         #[rustc_effective_visibility]
-        pub union PubUnion { //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+        pub union PubUnion { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
             #[rustc_effective_visibility]
             a: u8, //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
             #[rustc_effective_visibility]
-            pub b: u8, //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+            pub b: u8, //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
         }
 
         #[rustc_effective_visibility]
-        pub enum Enum { //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+        pub enum Enum { //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
             #[rustc_effective_visibility]
-            A( //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+            A( //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
                 #[rustc_effective_visibility]
-                PubUnion,  //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+                PubUnion,  //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
             ),
         }
     }
 
     #[rustc_effective_visibility]
-    macro_rules! none_macro { //~ Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
+    macro_rules! none_macro { //~ Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate)
         () => {};
     }
 
@@ -49,9 +49,9 @@ mod outer { //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(sel
     }
 
     #[rustc_effective_visibility]
-    pub struct ReachableStruct { //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImplTrait: pub
+    pub struct ReachableStruct { //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub, ReachableFromImplTrait: pub
         #[rustc_effective_visibility]
-        pub a: u8, //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImplTrait: pub
+        pub a: u8, //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub, ReachableFromImplTrait: pub
     }
 }
 
@@ -62,14 +62,13 @@ pub fn foo() -> outer::ReachableStruct { outer::ReachableStruct {a: 0} }
 
 mod half_public_import {
     #[rustc_effective_visibility]
-    pub type HalfPublicImport = u8; //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+    pub type HalfPublicImport = u8; //~ ERROR Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
     #[rustc_effective_visibility]
     #[allow(non_upper_case_globals)]
-    pub(crate) const HalfPublicImport: u8 = 0; //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
+    pub(crate) const HalfPublicImport: u8 = 0; //~ ERROR Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate)
 }
 
 #[rustc_effective_visibility]
 pub use half_public_import::HalfPublicImport; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
-                                              //~^ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
 
 fn main() {}
diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr
index 81514d1fbab..19199a3eb87 100644
--- a/src/test/ui/privacy/access_levels.stderr
+++ b/src/test/ui/privacy/access_levels.stderr
@@ -1,22 +1,22 @@
-error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
+error: Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate)
   --> $DIR/access_levels.rs:4:1
    |
 LL | mod outer {
    | ^^^^^^^^^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:6:5
    |
 LL |     pub mod inner1 {
    |     ^^^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:9:9
    |
 LL |         extern "C" {}
    |         ^^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:12:9
    |
 LL |         pub trait PubTrait {
@@ -28,7 +28,7 @@ error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFr
 LL |         struct PrivStruct;
    |         ^^^^^^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:23:9
    |
 LL |         pub union PubUnion {
@@ -40,31 +40,31 @@ error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFr
 LL |             a: u8,
    |             ^^^^^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:27:13
    |
 LL |             pub b: u8,
    |             ^^^^^^^^^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:31:9
    |
 LL |         pub enum Enum {
    |         ^^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:33:13
    |
 LL |             A(
    |             ^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:35:17
    |
 LL |                 PubUnion,
    |                 ^^^^^^^^
 
-error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
+error: Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate)
   --> $DIR/access_levels.rs:41:5
    |
 LL |     macro_rules! none_macro {
@@ -76,13 +76,13 @@ error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
 LL |     macro_rules! public_macro {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub(crate), Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:52:5
    |
 LL |     pub struct ReachableStruct {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub(crate), Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:54:9
    |
 LL |         pub a: u8,
@@ -94,13 +94,13 @@ error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
 LL | pub use outer::inner1;
    |         ^^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:65:5
    |
 LL |     pub type HalfPublicImport = u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
+error: Public: pub(crate), Exported: pub(crate), Reachable: pub(crate), ReachableFromImplTrait: pub(crate)
   --> $DIR/access_levels.rs:68:5
    |
 LL |     pub(crate) const HalfPublicImport: u8 = 0;
@@ -112,23 +112,17 @@ error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
 LL | pub use half_public_import::HalfPublicImport;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
-  --> $DIR/access_levels.rs:72:9
-   |
-LL | pub use half_public_import::HalfPublicImport;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:14:13
    |
 LL |             const A: i32;
    |             ^^^^^^^^^^^^
 
-error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
+error: Public: pub(crate), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
   --> $DIR/access_levels.rs:16:13
    |
 LL |             type B;
    |             ^^^^^^
 
-error: aborting due to 22 previous errors
+error: aborting due to 21 previous errors