在闭包中使用 split_at_mut 的 Rust 错误 E0495
Rust error E0495 using split_at_mut in a closure
我遇到了一个 "error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements" 的简单函数:
fn assign_split_at_mut<'a, 'b, T>(s: &'b mut &'a mut [T], mid: usize) -> &'a mut [T] {
let (x, y) = (*s: &'a mut [T]).split_at_mut(mid);
*s = y;
x
}
我写了一个 playpen example,其中包含 split_at_mut
的这个 unsafe
变体,它确实有效。
fn assign_split_at_mut_unsafe<'a, T>(s: &mut &'a mut [T], mid: usize) -> &'a mut [T] {
let len = (*s: &'a mut [T]).len();
let ptr = (*s: &'a mut [T]).as_mut_ptr();
unsafe {
use std::slice::from_raw_parts_mut;
assert!(mid <= len);
*s: &'a mut [T] = from_raw_parts_mut(ptr.offset(mid as isize), len - mid);
from_raw_parts_mut(ptr, mid)
}
}
其实我想大致这样写:
pub fn slice_header<'a>(&'static self, mut header: &'a mut [u8])
-> MyResult<HeaderRefs<'a>>
{
// ...
let take = |l: usize| -> &'a mut [u8] {
let (x,y) = header.split_at_mut(l);
header = y; x
};
let hr = HeaderRefs {
params: self,
alpha: array_mut_ref![take(32),0,32],
gamma: array_mut_ref![take(16),32,16],
beta: take(self.beta_length as usize),
surb_log: take(self.surblog_length as usize),
surb: take(self.surb_length()),
};
// ...
Ok(hr)
}
我相信如果我简单地写出一堆就可以了
let (alpha,header) = header.split_at_mut(32);
let (gamma,header) = header.split_at_mut(16);
// ...
如果我将它们放入一个数组中,也许它会起作用。我无法让它与闭包一起使用,这看起来会更干净。
一位 IRC 用户 nox 通过使用 mem::replace
将需要突变的 &mut [T]
首先移开,提供了一个清晰的答案:
fn reserve<'heap, T>(heap: &mut &'heap mut [T], len: usize) -> &'heap mut [T] {
let tmp: &'heap mut [T] = ::std::mem::replace(&mut *heap, &mut []);
let (reserved, tmp) = tmp.split_at_mut(len);
*heap = tmp;
reserved
}
这是一个借用问题:
fn assign_split_at_mut<'a, 'b, T>(s: &'b mut &'a mut [T], mid: usize) -> &'a mut [T] {
let (x, y) = (*s: &'a mut [T]).split_at_mut(mid);
*s = y;
x
}
具体来说,split_at_mut
借用了 s
,所以当 s
被借用时,您不能 也 分配给 s
。
为了理解这个问题,假设我们在这里讨论向量,s: &mut Vec<T>
:你可以先从 Vec
中借用一个切片,然后使用 s
来改变它.
这就是为什么 Rust 指定 整个访问路径 被借用,而不仅仅是叶子。
好的,那现在呢?
如@nox所述,解决方案是"dance":
- 将
&'a mut [T]
的所有权从 s
移至局部变量
- 借用这个局部变量
- 分配给
s
这样,借用检查器就安心了,因为它知道修改 s
不会影响局部变量及其借用。
有多种方法可以根据情况将所有权移出&mut X
,一些常见的方法是:
std::mem::replace
,
std::mem::swap
,
Option::take
如果 X
是 Option
,
- ...
在您的情况下,replace
更简单。 @nox 提供的解决方案非常简单:
fn reserve<'heap, T>(heap: &mut &'heap mut [T], len: usize) -> &'heap mut [T] {
let tmp: &'heap mut [T] = ::std::mem::replace(&mut *heap, &mut []);
let (reserved, tmp) = tmp.split_at_mut(len);
*heap = tmp;
reserved
}
我遇到了一个 "error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements" 的简单函数:
fn assign_split_at_mut<'a, 'b, T>(s: &'b mut &'a mut [T], mid: usize) -> &'a mut [T] {
let (x, y) = (*s: &'a mut [T]).split_at_mut(mid);
*s = y;
x
}
我写了一个 playpen example,其中包含 split_at_mut
的这个 unsafe
变体,它确实有效。
fn assign_split_at_mut_unsafe<'a, T>(s: &mut &'a mut [T], mid: usize) -> &'a mut [T] {
let len = (*s: &'a mut [T]).len();
let ptr = (*s: &'a mut [T]).as_mut_ptr();
unsafe {
use std::slice::from_raw_parts_mut;
assert!(mid <= len);
*s: &'a mut [T] = from_raw_parts_mut(ptr.offset(mid as isize), len - mid);
from_raw_parts_mut(ptr, mid)
}
}
其实我想大致这样写:
pub fn slice_header<'a>(&'static self, mut header: &'a mut [u8])
-> MyResult<HeaderRefs<'a>>
{
// ...
let take = |l: usize| -> &'a mut [u8] {
let (x,y) = header.split_at_mut(l);
header = y; x
};
let hr = HeaderRefs {
params: self,
alpha: array_mut_ref![take(32),0,32],
gamma: array_mut_ref![take(16),32,16],
beta: take(self.beta_length as usize),
surb_log: take(self.surblog_length as usize),
surb: take(self.surb_length()),
};
// ...
Ok(hr)
}
我相信如果我简单地写出一堆就可以了
let (alpha,header) = header.split_at_mut(32);
let (gamma,header) = header.split_at_mut(16);
// ...
如果我将它们放入一个数组中,也许它会起作用。我无法让它与闭包一起使用,这看起来会更干净。
一位 IRC 用户 nox 通过使用 mem::replace
将需要突变的 &mut [T]
首先移开,提供了一个清晰的答案:
fn reserve<'heap, T>(heap: &mut &'heap mut [T], len: usize) -> &'heap mut [T] {
let tmp: &'heap mut [T] = ::std::mem::replace(&mut *heap, &mut []);
let (reserved, tmp) = tmp.split_at_mut(len);
*heap = tmp;
reserved
}
这是一个借用问题:
fn assign_split_at_mut<'a, 'b, T>(s: &'b mut &'a mut [T], mid: usize) -> &'a mut [T] {
let (x, y) = (*s: &'a mut [T]).split_at_mut(mid);
*s = y;
x
}
具体来说,split_at_mut
借用了 s
,所以当 s
被借用时,您不能 也 分配给 s
。
为了理解这个问题,假设我们在这里讨论向量,s: &mut Vec<T>
:你可以先从 Vec
中借用一个切片,然后使用 s
来改变它.
这就是为什么 Rust 指定 整个访问路径 被借用,而不仅仅是叶子。
好的,那现在呢?
如@nox所述,解决方案是"dance":
- 将
&'a mut [T]
的所有权从s
移至局部变量 - 借用这个局部变量
- 分配给
s
这样,借用检查器就安心了,因为它知道修改 s
不会影响局部变量及其借用。
有多种方法可以根据情况将所有权移出&mut X
,一些常见的方法是:
std::mem::replace
,std::mem::swap
,Option::take
如果X
是Option
,- ...
在您的情况下,replace
更简单。 @nox 提供的解决方案非常简单:
fn reserve<'heap, T>(heap: &mut &'heap mut [T], len: usize) -> &'heap mut [T] {
let tmp: &'heap mut [T] = ::std::mem::replace(&mut *heap, &mut []);
let (reserved, tmp) = tmp.split_at_mut(len);
*heap = tmp;
reserved
}