为什么在函数 returns 时从 `HashMap::get` 借用还没有结束?

Why does the borrow from `HashMap::get` not end when the function returns?

这是对我的问题的模拟,当借用结束得太晚时

use std::collections::HashMap;

struct Item {
    capacity: u64
}

struct Petrol {
    name: String,
    fuel: HashMap<&'static str, Item>
}

fn buy_gaz(p: &mut Petrol) {
   match p.fuel.get("gaz") {
      Some(gaz) => {
        fire_petrol(p); 
      }
      None => ()
   }
}

fn fire_petrol(p: &mut Petrol) {
    println!("Boom!");
    p.fuel.remove("gaz");
    p.fuel.remove("benzin");
}

fn main() {
    let mut bt = Petrol {
        name: "Britii Petrovich".to_string(),
        fuel: HashMap::new()
    };

    bt.fuel.insert("gaz", Item { capacity: 1000 });
    bt.fuel.insert("benzin", Item { capacity: 5000 });

    buy_gaz(&mut bt);
}

编译时我得到:

note: previous borrow of `p.fuel` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `p.fuel` until the borrow ends
match p.fuel.get("gaz") {
      ^~~~~~

为什么借用这么晚结束而不是在从 HashMap::get 退出时结束?我该如何解决我的问题?

PS:我编辑了我的第一个 post 以将结构添加到 HashMap,因为下面的决定适用于简单的类型(我认为具有默认的 Clone 特征),但没有不适用于自定义结构

如果您查看 documentation of HashMap::get,您会发现它 returns 和 Option<&V>。对映射的引用允许您对哈希映射进行零拷贝访问。缺点是,只要您有引用,就不能修改哈希映射,因为这可能会使您的引用无效。

分支 Some(gaz) 导致绑定 gaz 具有类型 &u64,其中引用指向您的哈希映射。如果将其更改为 Some(&gaz),您将获得值的副本而不是引用,并且甚至可以在该分支内修改散列映射。

Minimal Example in Playpen