From b4b6b62e70f94c949b82f669498a925e3d4c3c2b Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Wed, 6 Jan 2021 17:19:47 +0300
Subject: [PATCH] resolve: Cleanup visibility resolution in enums and traits

---
 .../rustc_resolve/src/build_reduced_graph.rs  | 109 +++++++-----------
 1 file changed, 44 insertions(+), 65 deletions(-)

diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index c4ee4df2128..c4f3b3ff857 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -258,16 +258,16 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 Ok(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)))
             }
             ast::VisibilityKind::Inherited => {
-                if matches!(self.parent_scope.module.kind, ModuleKind::Def(DefKind::Enum, _, _)) {
-                    // Any inherited visibility resolved directly inside an enum
-                    // (e.g. variants or fields) inherits from the visibility of the enum.
-                    let parent_enum = self.parent_scope.module.def_id().unwrap().expect_local();
-                    Ok(self.r.visibilities[&parent_enum])
-                } else {
-                    // If it's not in an enum, its visibility is restricted to the `mod` item
-                    // that it's defined in.
-                    Ok(ty::Visibility::Restricted(self.parent_scope.module.nearest_parent_mod))
-                }
+                Ok(match self.parent_scope.module.kind {
+                    // Any inherited visibility resolved directly inside an enum or trait
+                    // (i.e. variants, fields, and trait items) inherits from the visibility
+                    // of the enum or trait.
+                    ModuleKind::Def(DefKind::Enum | DefKind::Trait, def_id, _) => {
+                        self.r.visibilities[&def_id.expect_local()]
+                    }
+                    // Otherwise, the visibility is restricted to the nearest parent `mod` item.
+                    _ => ty::Visibility::Restricted(self.parent_scope.module.nearest_parent_mod),
+                })
             }
             ast::VisibilityKind::Restricted { ref path, id, .. } => {
                 // For visibilities we are not ready to provide correct implementation of "uniform
@@ -1365,60 +1365,45 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
             return;
         }
 
+        let vis = self.resolve_visibility(&item.vis);
         let local_def_id = self.r.local_def_id(item.id);
         let def_id = local_def_id.to_def_id();
-        let vis = match ctxt {
-            AssocCtxt::Trait => {
-                let (def_kind, ns) = match item.kind {
-                    AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS),
-                    AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) => {
-                        if sig.decl.has_self() {
-                            self.r.has_self.insert(def_id);
-                        }
-                        (DefKind::AssocFn, ValueNS)
-                    }
-                    AssocItemKind::TyAlias(..) => (DefKind::AssocTy, TypeNS),
-                    AssocItemKind::MacCall(_) => bug!(), // handled above
-                };
 
-                let parent = self.parent_scope.module;
-                let expansion = self.parent_scope.expansion;
-                let res = Res::Def(def_kind, def_id);
-                // Trait item visibility is inherited from its trait when not specified explicitly.
-                let vis = match &item.vis.kind {
-                    ast::VisibilityKind::Inherited => {
-                        self.r.visibilities[&parent.def_id().unwrap().expect_local()]
-                    }
-                    _ => self.resolve_visibility(&item.vis),
-                };
-                // FIXME: For historical reasons the binding visibility is set to public,
-                // use actual visibility here instead, using enum variants as an example.
-                let vis_hack = ty::Visibility::Public;
-                self.r.define(parent, item.ident, ns, (res, vis_hack, item.span, expansion));
-                Some(vis)
-            }
-            AssocCtxt::Impl => {
-                // Trait impl item visibility is inherited from its trait when not specified
-                // explicitly. In that case we cannot determine it here in early resolve,
-                // so we leave a hole in the visibility table to be filled later.
-                // Inherent impl item visibility is never inherited from other items.
-                if matches!(item.vis.kind, ast::VisibilityKind::Inherited)
-                    && self
-                        .r
-                        .trait_impl_items
-                        .contains(&ty::DefIdTree::parent(&*self.r, def_id).unwrap().expect_local())
-                {
-                    None
-                } else {
-                    Some(self.resolve_visibility(&item.vis))
-                }
-            }
-        };
-
-        if let Some(vis) = vis {
+        if !(ctxt == AssocCtxt::Impl
+            && matches!(item.vis.kind, ast::VisibilityKind::Inherited)
+            && self
+                .r
+                .trait_impl_items
+                .contains(&ty::DefIdTree::parent(&*self.r, def_id).unwrap().expect_local()))
+        {
+            // Trait impl item visibility is inherited from its trait when not specified
+            // explicitly. In that case we cannot determine it here in early resolve,
+            // so we leave a hole in the visibility table to be filled later.
             self.r.visibilities.insert(local_def_id, vis);
         }
 
+        if ctxt == AssocCtxt::Trait {
+            let (def_kind, ns) = match item.kind {
+                AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS),
+                AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) => {
+                    if sig.decl.has_self() {
+                        self.r.has_self.insert(def_id);
+                    }
+                    (DefKind::AssocFn, ValueNS)
+                }
+                AssocItemKind::TyAlias(..) => (DefKind::AssocTy, TypeNS),
+                AssocItemKind::MacCall(_) => bug!(), // handled above
+            };
+
+            let parent = self.parent_scope.module;
+            let expansion = self.parent_scope.expansion;
+            let res = Res::Def(def_kind, def_id);
+            // FIXME: For historical reasons the binding visibility is set to public,
+            // use actual visibility here instead, using enum variants as an example.
+            let vis_hack = ty::Visibility::Public;
+            self.r.define(parent, item.ident, ns, (res, vis_hack, item.span, expansion));
+        }
+
         visit::walk_assoc_item(self, item, ctxt);
     }
 
@@ -1490,19 +1475,13 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         }
 
         let parent = self.parent_scope.module;
-        let vis = match variant.vis.kind {
-            // Variant visibility is inherited from its enum when not specified explicitly.
-            ast::VisibilityKind::Inherited => {
-                self.r.visibilities[&parent.def_id().unwrap().expect_local()]
-            }
-            _ => self.resolve_visibility(&variant.vis),
-        };
         let expn_id = self.parent_scope.expansion;
         let ident = variant.ident;
 
         // Define a name in the type namespace.
         let def_id = self.r.local_def_id(variant.id);
         let res = Res::Def(DefKind::Variant, def_id.to_def_id());
+        let vis = self.resolve_visibility(&variant.vis);
         self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id));
         self.r.visibilities.insert(def_id, vis);