Rust: Borrow with moved ownership with same lifetime [duplicate] - rust

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 7 months ago.
I have some code like this
struct A<'a> {
b: B,
c: C<'a>,
}
struct B {}
struct C<'a> {
b: &'a B
}
impl<'a> A<'a> {
fn new() -> Self {
let b = B {};
Self {
b,
c: C { b: &b },
}
}
}
where I get the error
error[E0515]: cannot return value referencing local variable `b`
--> src/dummy.rs:16:9
|
16 | / Self {
17 | | b,
18 | | c: C { b: &b },
| | -- `b` is borrowed here
19 | | }
| |_________^ returns a value referencing data owned by the current function
error[E0382]: borrow of moved value: `b`
--> src/dummy.rs:18:23
|
14 | let b = B {};
| - move occurs because `b` has type `B`, which does not implement the `Copy` trait
...
17 | b,
| - value moved here
18 | c: C { b: &b },
| ^^ value borrowed here after move
Some errors have detailed explanations: E0382, E0515.
For more information about an error, try `rustc --explain E0382`.
I think I understand the error, that of course b has a transferred ownership to that new object of A and therefore it seems like there is no guarantee for the lifetime of the object of C when it borrows from B. However because the object of C has its ownership also transferred to the object of A, the lifetime of the object of C as well as b should be the same, right?
How can I express that in Rust that I can create objects of A where I have an object of B and an object of C that also references to that object of B as B and C will have the same lifetime (the one of A)?

As pointed out in the comments and the duplicate question, you can't.
If you want to keep your current code structure, you are forced to use reference counters.
use std::{cell::RefCell, rc::Rc};
struct A {
b: Rc<RefCell<B>>,
c: C,
}
struct B {}
struct C {
b: Rc<RefCell<B>>,
}
impl A {
fn new() -> Self {
let b = Rc::new(RefCell::new(B {}));
Self {
b: b.clone(),
c: C { b },
}
}
}
However, I think it would be more benefitial to refactor your code structure to avoid this problem in the first place. This of course depends on the specific usecase.

Related

Is there no way to (one way or another) create an owned version of a (Box of) closure in rust?

