From ef5513f278106de9b6c005152fe832be5e197465 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Thu, 14 Mar 2024 22:45:57 +0300
Subject: [PATCH] Fill in HIR hash for associated opaque types

---
 compiler/rustc_ast_lowering/src/lib.rs    | 19 ++--------------
 compiler/rustc_middle/src/hir/mod.rs      | 27 +++++++++++++++++++++++
 compiler/rustc_ty_utils/src/assoc.rs      | 12 +++++++---
 tests/ui/async-await/in-trait/hir-hash.rs | 11 +++++++++
 4 files changed, 49 insertions(+), 20 deletions(-)
 create mode 100644 tests/ui/async-await/in-trait/hir-hash.rs

diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 94e1e06a95453..9f63adb1e29ec 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -642,23 +642,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let bodies = SortedMap::from_presorted_elements(bodies);
 
         // Don't hash unless necessary, because it's expensive.
-        let (opt_hash_including_bodies, attrs_hash) = if self.tcx.needs_crate_hash() {
-            self.tcx.with_stable_hashing_context(|mut hcx| {
-                let mut stable_hasher = StableHasher::new();
-                node.hash_stable(&mut hcx, &mut stable_hasher);
-                // Bodies are stored out of line, so we need to pull them explicitly in the hash.
-                bodies.hash_stable(&mut hcx, &mut stable_hasher);
-                let h1 = stable_hasher.finish();
-
-                let mut stable_hasher = StableHasher::new();
-                attrs.hash_stable(&mut hcx, &mut stable_hasher);
-                let h2 = stable_hasher.finish();
-
-                (Some(h1), Some(h2))
-            })
-        } else {
-            (None, None)
-        };
+        let (opt_hash_including_bodies, attrs_hash) =
+            self.tcx.hash_owner_nodes(node, &bodies, &attrs);
         let num_nodes = self.item_local_id_counter.as_usize();
         let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
         let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 61bdb5d4bb705..f9fa8ac2f7aa5 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -8,6 +8,9 @@ pub mod place;
 
 use crate::query::Providers;
 use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::sorted_map::SortedMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
@@ -121,6 +124,30 @@ impl<'tcx> TyCtxt<'tcx> {
         self.opt_parent(def_id.into())
             .is_some_and(|parent| matches!(self.def_kind(parent), DefKind::ForeignMod))
     }
+
+    pub fn hash_owner_nodes(
+        self,
+        node: OwnerNode<'_>,
+        bodies: &SortedMap<ItemLocalId, &Body<'_>>,
+        attrs: &SortedMap<ItemLocalId, &[rustc_ast::Attribute]>,
+    ) -> (Option<Fingerprint>, Option<Fingerprint>) {
+        if self.needs_crate_hash() {
+            self.with_stable_hashing_context(|mut hcx| {
+                let mut stable_hasher = StableHasher::new();
+                node.hash_stable(&mut hcx, &mut stable_hasher);
+                // Bodies are stored out of line, so we need to pull them explicitly in the hash.
+                bodies.hash_stable(&mut hcx, &mut stable_hasher);
+                let h1 = stable_hasher.finish();
+
+                let mut stable_hasher = StableHasher::new();
+                attrs.hash_stable(&mut hcx, &mut stable_hasher);
+                let h2 = stable_hasher.finish();
+                (Some(h1), Some(h2))
+            })
+        } else {
+            (None, None)
+        }
+    }
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 3f628092190b5..4bcbf1c037499 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -240,8 +240,14 @@ fn associated_types_for_impl_traits_in_associated_fn(
 
 fn feed_hir(feed: &TyCtxtFeed<'_, LocalDefId>) {
     feed.local_def_id_to_hir_id(HirId::make_owner(feed.def_id()));
+
+    let node = hir::OwnerNode::AssocOpaqueTy(&hir::AssocOpaqueTy {});
+    let bodies = Default::default();
+    let attrs = hir::AttributeMap::EMPTY;
+
+    let (opt_hash_including_bodies, _) = feed.tcx.hash_owner_nodes(node, &bodies, &attrs.map);
     feed.opt_hir_owner_nodes(Some(feed.tcx.arena.alloc(hir::OwnerNodes {
-        opt_hash_including_bodies: None,
+        opt_hash_including_bodies,
         nodes: IndexVec::from_elem_n(
             hir::ParentedNode {
                 parent: hir::ItemLocalId::INVALID,
@@ -249,9 +255,9 @@ fn feed_hir(feed: &TyCtxtFeed<'_, LocalDefId>) {
             },
             1,
         ),
-        bodies: Default::default(),
+        bodies,
     })));
-    feed.feed_owner_id().hir_attrs(hir::AttributeMap::EMPTY);
+    feed.feed_owner_id().hir_attrs(attrs);
 }
 
 /// Given an `opaque_ty_def_id` corresponding to an `impl Trait` in an associated
diff --git a/tests/ui/async-await/in-trait/hir-hash.rs b/tests/ui/async-await/in-trait/hir-hash.rs
new file mode 100644
index 0000000000000..8324fec8282f1
--- /dev/null
+++ b/tests/ui/async-await/in-trait/hir-hash.rs
@@ -0,0 +1,11 @@
+// Issue #122508
+
+//@ check-pass
+//@ incremental
+//@ edition:2021
+
+trait MyTrait {
+    async fn bar(&self) -> i32;
+}
+
+fn main() {}