如何编译以下Rust代码?

时间:2015-07-18 14:18:11

标签: compiler-errors rust

我是Rust编程语言的新手,我只是在玩它。我读到了Rust借用的东西,我想我理解为什么编译器不接受以下代码,但我不知道如何正确使用它:

struct Pixel;

struct Canvas {
    pixel : Pixel,
}

impl Canvas {
    fn drawPixel(&mut self, y : usize, x : usize, pixel : &Pixel) {
        // Modify internal pixmap using given Pixel description.
    }

    fn setPixel(&mut self, y : usize, x : usize) {
        // Draw a pixel to internal pixmap using own pixel description.
        self.drawPixel(y, x, &self.pixel);
    }
}

这是编译器报告的错误:

src/main.rs:14:35: 14:45 error: cannot borrow `self.pixel` as immutable because `*self` is also borrowed as mutable
src/main.rs:14             self.drawPixel(y, x, &self.pixel);
                                                 ^~~~~~~~~~
src/main.rs:14:13: 14:17 note: previous borrow of `*self` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `*self` until the borrow ends
src/main.rs:14             self.drawPixel(y, x, &self.pixel);
                           ^~~~
src/main.rs:14:46: 14:46 note: previous borrow ends here
src/main.rs:14             self.drawPixel(y, x, &self.pixel);

这个例子中的想法是有一个方法' drawPixel'可以根据指定的“像素”绘制像素。第二种方法' setPixel'只是转发到前一种方法,通过它来引用“像素”'与“画布”相关的实例'对象

请不要问我为什么要这样做。它是我真实用例的简化版本。而且我真的想知道如何编译这段代码。

2 个答案:

答案 0 :(得分:3)

根本问题是drawPixel中对setPixel的调用会为drawPixel字段提供pixel两个别名:可变的self字段(如self.pixel},以及pixel参数中的不可变参数。在Rust中,非mut指针确实是指向不可变值的指针。但是,使用这两个别名,drawPixel将能够改变pixel参数引用的像素值,并且其值将意外更改。

如果Pixel是小型(例如,RGBA四元组)并且未实现Drop,则可以将其设为Copy,然后只传递Pixel按值(见A.B.'s answer)。

如果那是不可能的,那么考虑drawPixel实际需要变异的内容。是否需要改变pixel字段?如果是,您需要以某种方式复制像素,否则当您改变字段时pixel参数的值将会改变,如上所述。在这种情况下,您可能只能实现Clone并使用clone()方法获取像素的副本。

如果您不需要改变pixel中的drawPixel字段,那么您可以在单独的结构中移动您变异的字段,并将drawPixel方法移动到该字段结构改为。这样,&mut self将应用于内部结构,它肯定不会与pixel字段别名。

struct Pixel;

struct Canvas2;

struct Canvas {
    canvas2 : Canvas2,
    pixel : Pixel,
}

impl Canvas2 {
    fn drawPixel(&mut self, y : usize, x : usize, pixel : &Pixel) {
        // Modify internal pixmap using given Pixel description.
    }
}

impl Canvas {
    fn setPixel(&mut self, y : usize, x : usize) {
        // Draw a pixel to internal pixmap using own pixel description.
        self.canvas2.drawPixel(y, x, &self.pixel);
    }
}

答案 1 :(得分:2)

如何正确使用取决于您需要什么以及Pixel在实际代码中的实际外观。

由于Pixel可能是一个可以轻易复制的轻量级对象,因此您可以按值传递它。

#[derive(Copy, Clone)]
struct Pixel;

struct Canvas {
    pixel : Pixel,
}

impl Canvas {
    fn drawPixel(&mut self, y : usize, x : usize, pixel : Pixel) {
        // Modify internal pixmap using given Pixel description.
    }

    fn setPixel(&mut self, y : usize, x : usize) {
        // Draw a pixel to internal pixmap using own pixel description.
        self.drawPixel(y, x, self.pixel);
    }
}