使用包含借用参数的结构

时间:2017-03-31 21:59:28

标签: rust lifetime borrow-checker

我正在写一个简单的Rust游戏,其中包含一个Drawer,它构造一次然后作为可变参考传递给许多方法:

pub struct Drawer<'a> {
    // ...
    renderer: Renderer<'a>,
    // ...
}

fn pause(drawer: &mut Drawer, events: &[Event]) {
    // ...
    drawer.draw_text(&TextPos::Centered, "Paused", 1);
    // ...
}

我想重构我的代码,为绘制文本引入流畅的界面,例如:

drawer.text()
    .size(4)
    .centered()
    .draw("Paused");

我是通过创建TextDrawer结构来实现的,该结构包含对Drawer的引用:

pub struct TextDrawer<'a, 'b: 'a> {
    pos: TextPos,
    size: u32,
    drawer: &'a mut Drawer<'b>,
}

impl<'a> Drawer<'a> {
     pub fn text(&mut self) -> TextDrawer {
        TextDrawer {
            pos: TextPos::At(0, 0),
            size: 1,
            drawer: self,
        }
    }
}

我认为我在结构上的生命周期是正确的(引用必须与Drawer本身一样长。)

但是,在添加显式生存期之前,我的text方法不会编译。当我这样做时,每个调用text的方法都需要明确的生命周期,依此类推。我很惊讶这些生命周期必须说明:毕竟,它们都是fn foo<'a, 'b: 'a>(drawer: &mut'a Drawer<'b>)的形式。在此之前我曾假设这已经是推断的生命周期,因为引用始终需要与Drawer本身一样长。

我是否有必要将这些明确的生命周期放在我的方法签名上?或者我可以通过其他方式避免它吗?

1 个答案:

答案 0 :(得分:1)

感谢上面Lukas提出的minimal example,我意识到我只是向我的text方法提取了生命周期参数。

我的生命时间不正确:

impl<'a> Drawer<'a> {
    pub fn text<'b>(&'b mut self) -> TextDrawer<'a, 'b> {
        // omitted
    }
}

正确的生命周期:

impl<'a> Drawer<'a> {
    pub fn text<'b>(&'b mut self) -> TextDrawer<'b, 'a> {
        // omitted
    }
}

在此之后,一切都在没有任何明确的生命周期的情况下进行编译。