在我期望可变借用结束之后,我遇到了关于同时使用可变和不可变借用的令人困惑的错误。我对类似问题(1 , 2 , 3 , 4 , 5)进行了大量研究,这让我相信我的问题与词法生命周期有关(尽管打开 NLL 功能并每晚编译并没有) t 改变结果),我只是不知道是什么;我的情况似乎不适合其他问题的任何场景。
pub enum Chain<'a> {
Root {
value: String,
},
Child {
parent: &'a mut Chain<'a>,
},
}
impl Chain<'_> {
pub fn get(&self) -> &String {
match self {
Chain::Root { ref value } => value,
Chain::Child { ref parent } => parent.get(),
}
}
pub fn get_mut(&mut self) -> &mut String {
match self {
Chain::Root { ref mut value } => …Run Code Online (Sandbox Code Playgroud) 我的印象是可变引用(即&mut T)总是被移动.这是完全合理的,因为它们允许独占的可变访问.在下面的代码中,我为另一个可变引用分配了一个可变引用,并移动了原始引用.结果我不能再使用原件了:
let mut value = 900;
let r_original = &mut value;
let r_new = r_original;
*r_original; // error: use of moved value *r_original
Run Code Online (Sandbox Code Playgroud)
如果我有这样的功能:
fn make_move(_: &mut i32) {
}
Run Code Online (Sandbox Code Playgroud)
并修改我的原始示例,如下所示:
let mut value = 900;
let r_original = &mut value;
make_move(r_original);
*r_original; // no complain
Run Code Online (Sandbox Code Playgroud)
我期望r_original在make_move用它调用函数时移动可变引用.然而,这不会发生.我仍然可以在通话后使用参考.
如果我使用通用函数make_move_gen:
fn make_move_gen<T>(_: T) {
}
Run Code Online (Sandbox Code Playgroud)
并称之为:
let mut value = 900;
let r_original = &mut value;
make_move_gen(r_original);
*r_original; // error: use of moved …Run Code Online (Sandbox Code Playgroud) 假设我有一个带有引用的结构,另一个带有该结构引用的结构,如下所示:
struct Image<'a> {
pixel_data: &'a mut Vec<u8>,
size: (i32, i32),
}
struct SubImage<'a> {
image: &'a mut Image<'a>,
offset: (i32, i32),
size: (i32, i32),
}
Run Code Online (Sandbox Code Playgroud)
结构具有几乎相同的接口,不同之处在于SubImage在转发到所包含的Image引用的相应功能之前基于其偏移调整位置参数.我希望这些结构大多可以互换,但我似乎无法弄清楚如何让生命正确.最初,我只是在使用Image,并且可以简单地传递对象,而不会使用终身说明符:
fn main() {
let mut pixel_data: Vec<u8> = Vec::new();
let mut image = Image::new(&mut pixel_data, (1280, 720));
render(&mut image);
}
fn render(image: &mut Image) {
image.rect_fill(0, 0, 10, 10);
}
Run Code Online (Sandbox Code Playgroud)
然后我创建了SubImage,并希望做这样的事情:
fn render2(image: &mut Image) {
let mut sub = SubImage {
image: image, // …Run Code Online (Sandbox Code Playgroud) 参数可以传递给函数并修改:
fn set_42(int: &mut i32) {
*int += 42;
}
fn main() {
let mut int = 0;
set_42(&mut int);
println!("{:?}", int);
}
Run Code Online (Sandbox Code Playgroud)
输出:
42
Run Code Online (Sandbox Code Playgroud)
天真地改变代码以使用切片失败了一大堆错误:
fn pop_front(slice: &mut [i32]) {
*slice = &{slice}[1..];
}
fn main() {
let mut slice = &[0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
Run Code Online (Sandbox Code Playgroud)
输出:
<anon>:2:14: 2:27 error: mismatched types:
expected `[i32]`,
found `&[i32]`
(expected slice,
found &-ptr) [E0308]
<anon>:2 *slice = &{slice}[1..];
^~~~~~~~~~~~~
<anon>:2:14: 2:27 help: see the detailed explanation …Run Code Online (Sandbox Code Playgroud) 我想编写以下函数:
fn foo<'a, 'b, 'c>(rr1: &'a mut &'c mut u32, rr2: &'b mut &'c mut u32) {
*rr1 = *rr2;
}
Run Code Online (Sandbox Code Playgroud)
但是编译器抱怨:
fn foo<'a, 'b, 'c>(rr1: &'a mut &'c mut u32, rr2: &'b mut &'c mut u32) {
*rr1 = *rr2;
}
Run Code Online (Sandbox Code Playgroud)
我对 Rust 生命周期的心智模型不同意代码是错误的。我读的类型rr2为“具有寿命的引用'b与寿命的参考'c到一个u32”。因此,当我提领rr2,我与寿命引用'c到u32。这应该可以安全地存储在*rr1具有相同类型的 中。
如果我需要它的'b寿命'c,它的工作原理:
fn foo<'a, 'b: 'c, 'c>(rr1: &'a mut &'c mut u32, rr2: &'b mut …Run Code Online (Sandbox Code Playgroud) 我有一个参考struct Foo<'a>包装&'a str.我想HashMap用Foos作为键来填充.这是一段代码(在操场上打开):
use std::collections::HashMap;
#[derive(PartialEq, Eq, Hash)]
struct Foo<'a> {
txt: &'a str,
}
fn main() {
let a = "hello".to_string();
let a2 = Foo { txt: &a };
let b = "hello".to_string();
let b2 = Foo { txt: &b };
let mut hm = HashMap::<Foo, u32>::new();
hm.insert(a2, 42);
println!("=== {:?}", hm.get(&b2)); // prints Some(42)
println!("=== {:?}", hm.get_mut(&b2)); // prints Some(42)
{
let c = "hello".to_string();
let c2 = …Run Code Online (Sandbox Code Playgroud) 在阅读Nomicon的子类型章节之后,我就无法将类型参数的协方差包住。特别是对于Box<T>类型,它被描述为:T is covariant。
但是,如果我编写此代码:
trait A {}
trait B: A {}
struct C;
impl A for C {}
impl B for C {}
fn foo(v: Box<A>) {}
fn main() {
let c = C;
let b: Box<B> = Box::new(c);
foo(b);
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
trait A {}
trait B: A {}
struct C;
impl A for C {}
impl B for C {}
fn foo(v: Box<A>) {}
fn main() {
let c = C; …Run Code Online (Sandbox Code Playgroud) 在尝试重构运行良好的 Rust 应用程序时,我尝试将循环的内容分离到一个新函数中。然而,在这个新重构的函数中,我需要传递一个必须可变的参数,并通过引用传递。突然之间,绝对内联工作的代码仅仅因为可变的引用传递而崩溃了。
我的问题是:有人可以解释一下为什么这样的“简单”更改不起作用吗?(即重构出原本未更改的代码的新函数)
我有一个关于该问题的最小演示,以及下面的一些工作比较。这是该代码的错误:
error[E0499]: cannot borrow `str_to_int` as mutable more than once at a time
--> src/main.rs:30:22
|
30 | get_key(key, &mut str_to_int);
| ^^^^^^^^^^^^^^^ `str_to_int` was mutably borrowed here in the previous iteration of the loop
Run Code Online (Sandbox Code Playgroud)
示例代码:
use std::collections::BTreeMap;
fn get_int (
key: u32,
values: &mut BTreeMap<u32, u32>,
) -> &u32 {
values.entry(key).or_insert_with(|| { 1 })
}
fn get_key<'a> (
key: &'a str,
values: &'a mut BTreeMap<&'a str, u32>,
) -> &'a u32 {
values.entry(key).or_insert_with(|| { 1 …Run Code Online (Sandbox Code Playgroud)