Skip to content

Rust could release borrows in match against the matched object in some cases #35132

Closed
@toumorokoshi

Description

@toumorokoshi

It seems like Rust's borrow checker could be more lenient on match checks where the match is an enum with no references to the object being matched.

I tried this code:

use std::collections::HashMap;

fn main() {
    let mut my_map: HashMap<String, String> = HashMap::new();
    lazy_get(&mut my_map, String::from("foo"));
}

/*
// what I want to do, but it leads to an error
fn lazy_get(map: &mut HashMap<String, String>, key: String) -> String {
    match map.get(&key) {
        Some(v) => v.clone(),
        None => {
            let new_val = key.clone();
            map.insert(new_val, new_val);
            new_val
        }
    }
} */

// my workaround
fn lazy_get(map: &mut HashMap<String, String>, key: String) -> String {
    if let None = map.get(&key) {
        let new_value = key.clone();
        map.insert(key.clone(), new_value.clone());
        return new_value;
    }
    match map.get(&key) {
        Some(v) => v.clone(),
        // this case will never happen, but I have to add it
        // to satisfy all matches.
        None => key.clone()
    }
}

I expected to see this happen:

In the commented example, I would expect that if the map is matched to None, it would release the borrow on the map, thereby allowing me to mutate it. For this particular case, it would make the code a bit cleaner, by omitting unused code that exists for the sake of the match completeness.

Instead, this happened: borrow checker complains about an immutable borrow existing previously.

Tried this on the rust playground, against the nightly as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions