rust - "the immutable borrow prevents mutable borrows"当使用 rust-sdl2 抽取事件时

标签 rust

学习了一段时间的Rust,我开始以为我理解了它的所有权/借用机制,但是接下来的例子让我真的很疑惑。我在玩 rust-sdl2 :

extern crate sdl2;

use sdl2::Sdl;
use sdl2::event::Event;
use sdl2::render::Renderer;

struct SdlDriver<'a> {
    sdl_ctx  : Sdl,
    renderer : Renderer<'a>
}

impl<'a> SdlDriver<'a> {
    fn event_pump(&self) -> sdl2::event::EventPump {
        self.sdl_ctx.event_pump()
    }

    fn draw_rect(&mut self, x: i32, y: i32) {
        let mut drawer = self.renderer.drawer();
        drawer.draw_rect(sdl2::rect::Rect::new(x-20, y-20, 40, 40));
        drawer.present();
    }

    fn event_loop(&mut self) {
        let mut event_pump = self.event_pump();

        loop {
            let event = event_pump.wait_event();

            match event {
                Event::Quit {..} => { break },
                Event::MouseMotion { x, y, .. } => { 
                    self.draw_rect(x, y);
                },
                _ => ()
            }
        }
    }
}

fn main() {
}

编译器显示错误:

main.rs:32:25: 32:29 error: cannot borrow `*self` as mutable because it is also borrowed as immutable
main.rs:32                         self.draw_rect(x, y);
                                   ^~~~
main.rs:24:34: 24:38 note: previous borrow of `*self` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `*self` until the borrow ends
main.rs:24             let mut event_pump = self.event_pump();
                                            ^~~~
main.rs:37:10: 37:10 note: previous borrow ends here
main.rs:23         fn event_loop(&mut self) {
...
main.rs:37         }
                   ^

据我了解,对self.event_pump()的调用应该暂时借用*self,返回现在拥有的EventPump结构通过event_loop(),然后释放*self。但看起来 *selfevent_pump 的整个生命周期中都是借用的。为什么?

为了比较,当我调用方法而不返回结果时,比如

self.draw_rect(x, y);
self.draw_rect(x, y);

一切正常,*self 在每次调用后立即释放。

还有一个我不明白的是为什么*self是借来的(带星号)? event_loop(&mut self) 已经从它的调用者那里借用了self,为什么还要在这里借用*self

应该如何重写上面的示例以满足 Rust 的借用检查器?

最佳答案

the call to self.event_pump should temporarily borrow *self

是的

then return EventPump struct which is now owned by event_loop and release *self

没有。这是你的方法:

fn event_pump(&self) -> sdl2::event::EventPump {
    self.sdl_ctx.event_pump()
}

在生命周期省略之前,它看起来像:

fn event_pump<'a>(&'a self) -> sdl2::event::EventPump<'a> {
    self.sdl_ctx.event_pump()
}

EventPump 结构 looks like :

pub struct EventPump<'sdl> {
    _sdl:    PhantomData<&'sdl ()>,

    // Prevents the event pump from moving to other threads.
    // SDL events can only be pumped on the main thread.
    _nosend: PhantomData<*mut ()>
}

当你借用self.sdl_ctx时,你也在借用self。借用检查器在 函数内进行细粒度检查,但不会 函数调用。即使在技术上可行,跨调用检查也会非常昂贵。

解决此问题的一种方法是直接调用成员变量上的方法 - 而不是创建您自己的 event_pump 方法,只需将其内联即可。这通常会导致创建更细粒度的结构。

关于rust - "the immutable borrow prevents mutable borrows"当使用 rust-sdl2 抽取事件时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29987374/

相关文章:

rust - 为什么使用 rustc 命令构建看不到 crate?

rust - 无法读取通过 hyper::client::Client 发出 HTTP 请求的简单负载:不满足特征绑定(bind) `Body: Future`

generics - 是否可以从函数中返回具有随机类型的泛型结构

multithreading - 多线程应用程序无法使用错误链进行编译

arrays - 如何在 Rust 中创建并传递以空字符结尾的 C 字符串数组 (char**)?

rust - 共享状态的生命周期

string - 查找连续相等字符的最长子串时出现 "borrowed value does not live long enough"错误如何处理?

rust - 如何使用 serde 从 XML 属性反序列化数字?

shell - 如何接受文字 "*"作为命令行参数?

rust - 如何切片具有 i32 限制的数组?