Skip to content

Tracking Issue for map_try_insert #82766

Open

Description

@m-ou-se

View all comments

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

Unresolved Questions

Activity

  1. added
    A-collectionsArea: `std::collections` (prefer A-binaryheap, A-btree, A-hashtable, A-linkedlist, A-vecdeque)
    T-libs-api[DEPRECATED; DO NOT USE]
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Mar 4, 2021
  2. changed the title [-]Tracking Issue for XXX[/-] [+]Tracking Issue for map_try_insert[/+] on Mar 4, 2021
  3. alecmocatta commented on Mar 16, 2021

    @alecmocatta
    Contributor

    Is there a reason why this isn't implemented for {Hash,BTree}Set as well?

  4. m-ou-se commented on Mar 21, 2021

    @m-ou-se
    MemberAuthor

    Is there a reason why this isn't implemented for {Hash,BTree}Set as well?

    @alecmocatta The sets have a different kind of insert method which doesn't replace any existing value. (They have a separate replace method for that.) So in a way, their insert is already a try_insert, except it returns a bool rather than a Result.

  5. alecmocatta commented on Mar 21, 2021

    @alecmocatta
    Contributor

    Personally I feel the motivation still stands.

    let x = map.insert(0, ());
    assert!(x.is_none());
    let x = set.insert(0);
    assert!(x);

    vs

    map.try_insert(0, ()).unwrap();
    set.try_insert(0).unwrap();

    The latter communicate "panic on duplicate" much more obviously IMO. Plus HashSet::try_insert would save me having to look up "does true mean it's a duplicate, or is it false?" every single time.

  6. nagisa commented on Aug 17, 2021

    @nagisa
    Member

    I think it is important that this API returns the K value that was supplied to the function. Right now it is Dropped internally and the key from the entry in the map is returned.

  7. linclelinkpart5 commented on Aug 31, 2021

    @linclelinkpart5

    Seems like this could benefit from a lazy try_insert_with variant as well, where the value is computed from a closure only if the key isn't found?

  8. Luro02 commented on Sep 27, 2021

    @Luro02
    Contributor

    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_insert to 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;

    pub fn try_insert(&mut self, key: K, value: V) -> Result<Option<V>, TryReserveError>;

    Maybe it would be better to rename it to something like HashMap::try_insert_or_keep?

  9. safinaskar commented on Jan 19, 2022

    @safinaskar
    Contributor

    @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 bad

  10. c410-f3r commented on Jan 21, 2022

    @c410-f3r
    Contributor

    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).

  11. Stargateur commented on Jan 21, 2022

    @Stargateur
    Contributor

    I think insert_if_vacant is way better, try is 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 VacantEntry use insert() I think we should keep insert() key word.

    My proposition is insert_vacant(). (aka insert if vacant entry).

  12. joshtriplett commented on Jan 23, 2022

    @joshtriplett
    Member

    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 like insert but returns a &mut (or an error for the occupied case).

  13. cuviper commented on Jan 23, 2022

    @cuviper
    Member

    Maybe insert_new?

  14. 40 remaining items

  15. crisbour commented on May 6, 2026

    @crisbour

    Seems like this could benefit from a lazy try_insert_with variant as well, where the value is computed from a closure only if the key isn't found?

    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.

  16. added a commit that references this issue on May 15, 2026
  17. added a commit that references this issue on May 15, 2026
  18. added a commit that references this issue on May 15, 2026
  19. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    T-libs-api[DEPRECATED; DO NOT USE]
    on Aug 12, 2026
  20. added
    A-btreeArea: `std::collections::{BTreeMap, BTreeSet}`
    A-hashtableArea: `std::collections::{HashMap, HashSet}`
    and removed
    A-collectionsArea: `std::collections` (prefer A-binaryheap, A-btree, A-hashtable, A-linkedlist, A-vecdeque)
    on Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-btreeArea: `std::collections::{BTreeMap, BTreeSet}`A-hashtableArea: `std::collections::{HashMap, HashSet}`C-tracking-issueCategory: 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.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions