Struct must outlive member reference - rust

I'm not sure how to properly title this post. I'm fairly new to Rust and trying to compile a program following this simple structure, but it seems to be incorrect, and I'm not sure why.
struct Bar;
impl Bar {
fn do_thing(&self) { println!("Ha, do nothing!") }
}
struct Foo<'a> {
bar: &'a Bar
}
impl<'a> Foo<'a> {
fn new(b: &Bar) -> Foo { Foo { bar: b } }
fn get_bar(&self) -> &Bar { self.bar }
}
fn main() {
let b = Bar;
let b_ref = {
let f = Foo::new(&b);
f.get_bar()
};
b_ref.do_thing();
}
The compiler error here claims that f does not live long enough. It shouldn't matter how long f lives though -- b_ref is valid for as long as b is, and I thought that references were Copy so that we wouldn't have to worry about the actual reference in f. Is this relevant?
Part of me feels like I need to specify the lifetime of the &Bar being returned from get_bar, but I don't know how to tie that into the lifetime of the Foo struct?
What am I missing here?

You have to specify that the reference you are returning is tied to the lifetime 'a and not the lifetime of self that compiler will infer for you:
impl<'a> Foo<'a> {
fn new(b: &Bar) -> Foo { Foo { bar: b } }
fn get_bar(&self) -> &'a Bar { self.bar }
}
This is equivalent to the original code:
impl<'a> Foo<'a> {
fn new(b: &Bar) -> Foo { Foo { bar: b } }
fn get_bar<'b>(&'b self) -> &'b Bar { self.bar }
}
Part of me feel like I should need to specify the lifetime of the &Bar
being returned from get_bar, but I don't know how to tie that into the
lifetime of the Foo struct?
The lifetime of Foo does not matter at all in this case.

Related

Closure lifetime in Rust through simple pattern

I'm trying to recreate a simple callback pattern in Rust using 2 structs. One will pass a bit of logic to execute whenever the other one is ready. The issue here is that the logic will run only if a certain value from the struct is true.
I can understand why the reference to Foo needs to live for 'static in this case, but I'm not sure how to refactor so that it compiles.
Seems like a pretty regular use case, but maybe I'm missing something since I'm new to Rust.
struct Foo {
value: bool,
}
struct Bar {
closure: Box<dyn Fn() -> ()>,
}
impl Foo {
fn new() -> Self {
Foo {
value: false,
}
}
fn set_closure(&self, b: &mut Bar) {
b.closure = self.get_closure();
}
fn get_closure(&self) -> Box<dyn Fn() -> ()> {
return Box::new(|| {
if self.value {
println!("true");
} else {
println!("false");
}
});
}
}
impl Bar {
fn new() -> Self {
Bar {
closure: Box::new(|| {})
}
}
}
fn main() {
let foo = Foo::new();
let mut bar = Bar::new();
foo.set_closure(&mut bar);
let closure = bar.closure;
closure();
}
Playground link -> here
You need to move the value into the closure:
fn get_closure(&self) -> Box<dyn Fn() -> ()> {
let value = self.value;
Box::new(move || {
if value {
println!("true");
} else {
println!("false");
}
})
}
Notice that in your example value is a bool which is Copy. If not you can either capture a reference or clone it. (If capturing a reference you may need to adjust some lifetimes there).
Playground

Cannot return referencing local variable and cannot move because its borrowed

I don't understand these two errors cannot return value referencing local variable 'foo_builder' and cannot move out of 'foo_builder' because it is borrowed. Here we have two structs Foo and FooBuilder, Foo is built by FooBuilder and its instance (or instances) cannot outlive FooBuilder (or thats what I'm trying to express with the code).
Then if there is a new struct called BigChungus that contains both, there should be no problem, right?
The fact that Foo cannot outlive its creator I think is properly expressed, then why rust complains that first cannot return local variable reference when the BigChungus now should own the Foo reference because it owns also FooBuilder?
Thanks in advance, here is the code and the live example:
use std::marker::PhantomData;
struct Foo<'r> {
_marker: PhantomData<&'r ()>,
}
struct FooBuilder;
impl FooBuilder {
fn create_foo(&self) -> Foo {
Foo { _marker: PhantomData }
}
}
struct BigChungus<'a> {
foo: Foo<'a>,
foo_builder: FooBuilder
}
impl<'a> BigChungus<'a> {
fn new() -> Self {
let foo_builder = FooBuilder;
let foo = foo_builder.create_foo();
Self {
foo,
foo_builder
}
}
}

Extracting a function which creates an instance in Rust

A bit of a beginner Rust question - say I have the following code, which compiles:
trait XGetter {
fn get_x(&self) -> i32;
}
struct Foo {
x: i32
}
impl XGetter for Foo {
fn get_x(&self) -> i32 {
self.x
}
}
struct Bar<'a>(&'a dyn XGetter);
impl<'a> XGetter for Bar<'a> {
fn get_x(&self) -> i32 {
self.0.get_x()
}
}
fn baz() -> i32 {
let foo = Foo { x: 42 };
let bar = Bar(&foo);
bar.get_x()
}
Let's say I want to extract out the creation of Bar, in order encapsulate the creation of the XGetter and Bar together, such that baz() now reads:
fn baz2() -> i32 {
let bar = createBar(42);
bar.get_x()
}
However, by implementing createBar below, I run a-fowl of the borrow checker:
fn createBar<'a>(x: i32) -> Bar<'a> {
let foo = Foo { x };
let bar = Bar(&foo);
// ---- `foo` is borrowed here
bar
// ^^^ returns a value referencing data owned by the current function
}
How would one extract out a function createBar which doesn't break the borrowing rules?
The foo in createBar() dies when the function ends, so the bar you return would be pointing to invalid memory.
Given how you have written the call to createBar(42), it looks like you want Bar to own the Foo, so do that:
struct Bar(Box<dyn XGetter>);
impl XGetter for Bar {
fn get_x(&self) -> i32 {
self.0.get_x()
}
}
fn createBar(x: i32) -> Bar {
let foo = Box::new(Foo { x });
let bar = Bar(foo);
bar
}
You can not:
The signature struct Bar<'a>(&'a dyn XGetter); and createBar(i: 32) are incompatible. Because it means that in createBar you would have to instantiate an object implementing XGetter and that reference will not live outside of the scope of createBar.
fn createBar<'a>(x: i32) -> Bar<'a> {
let foo = Foo { x };
let bar = Bar(&foo);
// ---- `foo` is borrowed here
bar
// ^^^ returns a value referencing data owned by the current function
}
^^^ That means that the variable foo will live just during createBar scope.
That said, you could use:
fn createBar(g: &dyn XGetter) -> Bar<'_> {
Bar(g)
}
That way the reference will live outside of the scope of createBar.
Playground
As per the comments. If you want to abstract that, you need Bar to own Foo
struct Bar(Box<dyn XGetter>);
fn createBar(x: i32) -> Bar {
let foo = Box::new(Foo { x });
let bar = Bar(foo);
bar
}

Pass a closure as an argument and store it to be called later [duplicate]

Before Rust 1.0, I could write a structure using this obsolete closure syntax:
struct Foo {
pub foo: |usize| -> usize,
}
Now I can do something like:
struct Foo<F: FnMut(usize) -> usize> {
pub foo: F,
}
But then what's the type of a Foo object I create?
let foo: Foo<???> = Foo { foo: |x| x + 1 };
I could also use a reference:
struct Foo<'a> {
pub foo: &'a mut FnMut(usize) -> usize,
}
I think this is slower because
the pointer dereference
there's no specialization for the type of FnMut that actually ends up being used
Complementing the existing answer with some more code for demonstration purposes:
Unboxed closure
Use a generic type:
struct Foo<F>
where
F: Fn(usize) -> usize,
{
pub foo: F,
}
impl<F> Foo<F>
where
F: Fn(usize) -> usize,
{
fn new(foo: F) -> Self {
Self { foo }
}
}
fn main() {
let foo = Foo { foo: |a| a + 1 };
(foo.foo)(42);
(Foo::new(|a| a + 1).foo)(42);
}
Boxed trait object
struct Foo {
pub foo: Box<dyn Fn(usize) -> usize>,
}
impl Foo {
fn new(foo: impl Fn(usize) -> usize + 'static) -> Self {
Self { foo: Box::new(foo) }
}
}
fn main() {
let foo = Foo {
foo: Box::new(|a| a + 1),
};
(foo.foo)(42);
(Foo::new(|a| a + 1).foo)(42);
}
Trait object reference
struct Foo<'a> {
pub foo: &'a dyn Fn(usize) -> usize,
}
impl<'a> Foo<'a> {
fn new(foo: &'a dyn Fn(usize) -> usize) -> Self {
Self { foo }
}
}
fn main() {
let foo = Foo { foo: &|a| a + 1 };
(foo.foo)(42);
(Foo::new(&|a| a + 1).foo)(42);
}
Function pointer
struct Foo {
pub foo: fn(usize) -> usize,
}
impl Foo {
fn new(foo: fn(usize) -> usize) -> Self {
Self { foo }
}
}
fn main() {
let foo = Foo { foo: |a| a + 1 };
(foo.foo)(42);
(Foo::new(|a| a + 1).foo)(42);
}
what's the type of a Foo object I create?
It's an unnameable, automatically generated type.
I could also use a reference [...] slower because [...] the pointer deref [...] no specialization
Perhaps, but it can be much easier on the caller.
See also:
How do I call a function through a member variable?
Returning a closure from a function
How to return an anonymous type from a trait method without using Box?
Closures as a type in a Rust struct
Types of unboxed closures being unique to each
Why does passing a closure to function which accepts a function pointer not work?
What does "dyn" mean in a type?
For what type you'd use in your third code snippet, there isn't one; closure types are anonymous and cannot be directly named. Instead, you'd write:
let foo = Foo { foo: |x| x + 1 };
If you're writing code in a context where you need to specify that you want a Foo, you'd write:
let foo: Foo<_> = Foo { foo: |x| x + 1 };
The _ tells the type system to infer the actual generic type for you.
The general rule of thumb as to which to use, in descending order:
Generic parameters: struct Foo<F: FnMut(usize) -> usize>. This is the most efficient, but it does mean that a specific Foo instance can only ever store one closure, since every closure has a different concrete type.
Trait references: &'a mut dyn FnMut(usize) -> usize. There's a pointer indirection, but now you can store a reference to any closure that has a compatible call signature.
Boxed closures: Box<dyn FnMut(usize) -> usize>. This involves allocating the closure on the heap, but you don't have to worry about lifetimes. As with a reference, you can store any closure with a compatible signature.
Before Rust 1.0
Closures that used the || syntax were references to closures stored on the stack, making them equivalent to &'a mut FnMut(usize) -> usize. Old-style procs were heap-allocated and were equivalent to Box<dyn FnOnce(usize) -> usize> (you can only call a proc once).

