代码如下所示,RefInner
有两个mut引用Inner
和Inner.a
,使用From
特征代码没有错误,但cp()
将显示cannot borrow
内部as mutable more than once at a time
。错误详细信息为:
error[E0499]: cannot borrow `inner` as mutable more than once at a time
--> src/main.rs:40:12
|
37 | let b: RefInner = RefInner {
| _______________________-
38 | | // b: a.geta().into(), //no error
39 | | b: cp(inner.geta()),
| | ------------ first mutable borrow occurs here
40 | | a: &mut inner,
| | ^^^^^^^^^^ second mutable borrow occurs here
41 | | };
| |_____- first borrow later used here
For more information about this error, try `rustc --explain E0499`.
warning: `hello` (bin "hello") generated 1 warning
error: could not compile `hello` due to previous error; 1 warning emitted
#[derive(Debug)]
pub struct Inner {
pub a: u64,
pub b: u64,
}
pub struct RefInner<'a> {
pub a: &'a mut Inner,
pub b: &'a mut ResponseContext,
}
impl Inner {
fn geta(&mut self) -> &mut u64 {
&mut self.a
}
}
#[repr(C)]
#[derive(Debug)]
pub struct ResponseContext {
seq_id: u8,
_ignore: [u8; 7],
}
impl From<&mut u64> for &mut ResponseContext {
fn from(value: &mut u64) -> Self {
unsafe { std::mem::transmute(value) }
}
}
fn cp(n: &mut u64) -> &mut ResponseContext {
unsafe { std::mem::transmute(n) }
}
fn main() {
let mut inner: Inner = Inner { a: 1, b: 2 };
let b: RefInner = RefInner {
// b: a.geta().into(), //no error
b: cp(inner.geta()), //cannot borrow `inner` as mutable more than once at a time
a: &mut inner,
};
}
- 有人能解释其中的区别吗**
2条答案
按热度按时间bqujaahr1#
在trait实现中使用lifetime省略号,输入和输出的生命周期是disjoint。
也就是说,在您情况下,它是
impl<'a, 'b> From<&'a mut u64> for &'b mut ResponseContext
。使用
transmute()
,您是在告诉编译器使用ignore it。对于具有一个输入和一个输出的函数,编译器分配相同的生存期.
基本上就是
如果执行
impl<'a> From<&'a mut u64> for &'a mut ResponseContext
,它的行为将类似于函数cp()
roejwanj2#
答案归结为省略规则。
当你有
impl From<&mut A> for &mut B
时,这个实现头被去糖化为impl<'from, 'to> From<&'from mut A> for &'to mut B
,也就是说,它允许将 any reference(不管多短)转换为 any reference(不管多长)。一般来说,这两个生命周期必须连接起来,因为否则方法体将无法编译,但是在这里你已经强制借用检查器接受了transmute
的这个通用实现。但是,当您使用
fn(&mut A) -> &mut B
时,它会以更具体的方式进行去糖处理-即,去糖处理为fn<'lt>(&'lt mut A) -> &'lt mut B
,即输入和输出的生命周期是相等的-因此,只要输出引用存在,原始可变引用就会被“锁定”,从而阻止任何其他使用。