I want to write a FuncWrapper struct with a new function that takes a (Boxed) closure as parameter, and returns a decorated closure that just adds some boilerplate to the incoming one. But I also want the returned value to be "owned", to allow for the following (e.g.):
fn main() {
let a: FuncWrapper<u32>;
{
let foo = |x: u32| {print!("{}", x)};
let b = &Box::new(foo);
a = FuncWrapper::new(b);
}
let _c = (a.func)(42);
}
That is, I want for the return value of new to be an "owned" value.
Now I recently learned that all closures in Rust (being Trais) must have a lifetime associated with them (and it will default to 'static if not specified.) But I suppose its seems that any lifetime for the closure in the FuncWrapper of the return value of new will be wrong.
I don't want the lifetime to be that of the incoming reference, because this will be too short. E.g. the following will not work because it the lifetime of the return value is that of the parameter f_box_ref which does not live long enough in the case I provide above
struct FuncWrapper<'b, DomainType> {
func: Box<dyn Fn(DomainType) + 'b>
}
impl<'b, DomainType> FuncWrapper<'b, DomainType> {
fn new<F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<'b, DomainType> {
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(**f_box_ref)(a)
};
let b = Box::new(new_f);
FuncWrapper {func: b}
}
}
results in
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:22:18
|
22 | let b = &Box::new(foo);
| ^^^^^^^^^^^^^ creates a temporary which is freed while still in use
23 | a = FuncWrapper::new(b);
24 | }
| - temporary value is freed at the end of this statement
...
27 | }
| - borrow might be used here, when `a` is dropped and runs the destructor for type `FuncWrapper<'_, u32>`
|
= note: consider using a `let` binding to create a longer lived value
Changing the lifetime of the return parameter to 'static also seems wrong, since my goal is to create a new closure inside the new function`, (so how could it be static?) but regardless this:
struct FuncWrapper<DomainType> {
func: Box<dyn Fn(DomainType) + 'static>
}
impl<DomainType> FuncWrapper<DomainType> {
fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(**f_box_ref)(a)
};
let b = Box::new(new_f);
FuncWrapper {func: b}
}
}
errors with
error[E0759]: `f_box_ref` has lifetime `'b` but it needs to satisfy a `'static` lifetime requirement
--> src/main.rs:7:21
|
6 | fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
| ---------- this data with lifetime `'b`...
7 | let new_f = move |a: DomainType| {
| _____________________^
8 | | // ..add some boilerplate then
9 | | (**f_box_ref)(a)
10 | | };
| |_________^ ...is used here...
11 | let b = Box::new(new_f);
12 | FuncWrapper {func: b}
| - ...and is required to live as long as `'static` here
The error surprised me since I thought the job of move was to capture by value. At first I thought that I need to dereference the f_box_ref first? But that
impl<DomainType> FuncWrapper<DomainType> {
fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
let f_box: Box<F> = *f_box_ref;
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(*f_box)(a)
};
let b = Box::new(new_f);
FuncWrapper {func: b}
}
}
results in
error[E0507]: cannot move out of `*f_box_ref` which is behind a shared reference
--> src/main.rs:7:30
|
7 | let f_box: Box<F> = *f_box_ref;
| ^^^^^^^^^^
| |
| move occurs because `*f_box_ref` has type `Box<F>`, which does not implement the `Copy` trait
| help: consider borrowing here: `&*f_box_ref`
Alas, following the hint to "help: consider borrowing here: &*f_box_ref" doesn't help either
impl<DomainType> FuncWrapper<DomainType> {
fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
let f_box: &Box<F> = &*f_box_ref;
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(*f_box)(a)
};
let b = Box::new(new_f);
FuncWrapper {func: b}
}
}
errors with
error[E0759]: `f_box_ref` has lifetime `'b` but it needs to satisfy a `'static` lifetime requirement
--> src/main.rs:7:31
|
6 | fn new<'b, F: Fn(DomainType) + 'static>(f_box_ref: &'b Box<F>) -> FuncWrapper<DomainType> {
| ---------- this data with lifetime `'b`...
7 | let f_box: &Box<F> = &*f_box_ref;
| ^^^^^^^^^^^ ...is used here...
...
13 | FuncWrapper {func: b}
| - ...and is required to live as long as `'static` here
so obviously we're still not returning anything like a new owned closure, and any choice for the lifetime of the returned closure seems arbitrary and wrong.
What I'm trying to do here seems like it should be common. What am I missing?
It's fairly straight forward, to get an owned type from a reference you have 3 options that come to mind immediately:
Copy, Clone or ToOwned.
ToOwned is a little more advanced since it can change the type as well and since Copy requires Cloned I'll focus on the later.
To get an owned Fn from a &Box<Fn> you can just call clone():
impl<DomainType> FuncWrapper<DomainType> {
fn new<F: Fn(DomainType) + Clone + 'static>(f_box_ref: &Box<F>) -> FuncWrapper<DomainType> {
let f_box = f_box_ref.clone();
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(f_box)(a)
};
let b = Box::new(new_f);
FuncWrapper { func: b }
}
}
Since it is not FnMut, just Fn maybe you can use an Rc instead of Box? You can always clone an Rc
use std::rc::Rc;
impl<DomainType> FuncWrapper<DomainType> {
fn new<F: Fn(DomainType) + 'static>(f_rc: Rc<F>) -> FuncWrapper<DomainType> {
let new_f = move |a: DomainType| {
// ..add some boilerplate then
(f_rc)(a)
};
let b = Box::new(new_f);
FuncWrapper { func: b }
}
}

Return value referencing local variable in Self::new() [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 9 months ago.
So I have a struct looking like this:
struct InterpolationList<'a, T: Interpolatable<T, Output=T>> {,
first_entry: InterpolationListValue<'a, T>,
last_entry: &'a mut InterpolationListValue<'a, T>,
}
And now I implemented a new function to create a simple "Instance":
pub fn new(distance: u64, value: T) -> InterpolationList<'a, T> {
let mut initial_entry = InterpolationListValue::new(distance, value);
InterpolationList {
first_entry: initial_entry,
last_entry: &mut initial_entry,
}
}
This however gives me the following errors:
cannot return value referencing local variable `initial_entry`
/ InterpolationList {
20 | | first_entry: initial_entry,
21 | | last_entry: &mut initial_entry,
| | ------------------ `initial_entry` is borrowed here
23 | | }
| |_________^ returns a value referencing data owned by the current function
borrow of moved value: `initial_entry`
|
17 | let mut initial_entry = InterpolationListValue::new(distance, value);
| ----------------- move occurs because `initial_entry` has type `InterpolationListValue<'_, T>`, which does not implement the `Copy` trait
...
23 | first_entry: initial_entry,
| ------------- value moved here
24 | last_entry: &mut initial_entry,
| ^^^^^^^^^^^^^^^^^^ value borrowed here after move
My guess is that rust thinks, ownership of initial_entry still belongs to the function, even though it is moved to the InterpolationList struct, because both move and referencing happens in the same instruction.
Does anybody know how to fix/circumvent this?
It has been explained several times why.
In this case if I am not missing something from the context, you could just make a method on your struct to access that:
impl<'a, T> InterpolationList<'a, T> where T: Interpolatable<T, Output=T> {
pub fn last_entry_mut(&mut self) -> &mut InterpolationListValue<'a, T> {
&mut self.first_entry
}
}

