簡體   English   中英

“錯誤:關閉可能比當前功能更長”但它不會比它活得更久

[英]“error: closure may outlive the current function” but it will not outlive it

當我嘗試編譯以下代碼時:

fn main() {

    (...)

    let mut should_end = false;

    let mut input = Input::new(ctx);

    input.add_handler(Box::new(|evt| {
        match evt {
            &Event::Quit{..} => {
                should_end = true;
            }
            _ => {}
        }
    }));

    while !should_end {
        input.handle();
    }
}

pub struct Input {
    handlers: Vec<Box<FnMut(i32)>>,
}

impl Input {
    pub fn new() -> Self {
        Input {handlers: Vec::new()}
    }
    pub fn handle(&mut self) {
        for a in vec![21,0,3,12,1] {
            for handler in &mut self.handlers {
                handler(a);
            }
        }
    }
    pub fn add_handler(&mut self, handler: Box<FnMut(i32)>) {
        self.handlers.push(handler);
    }
}

我收到此錯誤:

error: closure may outlive the current function, but it borrows `should_end`, which is owned by the current function

我不能簡單地將move添加到閉包中,因為我需要稍后在主循環中使用should_end 我的意思是,我可以,但由於boolCopy ,它只會影響閉包內的should_end ,因此程序會永遠循環。

據我所知,由於input是在main函數中創建的,並且閉包存儲在input ,因此它不可能比當前函數更長。 有沒有辦法向Rust表達封閉不會比main更長? 或者是否有可能我看不到關閉將比main更長? 在后一種情況下,它有一種方法可以強迫它只與main生活一樣長嗎?

我是否需要重構我處理輸入的方式,或者是否有某些方法可以使其工作。 如果我需要重構,我在哪里可以看到Rust的一個很好的例子?

是一個簡化版的圍欄 我可能在其中犯了一個可能導致瀏覽器崩潰的錯誤。 我碰巧遇到過一次,所以,要小心。

如果需要, 的其余代碼可用 所有相關信息都應該在main.rsinput.rs

問題不是你的閉包,而是add_handler方法。 完全展開它看起來像這樣:

fn add_handler<'a>(&'a mut self, handler: Box<FnMut(i32) + 'static>)

正如您所看到的,特征對象上存在一個隱式的'static綁定”。 顯然我們不希望這樣,所以我們引入第二個生命周期'b

fn add_handler<'a, 'b: 'a>(&'a mut self, handler: Box<FnMut(i32) + 'b>)

由於您要將handler對象添加到Input::handlers字段,因此該字段不能超過handler對象的范圍。 因此,我們還需要限制其壽命:

pub struct Input<'a> {
    handlers: Vec<Box<FnMut(i32) + 'a>>,
}

這再次要求impl具有生命周期,我們可以在add_handler方法中使用它。

impl<'a> Input<'a> {
    ...
    pub fn add_handler(&mut self, handler: Box<FnMut(i32) + 'a>) {
        self.handlers.push(handler);
    }
}

現在剩下的就是使用Cell來控制對should_end標志的訪問。

以下是固定代碼的示例

use std::cell::Cell;

fn main() {
    let should_end = Cell::new(false);
    let mut input = Input::new();
    input.add_handler(Box::new(|a| {
        match a {
            1 => {
                should_end.set(true);
            }
            _ => {
                println!("{} {}", a, should_end.get())
            }
        }
    }));
    let mut fail_safe = 0;
    while !should_end.get() {
        if fail_safe > 20 {break;}
        input.handle();
        fail_safe += 1;
    }
}

pub struct Input<'a> {
    handlers: Vec<Box<FnMut(i32) + 'a>>,
}

impl<'a> Input<'a> {
    pub fn new() -> Self {
        Input {handlers: Vec::new()}
    }
    pub fn handle(&mut self) {
        for a in vec![21,0,3,12,1,2] {// it will print the 2, but it won't loop again
            for handler in &mut self.handlers {
                handler(a);
            }
        }
    }
    pub fn add_handler(&mut self, handler: Box<FnMut(i32) + 'a>) {
        self.handlers.push(handler);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM