Problems implementing the Borrow trait


I am making a library that parses some records from a file. I have two versions of the main record struct: one that owns the data and one that does not:

pub struct OwnedRecord{
    pub data1: Vec<u8>,    
    pub data2: Vec<u8>,

pub struct RefRecord<'a>{
    pub data1: &'a [u8],    
    pub data2: &'a [u8],

(The records are actually more complicated than this, but this example already demonstrates my issue)

The purpose of the RefRecord version is that it can refer to internal buffers in my library, so that if the records are processed in a streaming fashion, I can reuse those internal buffers for better performance.

Now, I want to have a hash table that has OwnedRecord as the key type, so that I can also look up values in the hash table using the RefRecord type. From what I understand, I can do this if I implement the trait Borrow for OwnedRecord. That is, I need the following implementation:

impl<'a> Borrow<RefRecord<'a>> for OwnedRecord{
    fn borrow(&self) -> &RefRecord<'a>{

But, I can't implement this, because I can not return a reference to a RefRecord from this function because any RefRecord created here will not live long enough.

I must be doing something wrong. What would be the best way to accomplish what I'm trying to do here?


The signature of Borrow<T>::borrow only works if you effectively have a T as a field. You don't have a RefRecord as a field.

hashbrown has more flexible trait bounds, perhaps that would work for you.


Thanks. It looks like hashbrown would work for me. But I would prefer if the user of the library could use it with the standard hash map. I guess that is not possible with the two structs I have.

One workaround is to make one type for both:

struct Record<'a> {
    pub data1: Cow<'a, [u8]>,    
    pub data2: Cow<'a, [u8]>,

Then you can store Record<'static> and compare against Record<'a>.


This is a tricky problem. You might find Armin Ronacher's article on GATs or the experimental borrowme crate interesting (even if you can't use it).

I think you should be able to return a RefRecord from your borrow function if you return it without the reference.

    fn borrow(&self) -> RefRecord<'a>{

You have to move the RefRecord out of the fubction if you want to keep it alive past the end of that functions scope. you could also declare it as const or static but you will either leak memory or program space.
const record : RefRecord = { ... } <-- memory leak
static record : RefRecord = { ... } <-- stored in program binary

The Borrow trait defines the signature, which requires a reference be returned.

1 Like

No, consts don't leak memory.

If you need to create a RefRecord inside the borrow function and need to return a reference to that record you can:

  1. Define the created RefRecord as const or static.

  2. Move the created RefRecord out of the the function to somewhere it can live longer.

I did create this (Playground) which compiles despite doing neither of these... but it doesn't actually solve the problem it just kicks the can down the road.

I would suggest creating the RefRecord outside of the borrow function somewhere it can live longer. However you end up doing it, once you have a way for the RefRecord to live long enough, my playground code might be helpful.

There's no sound way without leaking memory or refer to a static object; in the latter case it won't reflect the contents of the OwnedRecord.

1 Like

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.