Repository navigation
Open
Labels
A-btreeArea: `std::collections::{BTreeMap, BTreeSet}`Area: `std::collections::{BTreeMap, BTreeSet}`A-hashtableArea: `std::collections::{HashMap, HashSet}`Area: `std::collections::{HashMap, HashSet}`C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Description
Feature gate: #![feature(map_try_insert)]
This is a tracking issue for BTreeMap::try_insert and HashMap::try_insert.
Unlike .insert(), .try_insert() does not overwrite existing values, and has a meaningful error type with more context. See #82764
Public API
// alloc::collections::btree_map
impl<K: Ord, V> BTreeMap<K, V> {
pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<'_, K, V>>;
}
pub struct OccupiedError<'a, K: 'a, V: 'a> {
pub entry: OccupiedEntry<'a, K, V>,
pub value: V,
}
impl<K: Debug + Ord, V: Debug> Debug for OccupiedError<'_, K, V>;
impl<'a, K: Debug + Ord, V: Debug> Display for OccupiedError<'a, K, V>;
impl<'a, K: Debug + Ord, V: Debug> Error for OccupiedError<'a, K, V>;
// std::collections::hash_map
impl<K: Eq + Hash, V, S: BuildHasher> HashMap<K, V, S> {
pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<'_, K, V>>;
}
pub struct OccupiedError<'a, K: 'a, V: 'a> {
pub entry: OccupiedEntry<'a, K, V>,
pub value: V,
}
impl<K: Debug, V: Debug> Debug for OccupiedError<'_, K, V>;
impl<'a, K: Debug, V: Debug> fmt::Display for OccupiedError<'a, K, V>;
impl<'a, K: Debug, V: Debug> Error for OccupiedError<'a, K, V>;Steps / History
- Issue: Missing a good way to insert into a HashMap while panicking on duplicates rfcs#3092
- Implementation: Add {BTreeMap,HashMap}::try_insert #82764
- Final commenting period (FCP)
- Stabilization PR
Unresolved Questions
- Should
OccupiedErrorimplement Error (and Display)? They are not especially useful with the captured lifetime. Add {BTreeMap,HashMap}::try_insert #82764 (comment) - Should
OccupiedErrorhave public fields, or accessors? Add {BTreeMap,HashMap}::try_insert #82764 (comment) -
try_might imply it returns anErrwhen allocating fails, which is not the case. Maybe rename it toinsert_newor something? - Put the
key: Kargument into theOccupiedError?
Reacted by John Kugelman, turbocool3r, Elichai Turkel, Finn Bear, Uros Mrkobrada, Joel Höner, cyqsimon, orzogc, Mincong Lu, Maximilian Roos and 5 more
Reacted by Reinis, Daniel, Ilia Vlasov, Andrii Lomakin, Oji Ishimori, Xin Liu, droogmic, Victor Barbu, Zizheng Guo, John Kugelman and 19 more
Metadata
Metadata
Assignees
Labels
A-btreeArea: `std::collections::{BTreeMap, BTreeSet}`Area: `std::collections::{BTreeMap, BTreeSet}`A-hashtableArea: `std::collections::{HashMap, HashSet}`Area: `std::collections::{HashMap, HashSet}`C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Activity
[-]Tracking Issue for XXX[/-][+]Tracking Issue for map_try_insert[/+]alecmocatta commentedon Mar 16, 2021
Is there a reason why this isn't implemented for
{Hash,BTree}Setas well?m-ou-se commentedon Mar 21, 2021
@alecmocatta The sets have a different kind of
insertmethod which doesn't replace any existing value. (They have a separatereplacemethod for that.) So in a way, theirinsertis already atry_insert, except it returns a bool rather than aResult.alecmocatta commentedon Mar 21, 2021
Personally I feel the motivation still stands.
vs
The latter communicate "panic on duplicate" much more obviously IMO. Plus
HashSet::try_insertwould save me having to look up "doestruemean it's a duplicate, or is itfalse?" every single time.nagisa commentedon Aug 17, 2021
I think it is important that this API returns the
Kvalue that was supplied to the function. Right now it isDropped internally and the key from the entry in the map is returned.linclelinkpart5 commentedon Aug 31, 2021
Seems like this could benefit from a lazy
try_insert_withvariant as well, where the value is computed from a closure only if the key isn't found?Luro02 commentedon Sep 27, 2021
Is the name of the method still open for debate?
I found myself confusing it with the try methods of for example
Vec.I expected
HashMap::try_insertto return an error if it failed to allocate the required space for the new item, so I was a bit astonished that this method has a different use.This is what I expected the method to look like;
Maybe it would be better to rename it to something like
HashMap::try_insert_or_keep?safinaskar commentedon Jan 19, 2022
@Luro02 . I agree. If we ever add method, which will report both "already exists" and "allocation error" errors, it will be called
try_try_insert, and this is very badc410-f3r commentedon Jan 21, 2022
HashMap::try_insert-> Tries to insert a key-value pair into the map (https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.try_insert).From my experience, any
try_*function/method from any situation simply means fallible. If there is a desire to segregate different prefixes from different contexts then the majority of all possible scenarios should be considered (which I personally don't think is worth it).Stargateur commentedon Jan 21, 2022
I think
insert_if_vacantis way better,tryis quite confusing with allocation error on collection. Also, try_ is too much generic on this case of specific "only if vacant".The downside of this is it's rather long. Since even
VacantEntryuseinsert()I think we should keepinsert()key word.My proposition is
insert_vacant(). (aka insert if vacant entry).joshtriplett commentedon Jan 23, 2022
I do think we need some way to handle the out-of-memory case. We don't have to solve that with this method, but I think we should think about naming with that in mind.
One naming possibility:
insert_mut, since it's likeinsertbut returns a&mut(or an error for the occupied case).cuviper commentedon Jan 23, 2022
Maybe
insert_new?40 remaining items
crisbour commentedon May 6, 2026
I agree with this, but this seems to already be supported by the Entry API
I got to this because I thought that I need
try_insert, but was put off by the fact that is not in a stable release. After I looked in the implementation I realized that using the Entry API is sufficient already, but didn't realize it use.TL;DR I am glad I found the function in the docs and pointed me to the Entry methods, so IMHO it's nice to have it in experimental for other people to notice it's implementation, but it superfluous to the already supported API.
Auto merge of #155360 - malezjaa:try_insert_changes, r=cuviper
Rollup merge of rust-lang#155360 - malezjaa:try_insert_changes, r=cuv…
Auto merge of #155360 - malezjaa:try_insert_changes, r=cuviper
Auto merge of #155360 - malezjaa:try_insert_changes, r=cuviper
Auto merge of #155360 - malezjaa:try_insert_changes, r=cuviper
Auto merge of #155360 - malezjaa:try_insert_changes, r=cuviper
Auto merge of #155360 - malezjaa:try_insert_changes, r=cuviper
Auto merge of #155360 - malezjaa:try_insert_changes, r=cuviper
Auto merge of #155360 - malezjaa:try_insert_changes, r=cuviper