Implementing Rust traits cause struct to not be found

When I implement a trait on a struct in Rust it's causing the struct type not to be found. First, the working code:
trait SomeTrait {
fn new() -> Box<SomeTrait>;
fn get_some_value(&self) -> int;
}
struct SomeStruct {
value: int
}
impl SomeStruct {
fn new() -> Box<SomeStruct> {
return box SomeStruct { value: 3 };
}
fn get_some_value(&self) -> int {
return self.value;
}
}
fn main() {
let obj = SomeStruct::new();
println!("{}", obj.get_some_value());
}
Here the SomeTrait trait isn't being used. Everything works. If I now change the impl of SomeStruct to implement SomeTrait:
trait SomeTrait {
fn new() -> Box<SomeTrait>;
fn get_some_value(&self) -> int;
}
struct SomeStruct {
value: int
}
impl SomeTrait for SomeStruct {
fn new() -> Box<SomeTrait> {
return box SomeStruct { value: 3 };
}
fn get_some_value(&self) -> int {
return self.value;
}
}
fn main() {
let obj = SomeStruct::new();
println!("{}", obj.get_some_value());
}
I get the error:
trait.rs:21:13: 21:28 error: failed to resolve. Use of undeclared module `SomeStruct`
trait.rs:21 let obj = SomeStruct::new();
^~~~~~~~~~~~~~~
trait.rs:21:13: 21:28 error: unresolved name `SomeStruct::new`.
trait.rs:21 let obj = SomeStruct::new();
What am I doing wrong? Why is SomeStruct suddenly missing? Thanks!
At the moment, associated functions (non-method functions) in traits are called via the trait, i.e. SomeTrait::new(). However, if you just write this, the compiler cannot work out which impl you're using, as there's no way to specify the SomeStruct information (it only works if the special Self type is mentioned in the signature somewhere). That is, the compiler needs to be able to work out which version of new should be called. (And this is required; they could have very different behaviour:
struct Foo;
impl SomeTrait for Foo {
fn new() -> Box<SomeTrait> { box Foo as Box<SomeTrait> }
}
struct Bar;
impl SomeTrait for Bar {
fn new() -> Box<SomeTrait> {
println!("hello")
box Bar as Box<SomeTrait>
}
}
Or something more dramatic than just printing.)
This is a language hole that will be filled by UFCS. For the moment, you need to use the dummy-Self trick:
trait SomeTrait {
fn new(_dummy: Option<Self>) -> Box<SomeTrait>;
...
}
which is then called like SomeTrait::new(None::<SomeStruct>).
However, I question why you are returning a boxed object from a constructor. This is rarely a good idea, it's normally better to just return the plain type directly, and the user can box it if necessary, that is,
trait SomeTrait {
fn new() -> Self;
...
}
(NB. this signature mentions Self and thus the Option trick above isn't required.)
Sidenote: the error message is rather bad, but it just reflects how these methods are implemented; an associated function in an impl Foo is very similar to writing mod Foo { fn ... }. You can see it differ by forcing the compiler to create that module:
struct Foo;
impl Foo {
fn bar() {}
}
fn main() {
Foo::baz();
}
prints just
<anon>:7:5: 7:13 error: unresolved name `Foo::baz`.
<anon>:7 Foo::baz();
^~~~~~~~
i.e. the Foo "module" exists.

Resources