Skip to content

Confusing lifetime on HashMap's Entry::get #49745

Closed
@Phlosioneer

Description

@Phlosioneer

The lifetime on the get() method's return value is bound to the lifetime of Entry. This is intended, as far as I can tell; however, the into_mut method allows the Entry to be converted into a reference bound to the HashMap's lifetime. But there is no way to get an immutable reference bound to the HashMap's lifetime.

This issue originally arose from this reddit thread. A minimal usecase example is:

fn get_symbol<'a>(symbols: &'a mut HashMap<u32, String>, id: u32) -> &'a str {
    match symbols.entry(id) {
        Entry::Occupied(e) => e.get().to_string(), // BAD! Should be e.into_mut().
        Entry::Vacant(e) => {
            // <snipped bookkeeping>...
            let new_symbol = "foobar".to_string();
            e.insert(new_symbol).as_str()
        }
    }
}

Playground

From my understanding, it should be safe to add an into_ref(self) -> &'a V method to fill this hole. It would be implemented as:

pub fn into_mut(self) -> &'a mut V {
    self.elem.into_refs().1
}

because the underlying structure FullBucket already supports an into_refs() method (with the same safety reasoning as into_mut_refs().)

It may also be useful to have an into_key(self) -> &'a K method. It should be just as safe (and would use basically the same implementation).

This was previously opened as an issue (#39099) but was self-closed when the poster found the into_mut() workaround.

I'd be happy to open a PR for this, but I want to make sure I'm not missing anything obvious here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsT-libs-apiRelevant to the library API 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