Return references to parts of one struct as fields of another struct [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 4 years ago.
I want move one struct into another and get references on parts of first struct as parts of other without cloning or copying, if it is possible. How to do it in right way?
fn main() {
let foo = Foo::new();
let bar = Bar::new(foo);
println!("{:?}", bar);
}
#[derive(Debug)]
struct Foo {
v: String,
}
impl Foo {
pub fn new() -> Self {
Foo {
v: String::from("a|b"),
}
}
pub fn get_a(&self) -> &str {
&self.v[0..1]
}
pub fn get_b(&self) -> &str {
&self.v[2..3]
}
}
#[derive(Debug)]
struct Bar<'a> {
foo: Foo,
a: &'a str,
b: &'a str,
}
impl<'a> Bar<'a> {
pub fn new(f: Foo) -> Self {
Bar::parse(f)
}
fn parse(f: Foo) -> Self {
let a = f.get_a();
let b = f.get_b();
Bar { foo: f, a, b }
}
}
Rust Playground
I got an error:
error[E0515]: cannot return value referencing function parameter `f`
--> src/main.rs:44:9
|
41 | let a = f.get_a();
| - `f` is borrowed here
...
44 | Bar { foo: f, a, b }
| ^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing function parameter `f`
--> src/main.rs:44:9
|
42 | let b = f.get_b();
| - `f` is borrowed here
43 |
44 | Bar { foo: f, a, b }
| ^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `f` because it is borrowed
--> src/main.rs:44:20
|
35 | impl<'a> Bar<'a> {
| -- lifetime `'a` defined here
...
41 | let a = f.get_a();
| - borrow of `f` occurs here
...
44 | Bar { foo: f, a, b }
| -----------^--------
| | |
| | move out of `f` occurs here
| returning this value requires that `f` is borrowed for `'a`
The lifetime of the argument f to parse ends when parse returns. Older Rust compiler versions returned an error message which might have been more useful:
error[E0597]: `f` does not live long enough
--> t.rs:41:17
|
41 | let a = f.get_a();
| ^ borrowed value does not live long enough
...
45 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 35:1...
--> t.rs:35:1
|
35 | / impl<'a> Bar<'a> {
36 | | pub fn new(f: Foo) -> Self {
37 | | Bar::parse(f)
38 | | }
... |
45 | | }
46 | | }
| |_^
I can get your example to compile by changing the definition of Bar to:
#[derive(Debug)]
struct Bar<'a> {
foo: &'a Foo,
a: &'a str,
b: &'a str,
}
and passing references of type &'a Foo to Bar::new and Bar::parse. However, it is unclear if this solution will work for your original problem. Maybe you need to use Rc if the ownership structure is too complicated.

How do I pass a function that creates a struct containing a Cell with a lifetime to another function?

