代码可以不借用而工作,但是我不能借用它

时间:2019-04-10 07:35:42

标签: rust

我有一些代码并且可以正常工作,但是AFAIK借用是专门为避免像在split_text方法中那样手动将同一个对象传入和传出方法

fn main() {
    println!("Hello, world!");
    let mut test = String::from("12345");
    let mut obj1 = Object {
        text: test.as_mut_str(),
        next: None,
    };
    for i in 0..5 {
        obj1 = obj1.split_text(4 - i);
        if let Some(obj) = obj1.next.as_ref() {
            println!("{}", obj.text);
        }
    }
}

struct Object<'a> {
    text: &'a mut str,
    next: Option<Box<Object<'a>>>,
}

impl<'a> Object<'a> {
    fn split_text(mut self, count: usize) -> Self {
        let tmp = self.text;
        let (part1, part2) = tmp.split_at_mut(count);
        self.text = part1;
        let obj2 = Object {
            text: part2,
            next: None,
        };
        self.next = Some(Box::new(obj2));
        self
    }
}

Playground

但是我不知道如何通过借阅检查器

impl<'a> Object<'a> {
    fn split_text(&'a mut self, count: usize) {
        let tmp = &mut self.text;
        let (part1, part2) = tmp.split_at_mut(count);
        self.text = part1;
        let obj2 = Object {
            text: part2,
            next: None,
        };
        self.next = Some(Box::new(obj2));
    }
}

导致错误

error[E0499]: cannot borrow `obj1` as mutable more than once at a time
  --> src/main.rs:11:9
   |
11 |         obj1.split_text(4 - i);
   |         ^^^^ mutable borrow starts here in previous iteration of loop

error[E0502]: cannot borrow `obj1.next` as immutable because it is also borrowed as mutable
  --> src/main.rs:12:28
   |
11 |         obj1.split_text(4 - i);
   |         ---- mutable borrow occurs here
12 |         if let Some(obj) = obj1.next.as_ref() {
   |                            ^^^^^^^^^
   |                            |
   |                            immutable borrow occurs here
   |                            mutable borrow later used here

error[E0506]: cannot assign to `self.text` because it is borrowed
  --> src/main.rs:27:9
   |
23 | impl <'a> Object<'a> {
   |       -- lifetime `'a` defined here
24 |     fn split_text(&'a mut self, count:usize) {
25 |         let tmp = &mut self.text;
   |                   -------------- borrow of `self.text` occurs here
26 |         let (part1, part2) = tmp.split_at_mut(count);
   |                              ----------------------- argument requires that `self.text` is borrowed for `'a`
27 |         self.text = part1;
   |         ^^^^^^^^^^^^^^^^^ assignment to borrowed `self.text` occurs here

Playground

有没有办法使此代码正常工作?

1 个答案:

答案 0 :(得分:1)

问题是,您要借用obj1函数中可变的对象split_text,期限为'a,直到main函数结束。

fn main() {
    println!("Hello, world!");
    let mut test = String::from("12345");
    let mut obj1 = Object {                             // 'a start
        text: test.as_mut_str(),
        next: None,
    };
    for i in 0..5 {
        obj1 = obj1.split_text(4 - i);                  // borrow for 'a lifetime,
                                                        // Won't work in next iteration
        if let Some(obj) = obj1.next.as_ref() {         // Won't work
            println!("{}", obj.text);
        }
    }
}                                                       // 'a end

您只想为split_text函数可变地借用它,即在不同的(较小的)生存期中使用-您可以忽略或指定不同的生存期(例如'b

struct Object<'a> {
    text: &'a str, // no need of mutable slice here
    next: Option<Box<Object<'a>>>,
}

impl<'a> Object<'a> {
    fn split_text(&mut self, count: usize) { // No lifetime required here
        let (part1, part2) = self.text.split_at(count); // no need of temp var and mutable split here
        self.text = part1;
        let obj2 = Object {
            text: part2,
            next: None,
        };
        self.next = Some(Box::new(obj2));
    }
}

明确不同的生命周期版本(仅出于完整性考虑):

impl<'a> Object<'a> {
    fn split_text<'b>(&'b mut self, count: usize) {
        let tmp = &mut self.text;
        let (part1, part2) = tmp.split_at(count);
        self.text = part1;
        let obj2 = Object {
            text: part2,
            next: None,
        };
        self.next = Some(Box::new(obj2));
    }
}

此外,仅在需要时才使某些内容可变。我更改了可变切片并拆分为正常。