Error: lifetime may not live long enough error

i'm trying to share &mut self with the loop and tx closure at the same time and i occurred a "error: lifetime may not live long enough" error

pub fn run(&mut self) {
        // Initialize
        utils::hide_cursor();
        crossterm::terminal::enable_raw_mode().unwrap();
        utils::clear();

        let app = Arc::new(Mutex::new(self));
        let app_thread = Arc::clone(&app);
        let tx = &move |command: Command| match command {
            Command::Render(tick) => {
                let mut data = app_thread.lock().unwrap();
                data.render(tick);
                drop(data);
            }
            Command::Exit => {
                crossterm::terminal::disable_raw_mode().unwrap();
                utils::clear();
                utils::show_cursor();
            } // Ect (more commands later)
        };

        tx(Command::Render(0));

        loop {
            {
                let mut data = app.lock().unwrap();
                data.element.update(tx, key::read_key());
            }
            tx(Command::Render(0));
        }
    }
error: lifetime may not live long enough
  --> src/lib.rs:98:37
   |
72 |     pub fn run(&mut self) {
   |                - let's call the lifetime of this reference `'1`
...
98 |                 data.element.update(tx, key::read_key());
   |                                     ^^ cast requires that `'1` must outlive `'static`

normal thread needs 'static, if you want to pass data with a lifetime between threads, you must use the scoped threads API.

I don't how your app works, but guessing from the compile error message, it seems this data.element.update() call requires 'static for its argument, probably sending data to different threads. if you cannot rewrite the threading code using the scoped API, then you cannot send a borrowed self to other threads. but it might be possible if you can rewrite this run() method to take a Arc<Self> as the receiver argument self.

side note: even if you managed to send an Arc<&mut Self> to different thread, it probably won't work as you expected, because it would downgrade to a shared reference (i.e. not mut anymore). so you really should re-think your app's architecture, not to fight the borrow check (and the type system as a whole).

yeah, if you want to have a value shared and mutated by multiple threads, you usually either want to stick it in an Arc<Mutex<T>>, or just an Arc, and wrap the indivitual fields in mutexes.

or use channels and message passing.

Yes. Can you show us the signature of this update() function? @kleo-dev

yeah sure:

pub trait Element: std::fmt::Debug + Send + dyn_clone::DynClone {
      fn update(&mut self, _tx: &Tx, _k: crate::key::Key) -> UpdateResponse {
              UpdateResponse::None
      }
}

here is the whole app struct which is for rendering the elements and updating them via keypress:

#[derive(Clone)]
pub struct App {
    element: Box<dyn Element>,
}

impl App {
    /// Creates a new screen to render components
    pub fn new() -> App {
        App {
            element: ui::text(),
        }
    }

    /// Creates a new screen to render components with a pre-existing component
    pub fn from(elem: Box<dyn Element>) -> App {
        let mut app = App::new();
        app.set_component(elem);
        app
    }

    /// Sets a component
    pub fn set_component(&mut self, element: Box<dyn Element>) {
        let (width, height) = crossterm::terminal::size().unwrap();
        self.element = element;
        let mut data = self.element.get_data();
        data.style.is_active = true;
        if data.width == 0 {
            data.width = width as usize;
        }
        if data.height == 0 {
            data.height = height as usize;
        }
        self.element.set_data(data);
    }

    /// Render to the screen
    fn render(&mut self, tick: usize) {
        let (width, height) = crossterm::terminal::size().unwrap();
        let mut data = self.element.get_data();
        if data.width == 0 {
            data.width = width as usize;
        }
        if data.height == 0 {
            data.height = height as usize;
        }
        self.element.set_data(data);
        let mut frame: Vec<String> = create_frame!(width as usize, height as usize);
        utils::render_to_frame(tick, &mut frame, &self.element);
        utils::clear();
        print!("{}", frame.join(""));
        utils::flush();
        let mut data = self.element.get_data();
        if data.width == width as usize {
            data.width = 0;
        }
        if data.height == height as usize {
            data.height = 0;
        }
        self.element.set_data(data);
    }

    /// Run the screen
    pub fn run(&mut self) {
        // Initialize
        utils::hide_cursor();
        crossterm::terminal::enable_raw_mode().unwrap();
        utils::clear();

        let app = Arc::new(Mutex::new(self));
        let app_thread = Arc::clone(&app);
        let tx = &move |command: Command| match command {
            Command::Render(tick) => {
                let mut data = app_thread.lock().unwrap();
                data.render(tick);
                drop(data);
            }
            Command::Exit => {
                crossterm::terminal::disable_raw_mode().unwrap();
                utils::clear();
                utils::show_cursor();
            } // Ect (more commands later)
        };

        tx(Command::Render(0));

        loop {
            {
                let mut data = app.lock().unwrap();
                data.element.update(tx, key::read_key());
            }
            tx(Command::Render(0));
        }
    }
}

update is only mean't to call tx with a Command enum:

pub enum Command {
    Render(usize),
    Exit,
    // will add more in the future
}

so it would look like this inside the update function: tx(Command::Exit)

also

pub type Tx = dyn Fn(Command);

i have fixed this issue, i added Command to UpdateResponse and made the match statement do the rest