Making borrowed struct from borrowed data

Is there a way to make a borrowed struct out of two pieces of borrowed data, for example:

struct Composite {
    u: usize,
    s: String
}

fn is_this_possible(u: &usize, s: &String) -> &Composite {
    // dark type magic
}

Or is this impossible as the struct must own the data it carries?

The situation is I have an enum-like thing going where I have a tag and some data. If I own the data, I can return an owned enum variant produced from the tag and data, but if I'm borrowing the data, I'd like to return a borrowed enum variant.

This trait describes the behaviour: peapod/lib.rs at main · fprasx/peapod · GitHub

I'd like to add a function like this:

fn reknit_ref(tag: usize, data: &Option<Self::Value>) -> &Self

Yes, but only if you change the definition of the struct.

If you want Composite to always represent borrowed data, then you can do:

struct Composite<'a> {
    u: usize, // probably no point borrowing this, it's cheap to copy
    s: &'a str,
}

If you want to abstract over owned/borrowed data, you can use the Cow (short for 'copy on write') type, or define something similar yourself:

struct Composite<'a> {
    u: usize, // probably no point borrowing this, it's cheap to copy
    s: Cow<'a, str>,
}
3 Likes

Borrowing requires the thing to already exist in memory, exactly in the final format required to borrow it. This happens to work in some cases, e.g. &Option<T> can be changed to Option<&T>, and loan of a struct can be split into loans of its fields.

However, it's not possible to guarantee that two independent function arguments form a cohesive struct in memory (even if the addresses happened to match, it's still not allowed per Rust's borrowing rules), so the specific case of fn(u: &usize, s: &String) -> &Composite is not possible.

2 Likes

Ahh ok, thank you all!

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.