I'm trying to pass a constructor function as an argument to another function. The function creates a struct with an associated lifetime. I need to create a struct from this pointer after I have created some other objects that this struct can then reference. The example below seems to work:
struct Bar<'a> {
number: Option<&'a usize>,
}
impl<'a> Bar<'a> {
pub fn new() -> Bar<'a> {
Bar { number: None }
}
}
fn foo<'a, F>(func: &F)
where
F: Fn() -> Bar<'a>,
{
let number = 42;
let mut bar = (func)();
bar.number = Some(&number);
}
fn main() {
foo(&Bar::new);
}
When I add a Cell for interior mutability then it does not compile:
use std::cell::Cell;
struct Bar<'a> {
number: Cell<Option<&'a usize>>,
}
impl<'a> Bar<'a> {
pub fn new() -> Bar<'a> {
Bar {
number: Cell::new(None),
}
}
}
fn foo<'a, F>(func: &F)
where
F: Fn() -> Bar<'a>,
{
let number = 42;
let bar = (func)();
bar.number.set(Some(&number));
}
fn main() {
foo(&Bar::new);
}
Giving me the following error:
error[E0597]: `number` does not live long enough
--> src/main.rs:21:26
|
21 | bar.number.set(Some(&number));
| ^^^^^^ borrowed value does not live long enough
22 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 15:1...
--> src/main.rs:15:1
|
15 | / fn foo<'a, F>(func: &F)
16 | | where
17 | | F: Fn() -> Bar<'a>,
18 | | {
... |
21 | | bar.number.set(Some(&number));
22 | | }
| |_^
Why did the first example work and not the second? Is there a way to specify a lifetime that exists for the scope let mut bar until the end of the function, rather than 'a which encompasses the entire function? Is this not possible without Non Lexical Lifetimes or Higher Kind Type Constructors etc?
The compiler is smarter than you give it credit for. It has prevented you from introducing memory unsafety:
fn foo<'a, F>(func: &F)
where
F: Fn() -> Bar<'a>,
{
let number = 42;
let bar = (func)();
bar.number.set(Some(&number));
}
This code says that the caller of foo can specify a lifetime for 'a, but then the body of the method stores a reference into the value. That stored reference is not guaranteed to live that long. As an obvious example, the caller might require that 'a == 'static, but that would be impossible for the function to accomplish:
fn b() -> Bar<'static> {
Bar {
number: Cell::new(None),
}
}
fn main() {
foo(&b);
}
Note that this doesn't have anything to do with closures or functions:
use std::cell::Cell;
fn main() {
let number = Cell::new(None);
let x = 1;
number.set(Some(&x));
let y = 2;
number.set(Some(&y));
}
error[E0597]: `x` does not live long enough
--> src/main.rs:6:22
|
6 | number.set(Some(&x));
| ^ borrowed value does not live long enough
...
9 | }
| - `x` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
Why did the first example work and not the second?
Because the compiler knows that Cell (really UnsafeCell) needs to account for the possibility that you will be storing a value in the created type.
From the Nomicon, emphasis mine:
UnsafeCell<T>, Cell<T>, RefCell<T>, Mutex<T> and all other interior mutability types are invariant over T (as is *mut T by metaphor)
Variance is a dense topic that I cannot explain succinctly.
#trentcl provides this example that shows that your original code may not be doing what you think it is.
Without the Cell, the compiler knows that it's safe to automatically adjust the lifetime of the returned type to one that's a little bit shorter. If we force the type to be the longer 'a, however, we get the same error:
fn foo<'a, F>(func: F)
where
F: Fn() -> Bar<'a>,
{
let number = 42;
let mut bar: Bar<'a> = func();
// ^^^^^^^
bar.number = Some(&number);
}
error[E0597]: `number` does not live long enough
--> src/main.rs:17:24
|
17 | bar.number = Some(&number);
| ^^^^^^ borrowed value does not live long enough
18 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 11:1...
--> src/main.rs:11:1
|
11 | / fn foo<'a, F>(func: F)
12 | | where
13 | | F: Fn() -> Bar<'a>,
14 | | {
... |
17 | | bar.number = Some(&number);
18 | | }
| |_^
Is this not possible without [...]
Yes, but I'm not sure exactly what it would be. I believe it would need generic associated types (GAT) from RFC 1598.
My first thought was to try higher-ranked trait bounds (HRTB):
fn foo<F>(func: F)
where
F: for<'a> Fn() -> Bar<'a>,
{
let number = 42;
let bar = func();
bar.number.set(Some(&number));
}
This triggers E0582:
error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
--> src/main.rs:17:25
|
17 | F: for <'a> Fn() -> Bar<'a>,
| ^^^^^^^
To be honest, I cannot see the value in the code based on the example provided. If you are returning a Bar by value, you can make it mutable, removing any need for interior mutability.
You can also change the closure to take the value as needed:
fn foo<F>(func: F)
where
F: for<'a> Fn(&'a i32) -> Bar<'a>,
{
let number = 42;
let bar = func(&number);
}
See also:
Is it possible to have a struct which contains a reference to a value which has a shorter lifetime than the struct?
How does for<> syntax differ from a regular lifetime bound?

What is the correct way to use lifetimes with a struct in Rust?

