How can I pass reference of data to self variable to another

I'm trying this in playground with error

    #[derive(Debug, Copy, Clone)]
    struct Foo<'a, T> {
        data: T,
        data2: &'a T,
    }

    impl<T:Copy> Foo<'_,T> {
        fn new(d: T) -> Self {
            Foo {
                data: d,
                data2: &d,
            }
        }
    }

    fn main() {
        let mut foo = Foo::new("hello");

        let x = &mut foo.data;
        let y = &mut foo.data2;

        println!("{}", &foo.data);
        println!("{}", x);
        println!("{}", y);
    }

error:

error[E0515]: cannot return value referencing function parameter `d`
  --> src/main.rs:9:9
   |
9  | /         Foo {
10 | |             data: d,
11 | |             data2: &d,
   | |                    -- `d` is borrowed here
12 | |         }
   | |_________^ returns a value referencing data owned by the current function

I want to refer same variable as reference for a struct var, while having it borrowed as another.

Self-referential types are not possible in safe Rust. Split up your struct so that one type holds the data by value, while another one provides a borrowed view into it.

2 Likes

See also Saving variables interwoven by reference in one structure

Alternatively, generate the reference on-the-fly when it's needed:

struct Foo<T> {
    data: T
}

impl<T> Foo<T> {
    pub fn data2(&self)->&T { &self.data }
}
2 Likes

Thank you.
I think this should be allowed as the reference is immutable and ownership is with data var. For now I'll use the work around thank you everyone

Are you looking to keep the data field mutable? What makes generating a reference only when needed not ideal for your situation?

The problem is that Rust requires all types to be relocatable. Moving an object to another place in memory is always allowed by the object's owner, as long as the owner hasn't lent out a reference. This is impossible If an object contains a pointer into itself: The pointer will continue referring to the old, invalid, location.


The more local problem with this code is that d resides in the new function's stack frame. That stack frame is destroyed when new() returns, and so the memory location that Foo::data2 is referring is no longer valid. You can get similar code to work by referring to the T on the calling function's stack, instead:

    impl<T:Copy> Foo<'_,T> {
        fn new<'a>(d: &'a T) -> Foo<'a,T> {
            Foo {
                data: *d,
                data2: d,
            }
        }
    }

Here, though, changing the contents of Foo::data won't be reflected in Foo::data2.


Regardless of the definition of Foo, this code is incorrect. &mut references are non-aliasing: no other accesses to the referent are allowed while one exists. Here, the line let x = &mut foo.data claims exclusive access to foo.data until println!("{}", x), the last mention of x. The print of foo.data occurs between these two statements, which is forbidden.

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.