为什么`Option::map`适用于不可变数据,但不适用于可变数据

问题描述 投票:0回答:1

为什么以下示例中的不可变版本可以工作,但可变版本无法编译并出现错误

error: lifetime may not live long enough

trait Car {
    fn honk(&self);
}

struct CarCollection {
    cars: HashMap<usize, Box<dyn Car>>,
}

impl CarCollection {
    // Does compile
    fn get(&self, id: usize) -> Option<&dyn Car> {
        self.cars.get(&id).map(|c| c.as_ref())
    }

    // Does not compile
    fn get_mut(&mut self, id: usize) -> Option<&mut dyn Car> {
        self.cars.get_mut(&id).map(|c| c.as_mut())
    }
}

我知道我可以通过以下方式解决这个问题:

if let Some(car) = self.cars.get_mut(id) {
    Some(car.as_mut())
} else {
    None
}

尽管如此,我对此感到非常困惑,想知道这是怎么回事?我认为可变引用和不可变引用之间的生命周期没有区别。

游乐场

rust reference immutability mutable rust-lifetimes
1个回答
0
投票

这与 trait 对象生命周期省略规则有关。

struct CarCollection {
    cars: HashMap<usize, Box<dyn Car>>,
}

这里,省略规则导致了这个隐含的生命周期:

struct CarCollection {
    cars: HashMap<usize, Box<dyn Car + 'static>>,
}

现在我们来看看这个方法:

fn get_mut(&mut self, id: usize) -> Option<&mut dyn Car>

当我们对省略的引用生命周期进行脱糖处理时,我们得到:

fn get_mut<'a>(&'a mut self, id: usize) -> Option<&'a mut dyn Car>

然后,根据特征对象生命周期省略规则,我们得到这样的结果:

fn get_mut<'a>(&'a mut self, id: usize) -> Option<&'a mut (dyn Car + 'a)>

当您尝试返回

&mut (dyn Car + 'static)
时,这会导致生命周期不匹配。 这在共享引用情况下有效,因为共享引用的生命周期可以隐式缩短,但独占引用何时发生这种情况的规则通常不允许这样做。

通过显式设置特征对象的生命周期,可以轻松解决这种情况下的问题

'static

fn get_mut(&mut self, id: usize) -> Option<&mut (dyn Car + 'static)>
© www.soinside.com 2019 - 2024. All rights reserved.