Skip to content

{BTreeMap,BTreeSet}::append behaves differently to ::insert #145614

@tinnamchoi

Description

@tinnamchoi

I tried this code:

#[derive(Debug, Clone)]
struct Key {
    id: u32,
    name: String,
}

use std::cmp::Ordering;

impl PartialEq for Key {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl Eq for Key {}

impl PartialOrd for Key {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Key {
    fn cmp(&self, other: &Self) -> Ordering {
        self.id.cmp(&other.id)
    }
}

use std::collections::BTreeMap;

fn append(mut lhs: BTreeMap<Key, String>, mut rhs: BTreeMap<Key, String>) {
    lhs.append(&mut rhs);
    println!("append: {lhs:?}");
}
fn insert(mut lhs: BTreeMap<Key, String>, rhs: BTreeMap<Key, String>) {
    for (k, v) in rhs.into_iter() {
        lhs.insert(k, v);
    }
    println!("insert: {lhs:?}");
}

fn main() {
    let mut lhs = BTreeMap::new();
    let mut rhs = BTreeMap::new();

    lhs.insert(Key {
        id: 0,
        name: "lhs_k".to_string(),
    }, "lhs_v".to_string());
    rhs.insert(Key {
        id: 0,
        name: "rhs_k".to_string(),
    }, "rhs_v".to_string());

    append(lhs.clone(), rhs.clone());
    insert(lhs.clone(), rhs.clone());
}

The documentation for BTreeMap::append says If a key from other is already present in self, the respective value from self will be overwritten with the respective value from other.. There is no mention of the overwriting of keys, which aligns with the documentation and behaviour of BTreeMap::insert. (If the map did have this key present, the value is updated, and the old value is returned. The key is not updated, though; this matters for types that can be == without being identical.)

Therefore, I expected to see this happen:

append: {Key { id: 0, name: "lhs_k" }: "rhs_v"}
insert: {Key { id: 0, name: "lhs_k" }: "rhs_v"}

Instead, this happened:

append: {Key { id: 0, name: "rhs_k" }: "rhs_v"}
insert: {Key { id: 0, name: "lhs_k" }: "rhs_v"}

Meta

Tested on Rust Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=fa5d69959152003932b622e9f57e9b5e

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-collectionsArea: `std::collections`C-bugCategory: This is a bug.T-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