From 5e5d82e8033904cbae8d386983ced7b7b6e329b7 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Tue, 19 Dec 2023 23:16:49 +0300
Subject: [PATCH] resolve: Eagerly feed closure visibilities

Also factor out all tcx-dependent operations performed for every created definition into `TyCtxt::create_def`
---
 compiler/rustc_ast_lowering/src/lib.rs  |  6 +-----
 compiler/rustc_middle/src/ty/context.rs | 25 +++++++++++++++++++++----
 compiler/rustc_privacy/src/lib.rs       |  9 ---------
 compiler/rustc_resolve/src/lib.rs       |  5 +----
 4 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index e29ecf55e2ff5..47b9298162601 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -60,7 +60,7 @@ use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{ConstArg, GenericArg, ItemLocalMap, ParamName, TraitCandidate};
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_middle::span_bug;
-use rustc_middle::ty::{ResolverAstLowering, TyCtxt, Visibility};
+use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_session::parse::{add_feature_diagnostics, feature_err};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{DesugaringKind, Span, DUMMY_SP};
@@ -1651,10 +1651,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         );
         debug!(?opaque_ty_def_id);
 
-        // Meaningless, but provided so that all items have visibilities.
-        let parent_mod = self.tcx.parent_module_from_def_id(opaque_ty_def_id).to_def_id();
-        self.tcx.feed_local_def_id(opaque_ty_def_id).visibility(Visibility::Restricted(parent_mod));
-
         // Map from captured (old) lifetime to synthetic (new) lifetime.
         // Used to resolve lifetimes in the bounds of the opaque.
         let mut captured_to_synthesized_mapping = LocalDefIdMap::default();
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 6a6ed59fabfa9..b5ca700c2cd5a 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1039,17 +1039,34 @@ impl<'tcx> TyCtxtAt<'tcx> {
         // This is fine because:
         // - those queries are `eval_always` so we won't miss their result changing;
         // - this write will have happened before these queries are called.
-        let data = def_kind.def_path_data(name);
-        let key = self.untracked.definitions.write().create_def(parent, data);
+        let def_id = self.tcx.create_def(parent, name, def_kind);
 
-        let feed = TyCtxtFeed { tcx: self.tcx, key };
-        feed.def_kind(def_kind);
+        let feed = self.tcx.feed_local_def_id(def_id);
         feed.def_span(self.span);
         feed
     }
 }
 
 impl<'tcx> TyCtxt<'tcx> {
+    /// `tcx`-dependent operations performed for every created definition.
+    pub fn create_def(self, parent: LocalDefId, name: Symbol, def_kind: DefKind) -> LocalDefId {
+        let data = def_kind.def_path_data(name);
+        let def_id = self.untracked.definitions.write().create_def(parent, data);
+
+        let feed = self.feed_local_def_id(def_id);
+        feed.def_kind(def_kind);
+        // Unique types created for closures participate in type privacy checking.
+        // They have visibilities inherited from the module they are defined in.
+        // Visibilities for opaque types are meaningless, but still provided
+        // so that all items have visibilities.
+        if matches!(def_kind, DefKind::Closure | DefKind::OpaqueTy) {
+            let parent_mod = self.parent_module_from_def_id(def_id).to_def_id();
+            feed.visibility(ty::Visibility::Restricted(parent_mod));
+        }
+
+        def_id
+    }
+
     pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
         // Create a dependency to the red node to be sure we re-execute this when the amount of
         // definitions change.
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 61f6a2b18ae60..be9c6b7258330 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1765,15 +1765,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
 
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
-        visibility: |tcx, def_id| {
-            // Unique types created for closures participate in type privacy checking.
-            // They have visibilities inherited from the module they are defined in.
-            // FIXME: Consider evaluating visibilities for closures eagerly, like for all
-            // other nodes. However, unlike for others, for closures it may cause a perf
-            // regression, because closure visibilities are not commonly queried.
-            assert_eq!(tcx.def_kind(def_id), DefKind::Closure);
-            ty::Visibility::Restricted(tcx.parent_module_from_def_id(def_id).to_def_id())
-        },
         effective_visibilities,
         check_private_in_public,
         check_mod_privacy,
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 670fdcfb0d264..75ec594eb9b98 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1225,10 +1225,7 @@ impl<'tcx> Resolver<'_, 'tcx> {
         );
 
         // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()`
-        let def_id = self.tcx.untracked().definitions.write().create_def(parent, data);
-
-        let feed = self.tcx.feed_local_def_id(def_id);
-        feed.def_kind(def_kind);
+        let def_id = self.tcx.create_def(parent, name, def_kind);
 
         // Create the definition.
         if expn_id != ExpnId::root() {