我有一个函数take_head
,它有两个参数:一个切片,以及切片“head”中的项目数(“head”是第一个n
项,而“尾巴”就是头后的一切。它将切片分为两部分:它返回的head
和设置参数的tail
。这是显示如何使用的main
函数:
fn main() {
let mut strings = &mut ["a", "b", "c"][..];
println!("original: {:?}", strings);
// head should ["a"], and strings should be set to the tail (["b", "c"]).
let head = take_head(&mut strings, 1);
println!("head: {:?}", head); // Should print ["a"].
println!("tail: {:?}", strings); // Should print ["b", "c"].
}
如果我这样实施take_head
:
fn take_head<'a>(strings: &mut &'a mut [&'a str], n: usize) -> &'a mut [&'a str] {
let value = std::mem::replace(strings, &mut []);
let (head, tail) = value.split_at_mut(n);
*strings = tail;
println!("returning head: {:?}", head);
head
}
original: ["a", "b", "c"] returning head: ["a"] head: ["a"] tail: ["b", "c"]
但是,如果我像这样实施take_head
:
// Make a convenient trait for slices.
pub trait TakeFrontMut<T> {
fn take_front_mut(&mut self, n: usize) -> &mut [T];
}
impl<'a, T> TakeFrontMut <T> for &'a mut [T] {
fn take_front_mut(&mut self, n: usize) -> &mut [T] {
// It's the same code as before, just in a trait method.
let value = std::mem::replace(self, &mut []);
let (head, tail) = value.split_at_mut(n);
*self = tail;
return head;
}
}
fn take_head<'a>(strings: &mut &'a mut [&'a str], n: usize) -> &'a mut [&'a str] {
let head = strings.take_front_mut(n);
println!("returning head: {:?}", head);
head
}
<anon>:15:24: 15:41 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495] <anon>:15 let head = strings.take_front_mut(n); ^~~~~~~~~~~~~~~~~ <anon>:14:1: 18:2 help: consider using an explicit lifetime parameter as shown: fn take_head<'a>(strings: &'a mut &'a mut [&'a str], n: usize) -> &'a mut [&'a str] <anon>:14 fn take_head<'a>(strings: &mut &'a mut [&'a str], n: usize) -> &'a mut [&'a str] { <anon>:15 let head = strings.take_front_mut(n); <anon>:16 println!("returning head: {:?}", head); <anon>:17 head <anon>:18 }
问题:为什么第二个版本会产生错误?解析器无法确定合适的生命周期有什么不同?我不明白为什么会失败,我不确定这些相互矛盾的要求是什么。
是的,take_head
函数是愚蠢的,但它是我能做的最简单的MVCE,它仍能捕获与我的真实代码相同的问题。
答案 0 :(得分:3)
take_front_mut
的签名未指定返回值的正确生命周期。它应该是&'a mut [T]
,因为这是您分割的切片的生命周期。这也要求你对特质本身进行改变。
pub trait TakeFrontMut<'a, T> {
fn take_front_mut(&mut self, n: usize) -> &'a mut [T];
}
impl<'a, T> TakeFrontMut<'a, T> for &'a mut [T] {
fn take_front_mut(&mut self, n: usize) -> &'a mut [T] {
let value = std::mem::replace(self, &mut []);
let (head, tail) = value.split_at_mut(n);
*self = tail;
return head;
}
}