I want to write this structure:
struct A {
b: B,
c: C,
}
struct B {
c: &C,
}
struct C;
The B.c should be borrowed from A.c.
A ->
b: B ->
c: &C -- borrow from --+
|
c: C <------------------+
This is what I tried:
struct C;
struct B<'b> {
c: &'b C,
}
struct A<'a> {
b: B<'a>,
c: C,
}
impl<'a> A<'a> {
fn new<'b>() -> A<'b> {
let c = C;
A {
c: c,
b: B { c: &c },
}
}
}
fn main() {}
But it fails:
error[E0597]: `c` does not live long enough
--> src/main.rs:17:24
|
17 | b: B { c: &c },
| ^ borrowed value does not live long enough
18 | }
19 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'b as defined on the method body at 13:5...
--> src/main.rs:13:5
|
13 | fn new<'b>() -> A<'b> {
| ^^^^^^^^^^^^^^^^^^^^^
error[E0382]: use of moved value: `c`
--> src/main.rs:17:24
|
16 | c: c,
| - value moved here
17 | b: B { c: &c },
| ^ value used here after move
|
= note: move occurs because `c` has type `C`, which does not implement the `Copy` trait
I've read the Rust documentation on ownership, but I still don't know how to fix it.
There is actually more than one reason why the code above fails. Let's break it down a little and explore a few options on how to fix it.
First let's remove the new and try building an instance of A directly in main, so that you see that the first part of the problem has nothing to do with lifetimes:
struct C;
struct B<'b> {
c: &'b C,
}
struct A<'a> {
b: B<'a>,
c: C,
}
fn main() {
// I copied your new directly here
// and renamed c1 so we know what "c"
// the errors refer to
let c1 = C;
let _ = A {
c: c1,
b: B { c: &c1 },
};
}
this fails with:
error[E0382]: use of moved value: `c1`
--> src/main.rs:20:20
|
19 | c: c1,
| -- value moved here
20 | b: B { c: &c1 },
| ^^ value used here after move
|
= note: move occurs because `c1` has type `C`, which does not implement the `Copy` trait
what it says is that if you assign c1 to c, you move its ownership to c (i.e. you can't access it any longer through c1, only through c). This means that all the references to c1 would be no longer valid. But you have a &c1 still in scope (in B), so the compiler can't let you compile this code.
The compiler hints at a possible solution in the error message when it says that type C is non-copyable. If you could make a copy of a C, your code would then be valid, because assigning c1 to c would create a new copy of the value instead of moving ownership of the original copy.
We can make C copyable by changing its definition like this:
#[derive(Copy, Clone)]
struct C;
Now the code above works. Note that what #matthieu-m comments is still true: we can't store both the reference to a value and the value itself in B (we're storing a reference to a value and a COPY of the value here). That's not just for structs, though, it's how ownership works.
Now, if you don't want to (or can't) make C copyable, you can store references in both A and B instead.
struct C;
struct B<'b> {
c: &'b C,
}
struct A<'a> {
b: B<'a>,
c: &'a C, // now this is a reference too
}
fn main() {
let c1 = C;
let _ = A {
c: &c1,
b: B { c: &c1 },
};
}
All good then? Not really... we still want to move the creation of A back into a new method. And THAT's where we will run in trouble with lifetimes. Let's move the creation of A back into a method:
impl<'a> A<'a> {
fn new() -> A<'a> {
let c1 = C;
A {
c: &c1,
b: B { c: &c1 },
}
}
}
as anticipated, here's our lifetime error:
error[E0597]: `c1` does not live long enough
--> src/main.rs:17:17
|
17 | c: &c1,
| ^^ borrowed value does not live long enough
...
20 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 13:1...
--> src/main.rs:13:1
|
13 | impl<'a> A<'a> {
| ^^^^^^^^^^^^^^
error[E0597]: `c1` does not live long enough
--> src/main.rs:18:24
|
18 | b: B { c: &c1 },
| ^^ borrowed value does not live long enough
19 | }
20 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 13:1...
--> src/main.rs:13:1
|
13 | impl<'a> A<'a> {
| ^^^^^^^^^^^^^^
this is because c1 is destroyed at the end of the new method, so we can't return a reference to it.
fn new() -> A<'a> {
let c1 = C; // we create c1 here
A {
c: &c1, // ...take a reference to it
b: B { c: &c1 }, // ...and another
}
} // and destroy c1 here (so we can't return A with a reference to c1)
One possible solution is to create C outside of new and pass it in as a parameter:
struct C;
struct B<'b> {
c: &'b C,
}
struct A<'a> {
b: B<'a>,
c: &'a C
}
fn main() {
let c1 = C;
let _ = A::new(&c1);
}
impl<'a> A<'a> {
fn new(c: &'a C) -> A<'a> {
A {c: c, b: B{c: c}}
}
}
playground
After checking with Manishearth and eddyb on the #rust IRC, I believe it's not possible for a struct to store a reference to itself or a portion of itself. So what you are trying to do isn't possible within Rust's type system.
Late to the party (replying from the future) and totally new to Rust, but I am getting there (sort of). Building on the answer this worked for me, at least compile wise.
impl<'a> A<'a> {
fn new() -> A<'a> {
let c1:&'a C = &C;
A {
c: c1,
b: B { c: c1 },
}
}
}

Resources