use std::collections::HashMap;
use std::collections::hash_map::Entry::*;
struct A {
map: HashMap<String, String>,
i: i32
}
impl A {
fn test(&mut self) {
match self.map.get("abc") {
None => {},
Some(x) => self.trigger(&x)
}
}
fn trigger(&mut self, x: &str) {
self.i += 1;
}
}
Run Code Online (Sandbox Code Playgroud)
该代码不起作用,因为可变self.trigger借用self,同时在范围内self.map.get保持不可变借用self。
鉴于我可以确保不trigger修改,有什么方法可以使其工作吗self.map?
我不能一成不变地trigger借用self,就像 我可以为 self.callbacks: Vec<Box<FnMut>>? 一样借用 self 吗?
我正在使用 rustc 1.19.0-nightly。
小智 5
这里的问题是借用检查器不知道trigger仅发生变化self.i。据借用检查员所知,它也可能会改变self.map,这是不安全的。
解决方案是告诉借用检查员更多有关trigger更改的信息。
实现此目的的一种方法是将trigger需要可变借用的所有内容移至其自己的结构中,然后为该结构实现触发器:
use std::collections::HashMap;
use std::collections::hash_map::Entry::*;
struct TriggerThing {
i: i32
}
impl TriggerThing {
fn trigger(&mut self, _: &HashMap<String, String>, x: &str) {
self.i += 1;
}
}
struct A {
map: HashMap<String, String>,
trigger_thing: TriggerThing,
}
impl A {
fn test(&mut self) {
// Its fine to have a immutable borrow of self.map
// and a mutable borrow of self.trigger_thing at the
// same time, since borrowing self.trigger_thing does not
// imply a mutable borrow of self.map.
if let Some(x) = self.map.get("abc") {
// Notice that we can still give self.trigger_thing
// access to self.map, as long as we only
// give it an immutable reference
self.trigger_thing.trigger(&self.map, &x)
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您之前没有见过它的精彩语法,请参阅《Rust Book: If Let》 。if let
| 归档时间: |
|
| 查看次数: |
1532 次 |
| 最近记录: |