I want to keep an Holded instance, but I can't since it's in an array. How can I do to 'extract' this instance from the array and keep it in an Object instance ? (In my original code, I don't have array but iterators). Here is the equivalent code :
struct Holded {
value: u8,
}
struct Holder;
impl Holder {
pub fn get(&self) -> [Holded; 2] {
[Holded { value: 0 }, Holded { value: 1 }]
}
}
struct Object<'a> {
holded: &'a Holded,
}
fn main() {
let holder = Holder;
let obj = work(&holder).unwrap();
println!("{}", obj.holded.value);
}
fn work(holder: &Holder) -> Option<Object> {
let mut obj: Object;
let array = holder.get();
for h in array.into_iter() {
if h.value == 1u8 {
obj = Object { holded: h };
return Some(obj);
}
}
None
}
The error message:
error: `array` does not live long enough
--> src/main.rs:28:14
|
28 | for h in array.into_iter() {
| ^^^^^ does not live long enough
...
36 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the block at 24:43...
--> src/main.rs:24:44
|
24 | fn work(holder: &Holder) -> Option<Object> {
| ^
In the MCVE you have posted, the struct Object contains a reference to Holded:
struct Object<'a> {
holded: &'a Holded,
}
In the function work() you return an Object (optionally):
fn work(holder: &Holder) -> Option<Object> {
You acquire Holded from a function which returns it by value:
impl Holder {
pub fn get( &self ) -> [Holded; 2] {
[Holded { value: 0 }, Holded { value: 1 }]
}
}
Now this will never work. If you return a reference to Holded, the Holded you reference to, must be stored somewhere. This means either as an input, or as an output of the function work().
I rewrote your example to include Holded inside Holder. That is one way to solve this. But I am not sure this would apply to your original problem.
struct Holded {
value: u8,
}
struct Holder{
value: [Holded; 2],
}
impl Holder {
pub fn new() -> Holder {
Holder {value: [Holded { value: 0 }, Holded { value: 1 }] }
}
pub fn get( &self ) -> &[Holded; 2] {
&self.value
}
}
struct Object<'a> {
holded: &'a Holded,
}
fn main() {
let holder = Holder::new();
let obj = work(&holder).unwrap();
println!("{}", obj.holded.value);
let obj = work2(&holder).unwrap();
println!("{}", obj.holded.value);
}
fn work(holder: &Holder) -> Option<Object> {
let obj: Object;
let array = holder.get();
for h in array.into_iter() {
if h.value == 1u8 {
obj = Object { holded: h };
return Some(obj);
}
}
None
}
fn work2(holder: &Holder) -> Option<Object> {
holder.get()
.iter()
.filter(|h| h.value == 1u8)
.map(|h| Object { holded: h })
.next()
}
You notice I also added a different way to implement the work() function (work2()).
Related
Here's my code:
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
impl Default for AnotherThing {
fn default() -> Self {
Self {
val: 2,
}
}
}
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
Self {
val,
another: &AnotherThing::default(),
}
}
}
fn main() {
let _ = Something::new(1);
}
It doesn't compile because:
Compiling playground v0.0.1 (/playground)
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:24:9
|
24 | / Self {
25 | | val,
26 | | another: &AnotherThing::default(),
| | ----------------------- temporary value created here
27 | | }
| |_________^ returns a value referencing data owned by the current function
I understand the problem but I don't know how to fix it. If it's not possible to use the Default trait for this case, how can I deal with the function ownership. Below a simpler example:
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
let at = AnotherThing { val : 2 };
Self {
val,
another: &at,
}
}
}
fn main() {
let _ = Something::new(1);
}
If I had another: &AnotherThing { val : 2 } instead of another: &at it would work. If I want the another attribute to be a reference and get the value from a function, how can I do it?
You can do like this
#[derive(Default)]
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
impl<'a> Default for &'a AnotherThing {
fn default() -> &'a AnotherThing {
&AnotherThing {
val: 3,
}
}
}
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
Self {
val,
..Default::default()
}
}
}
Another option is to create a const item, of which you can create a reference with 'static lifetime, thus binding to any 'a:
struct Something<'a> {
val: u32,
another: &'a AnotherThing,
}
struct AnotherThing {
val: u32,
}
const ANOTHER_THING_DEFAULT: AnotherThing = AnotherThing { val: 3 };
trait Anything {
fn new(val: u32) -> Self;
}
impl Anything for Something<'_> {
fn new(val: u32) -> Self {
Self {
val,
another: &ANOTHER_THING_DEFAULT,
}
}
}
I have a function that returns a flat-mapped Vec over children of a tree:
use std::iter;
#[derive(Clone)]
struct Tree {
value: String,
children: Vec<Tree>,
}
struct NoClone;
impl NoClone {
pub fn children(&self, from: &Tree) -> Vec<Tree> {
from.children.clone()
}
pub fn descendants_vec<'a>(&'a self, from: Tree) -> Vec<Tree> {
let children = self.children(&from);
iter::once(from)
.chain(children.into_iter().flat_map(|child| self.descendants_vec(child)))
.collect::<Vec<Tree>>()
}
pub fn descendants_iter<'a>(&'a self, from: Tree) -> Box<Iterator<Item = Tree> + 'a> {
let children = self.children(&from);
Box::new(iter::once(from)
.chain(children.into_iter().flat_map(move |child| {
self.descendants_iter(child)
})))
}
}
fn main() {
//println!("Flattened (Iter): {:?}", mapped_iter());
println!("Flattened (Vec): {:?}", mapped_vec());
}
fn tree() -> Tree {
let tree_a = Tree {
value: "a".to_owned(),
children: Vec::new(),
};
let tree_b = Tree {
value: "b".to_owned(),
children: Vec::new(),
};
let tree_c = Tree {
value: "c".to_owned(),
children: Vec::new(),
};
Tree {
value: "abc".to_owned(),
children: vec![tree_a, tree_b, tree_c],
}
}
/*fn mapped_iter() -> Vec<String> {
let tree = tree();
let no_clone = NoClone;
no_clone.descendants_iter(tree).map(|x| x.value).collect::<Vec<String>>()
}*/
fn mapped_vec() -> Vec<String> {
let tree = tree();
let no_clone = NoClone;
no_clone.descendants_vec(tree)
.into_iter()
.map(|x| x.value)
.collect::<Vec<String>>()
}
I would like to avoid the intermediate collect/iter and use descendants_iter which returns an Iterator (boxed until we get impl traits).
However, uncommenting the blocks calling this function causes the compiler to complain with the following error:
error: `no_clone` does not live long enough
--> <anon>:63:1
|
62 | no_clone.descendants_iter(tree).map(|x| x.value).collect::<Vec<String>>()
| -------- borrow occurs here
63 | }
| ^ `no_clone` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
error: aborting due to previous error
Any ideas about how to use the descendants_iter function?
I'm wrapping a C library, and it has a standard sort of context object:
library_context* context = library_create_context();
And then using that you can create more objects:
library_object* object = library_create_object(context);
And destroy them both:
library_destroy_object(object);
library_destroy_context(context);
So I've wrapped this up in Rust structs:
struct Context {
raw_context: *mut library_context,
}
impl Context {
fn new() -> Context {
Context {
raw_context: unsafe { library_create_context() },
}
}
fn create_object(&mut self) -> Object {
Object {
raw_object: unsafe { library_create_object(self.raw_context) },
}
}
}
impl Drop for Context {
fn drop(&mut self) {
unsafe {
library_context_destroy(self.raw_context);
}
}
}
struct Object {
raw_object: *mut library_object,
}
impl Drop for Object {
fn drop(&mut self) {
unsafe {
library_object_destroy(self.raw_object);
}
}
}
So now I can do this, and it seems to work:
fn main() {
let mut ctx = Context::new();
let ob = ctx.create_object();
}
However, I can also do this:
fn main() {
let mut ctx = Context::new();
let ob = ctx.create_object();
drop(ctx);
do_something_with(ob);
}
I.e. the library context is destroyed before the objects it creates are.
Can I somehow use Rust's lifetime system to prevent the above code from compiling?
Yes, just use normal lifetimes:
#[derive(Debug)]
struct Context(u8);
impl Context {
fn new() -> Context {
Context(0)
}
fn create_object(&mut self) -> Object {
Object {
context: self,
raw_object: 1,
}
}
}
#[derive(Debug)]
struct Object<'a> {
context: &'a Context,
raw_object: u8,
}
fn main() {
let mut ctx = Context::new();
let ob = ctx.create_object();
drop(ctx);
println!("{:?}", ob);
}
This will fail with
error[E0505]: cannot move out of `ctx` because it is borrowed
--> src/main.rs:26:10
|
25 | let ob = ctx.create_object();
| --- borrow of `ctx` occurs here
26 | drop(ctx);
| ^^^ move out of `ctx` occurs here
Sometimes people like to use PhantomData, but I'm not sure I see the benefit here:
fn create_object(&mut self) -> Object {
Object {
marker: PhantomData,
raw_object: 1,
}
}
#[derive(Debug)]
struct Object<'a> {
marker: PhantomData<&'a ()>,
raw_object: u8,
}
I want to expose a public function with immutable self which calls a private function with mutable self.
struct Foo {
value: i32,
}
impl Foo {
fn f1(&self) {
self.f2(); // <--- is it possible to make self mutable?
}
fn f2(&mut self) {
self.value = 5;
}
}
fn main() {
let foo = Foo { value: 0 };
foo.f1();
}
When compiling this code I get an error
cannot borrow immutable borrowed content *self as mutable
Is it possible to make self mutable?
EDIT:
After missing that last sentence.. you could get away with wrapping the property in a Cell:
use std::cell::Cell;
struct Foo { value: Cell<i32> }
impl Foo {
fn f1(&self) {
self.f2();
}
fn f2(&self) {
self.value.set(5);
}
}
fn main() {
let foo = Foo { value: Cell::new(0) };
foo.f1();
println!("{:?}", foo.value.get()); // prints 5
}
What you want cannot be done: you cannot convert a non-mutable reference into a mutable one.
But you can get almost that with RefCell:
struct Foo { value: RefCell<i32> }
impl Foo {
fn f1(&self) {
let mutValue = self.value.borrow_mut();
*mutValue = 5;
}
}
I didn't even need the f2 function!
I have an enum with multiple single field tuple struct variants. Each tuple struct field is a different struct. I tried this code:
struct Foo { a: i32 }
struct Bar { b: i32 }
enum Foobar {
Foo(Foo),
Bar(Bar)
}
impl Foobar {
fn new_foo() -> Foobar {
Foobar::Foo(Foo { a: 1 })
}
fn new_bar() -> Foobar {
Foobar::Bar(Bar { b: 2 })
}
}
fn main() {
let x = vec![Foobar::new_foo(), Foobar::new_bar()];
let mut i = 0;
while i < x.len() {
let element = &x[i];
match element {
&Foobar::Foo(_) => { x[i].a = 3 },
&Foobar::Bar(_) => { x[i].b = 4 }
}
i += 1
}
}
The compiler says:
error: attempted access of field a on type Foobar, but no field with that name was found
I tried the solution found in this question but it says:
error: cannot borrow immutable anonymous field as mutable
How can I modify the fields of the content of vector x?
This is because your vector and the reference element are immutable. Try this:
fn main() {
let mut x = vec![Foobar::new_foo(), Foobar::new_bar()];
let mut i = 0;
while i < x.len() {
let element = &mut x[i];
match *element {
Foobar::Foo(Foo { ref mut a }) => { *a = 3 },
Foobar::Bar(Bar { ref mut b }) => { *b = 4 }
}
i += 1
}
}