'static lifetime required for a cloned & moved value when spawning thread?

I was trying to parallelise some code, but I'm getting an error I don't quite understand. This is the first time I'm trying multi-threading in any language btw.
The code vaguely resembles the following:

pub async fn function(
    ...
    profile: &Profile,
//  ^^^^^^^ this has an anonymous lifetime
) -> Result<()> {
    for item in items {
        let profile = profile.clone()
        tokio::task::spawn(async move {
//                   ^^^^^ and is required to live for 'static here
            another_function(
                ...
                &profile,
            ).await?;
            ...
        }
    }
}

But why is it required to live for static? I cloned it and moved it, so why is it still considered a 'reference'? How would I solve this?

The full code can be found here and the full error here

The current code tries to use a reference to the profile in the async block, while the actual profile is owned outside of it. Try taking ownership of the profile inside the block, like this:

pub async fn function(
    ...
    profile: &Profile,
//  ^^^^^^^ this has an anonymous lifetime
) -> Result<()> {
    for item in items {
        let profile = profile.clone()
        tokio::task::spawn(async move {
            let profile = profile; // <-- Added, to move ownership inside the block
            another_function(
                ...
                &profile,
            ).await?;
            ...
        }
    }
}

But shouldn't moving ownership be done by the move keyword? And it doesn't work either it still gives me the same error. I have a feeling the compiler somehow isn't reporting the actual error correctly.

What is the exact message the compiler is giving you? Are you sure that profile.clone() is cloning the Profile object and not the &Profile reference?

The full error message is here

Yes because the type changes to Profile as expected

This message is suggesting that the compiler is trying to move the outer profile reference and not the cloned profile. Are you also sure that the variable is correctly shadowed and you haven't made any typos (e.g., let proflie = profile.clone())?

Yes I checked that too, even the IDE jumps to the correct variables

Aha I finally figured it out. The problem is that I'm using item inside the block too, and since item borrows from profile.mods in the actual code profile is borrowed too. :man_facepalming:
This bug was really hard to find though

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.