From 72f25eea3398e9dda3db71a423baea334916d19c Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Mon, 20 Apr 2026 13:22:22 +0300 Subject: [PATCH 1/3] Replace `ShardedHashMap` method `insert` with debug-checked `insert_unique` --- compiler/rustc_data_structures/src/sharded.rs | 24 ++++++++++++------- .../rustc_middle/src/mir/interpret/mod.rs | 19 ++++++--------- compiler/rustc_middle/src/query/caches.rs | 4 +--- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index e10ccccad5bb..48b6da6ed48c 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -1,6 +1,6 @@ use std::borrow::Borrow; use std::hash::{Hash, Hasher}; -use std::{iter, mem}; +use std::iter; use either::Either; use hashbrown::hash_table::{self, Entry, HashTable}; @@ -183,19 +183,25 @@ pub fn get_or_insert_with(&self, key: K, default: impl FnOnce() -> V) -> V } } + /// Insert value into the [`ShardedHashMap`] with unique key. + /// + /// Checks uniqness if debug_assertions enabled. #[inline] - pub fn insert(&self, key: K, value: V) -> Option { + pub fn insert_unique(&self, key: K, value: V) { let hash = make_hash(&key); let mut shard = self.lock_shard_by_hash(hash); - match table_entry(&mut shard, hash, &key) { - Entry::Occupied(e) => { - let previous = mem::replace(&mut e.into_mut().1, value); - Some(previous) + cfg_select! { + debug_assertions => match table_entry(&mut shard, hash, &key) { + Entry::Occupied(_) => { + panic!("tried to insert key that's already present"); + } + Entry::Vacant(e) => { + e.insert((key, value)); + } } - Entry::Vacant(e) => { - e.insert((key, value)); - None + _ => { + shard.insert_unique(hash, (key, value), |(k, _)| make_hash(k)); } } } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index b3ec4439e354..84a4e523d95c 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -473,9 +473,8 @@ fn reserve_and_set_dedup(self, alloc: GlobalAlloc<'tcx>, salt: usize) -> AllocId } let id = self.alloc_map.reserve(); debug!("creating alloc {:?} with id {id:?}", alloc_salt.0); - let had_previous = self.alloc_map.to_alloc.insert(id, alloc_salt.0.clone()).is_some(); // We just reserved, so should always be unique. - assert!(!had_previous); + self.alloc_map.to_alloc.insert_unique(id, alloc_salt.0.clone()); dedup.insert(alloc_salt, id); id } @@ -548,21 +547,17 @@ pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> { } /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to - /// call this function twice, even with the same `Allocation` will ICE the compiler. + /// call this function twice, even with the same `Allocation` will ICE the compiler if + /// debug_assertions are enabled. pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) { - if let Some(old) = self.alloc_map.to_alloc.insert(id, GlobalAlloc::Memory(mem)) { - bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}"); - } + self.alloc_map.to_alloc.insert_unique(id, GlobalAlloc::Memory(mem)) } /// Freezes an `AllocId` created with `reserve` by pointing it at a static item. Trying to - /// call this function twice, even with the same `DefId` will ICE the compiler. + /// call this function twice, even with the same `DefId` will ICE the compiler if + /// debug_assertions are enabled. pub fn set_nested_alloc_id_static(self, id: AllocId, def_id: LocalDefId) { - if let Some(old) = - self.alloc_map.to_alloc.insert(id, GlobalAlloc::Static(def_id.to_def_id())) - { - bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}"); - } + self.alloc_map.to_alloc.insert_unique(id, GlobalAlloc::Static(def_id.to_def_id())) } } diff --git a/compiler/rustc_middle/src/query/caches.rs b/compiler/rustc_middle/src/query/caches.rs index 0c71a98b7fb2..665d4f4d7dfa 100644 --- a/compiler/rustc_middle/src/query/caches.rs +++ b/compiler/rustc_middle/src/query/caches.rs @@ -65,9 +65,7 @@ fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> { #[inline] fn complete(&self, key: K, value: V, index: DepNodeIndex) { - // We may be overwriting another value. This is all right, since the dep-graph - // will check that the value fingerprint matches. - self.cache.insert(key, (value, index)); + self.cache.insert_unique(key, (value, index)); } fn for_each(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) { From 93d018695758deb1545bc2b8dfb64b541962915e Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Mon, 20 Apr 2026 13:51:01 +0300 Subject: [PATCH 2/3] Fix typo --- compiler/rustc_data_structures/src/sharded.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 48b6da6ed48c..5cce53efff49 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -185,7 +185,7 @@ pub fn get_or_insert_with(&self, key: K, default: impl FnOnce() -> V) -> V /// Insert value into the [`ShardedHashMap`] with unique key. /// - /// Checks uniqness if debug_assertions enabled. + /// Checks uniqueness if debug_assertions enabled. #[inline] pub fn insert_unique(&self, key: K, value: V) { let hash = make_hash(&key); From fa4d2ad67113d68bcf0e8732e50e8626372dc7ff Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Wed, 22 Apr 2026 12:39:19 +0300 Subject: [PATCH 3/3] Clarify behavior of ShardedHashMap::insert_unique --- compiler/rustc_data_structures/src/sharded.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 5cce53efff49..7be6b8dc41d9 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -185,7 +185,9 @@ pub fn get_or_insert_with(&self, key: K, default: impl FnOnce() -> V) -> V /// Insert value into the [`ShardedHashMap`] with unique key. /// - /// Checks uniqueness if debug_assertions enabled. + /// This function panics if debug_assertions are enabled and uniqueness is violated. + /// If uniqueness is violated but debug_assertions are disabled then lookups will arbitrarily + /// return one of the inserted elements. #[inline] pub fn insert_unique(&self, key: K, value: V) { let hash = make_hash(&key);