Help with variable move

Trying building app with alcro as ui and rocket as backend.
In the ui trying to bind a button with exit command, so that both ui and server are closed upon the press of exit button, but stuck with move restrictions, any thought?

#![feature(decl_macro, proc_macro_hygiene)]

mod routes;

use rocket_contrib::serve::StaticFiles;
use rocket_contrib::templates::Template;
use std::sync::Arc;
use alcro::{UI, UIBuilder, Content, JSObject};
use std::thread::spawn;
use std::process::exit;

struct Chrome(Arc<UI>);  // to be used in rocket routes by 

fn main() {
    println!("Hello, world!");

    let ui = Arc::new(
        UIBuilder::new()
            .content(Content::Url("http://localhost:8000"))
            .size(1200, 800)
            .run()
    );
    
    ui.bind("exit", move |_| {  // ui value moved into closure
        println!("good bye");
        ui.close();   // ui variable moved due to use in closure
        exit(0);
        Ok(JSObject::Null)
    });

    rocket::ignite()
        .attach(Template::fairing())
        .mount("/static",
               StaticFiles::from(concat!(env!("CARGO_MANIFEST_DIR", "/static"))))
        .mount("/", rocket::routes![routes::root::root])
        .manage(Chrome(ui))   // ui value used here after move
        .launch();
}

Got the below error:

error[E0382]: borrow of moved value: `ui`
  --> src\main.rs:35:24
   |
16 |     let ui = Arc::new(
   |         -- move occurs because `ui` has type `std::sync::Arc<alcro::UI>`, which does not implement the `Copy` trait
...
23 |     ui.bind("exit", move |_| {  // ui value moved into closure
   |                     -------- value moved into closure here
24 |         println!("good bye");
25 |         ui.close();   // ui variable moved due to use in closure
   |         -- variable moved due to use in closure
...
35 |         .manage(Chrome(ui.clone()))   // ui value used here after move
   |                        ^^ value borrowed here after move

You must clone the Arc before moving it into the closure.

I made this:

    let ui_clone = ui.clone();
    ui_clone.bind("exit", move |_| {  
        println!("good bye");
        ui_clone.close();   
        exit(0);
        Ok(JSObject::Null)
    });

But remains almost same:

error[E0505]: cannot move out of `ui_clone` because it is borrowed
  --> src\main.rs:24:27
   |
24 |     ui_clone.bind("exit", move |_| {  // ui value moved into closure
   |     -------- ----         ^^^^^^^^ move out of `ui_clone` occurs here
   |     |        |
   |     |        borrow later used by call
   |     borrow of `ui_clone` occurs here
25 |         println!("good bye");
26 |         ui_clone.close();   // ui variable moved due to use in closure
   |         -------- move occurs due to use in closure

If ui's type has a clone method, it'll be called instead of Arc::clone. Always call the method via Arc::clone(ui). I'd even recommend doing that, if you know there is no conflict, because there might be one in the future and you don't want to go through the whole codebase to fix these kind of issues.

It gave me:

mismatched types [E0308] expected `&Arc<<unknown>>`, found `Arc<UI>` 

Once I tried:

let ui_clone = Arc::clone(ui);

According to the error message Arc::clone(&ui) should be correct, then.

You can't both call bind and move it into the closure passed to bind.

2 Likes

Thanks, worked as:

    let ui_clone = Arc::clone(&ui);
    ui.bind("exit", move |_| {
        println!("good bye");
        ui_clone.close();
        exit(0);
       // Ok(JSObject::Null)
    }).unwrap();
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.