jeudi 26 novembre 2020

In Rust, what's the pattern for when you need a reference-holding struct to sometimes own its referenced data?

Consider the following data structure:

struct ReferenceHoldingStruct<'a> {
    pub prop: &'a str
}

This pattern is often useful, especially in parsers (my use-case), for "giving" a struct some piece of string data without re-allocating it:

fn generate_these_1<'a>(input: &'a str) -> ReferenceHoldingStruct<'a> {
    ReferenceHoldingStruct { prop: input }
}

However, I've got a case where I have a struct like the above, but in one spot I need to generate instances that are "independent"; i.e. they own their own data:

fn generate_these_2<'a>(input: String) -> ReferenceHoldingStruct<'a> {
    ReferenceHoldingStruct { prop: input.as_str() }
}

I understand why this version doesn't work: the String being referred to doesn't live anywhere where Rust can see that it will hang around to keep fulfilling the struct's &str reference. I thought maybe this would work:

fn generate_these_2<'a>(input: String) -> (String, ReferenceHoldingStruct<'a>) {
    (input, ReferenceHoldingStruct { prop: input.as_str() })
}

because at least the String won't get immediately dropped. I thought maybe Rust could figure out that this tuple contains both the reference and the data it refers to, and that they'd therefore be valid as long as they're kept together like this. But no dice: this still doesn't work. It treats the reference as a borrow and the move to the tuple as a move, and you can't do both "at the same time".

So, I understand the problem, but not where to go from here. What's the standard practice for this kind of situation?

Aucun commentaire:

Enregistrer un commentaire