首页 > 解决方案 > 代码无需借用即可工作,但我无法使其与借用一起工作

问题描述

我有一些代码并且它可以工作,但是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
    }
}

游乐场

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

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

游乐场

有没有办法让这段代码工作?

标签: rust

解决方案


问题是你借用了函数中obj1可变的对象,直到函数结束。split_text'amain

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));
    }
}

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


推荐阅读