0

I'm implementing a web service using tonic grpc crate. Here is the my code:

use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use std::sync::Mutex;


fn main() {
    let my_struct = MyStruct {data_ref: RefCell::new(None), data: vec![MyData(28)]};
    my_struct.my_fun();
    // my_struct.my_fun_is_gone(); This is not working.
    println!("{}", my_struct.data_ref.borrow().deref().unwrap().0);
}

/// AUTO GENERATED CODE OR THIRD PARTY TRAITS
///for example tonic generated Grpc services
trait TonicGeneratedGrpcService {
    fn my_fun_is_gone(&self); //so I Can't change the &self lifetime parameter
}

struct MyData(u8);
struct MyStruct<'a> {
    data: Vec<MyData>, //this struct is owns this property, there is no any problem
    data_ref: RefCell<Option<&'a MyData>>, //And sometimes I want to save the data
}

impl<'a> TonicGeneratedGrpcService for MyStruct<'a> {
    fn my_fun_is_gone(&self) { //I can't change the &self lifetime parameter because this is just an implementation of some super traits, change the lifetime parameters also requires change the super trait's method's lifetime.

//***********COMPILER ERROR is occurred HERE, how can I make this working?*************
        let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
        *self.data_ref.borrow_mut() = Some(some_of_data);
    }
}

impl<'a> MyStruct<'a> {
    //Below code is works fine if this is myself defined method, but I can't change the lifetime of "self" in super traits if this is a implementation of tonic generated service or other third party traits
    fn my_fun(&'a self) {
        let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
        *self.data_ref.borrow_mut() = Some(some_of_data);
    }
}

My final purpose is save the reference that one of the Vec<MyData> into data_ref field at runtime by some conditions.

Here is the compiler error:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:28:29
   |
28 |         let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
   |                             ^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
  --> src/main.rs:26:23
   |
26 |     fn my_fun_is_gone(&self) { //I can't change the &self lifetime parameter because this is just an implementation of some super traits,...
   |                       ^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:28:29
   |
28 |         let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
   |                             ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
  --> src/main.rs:25:6
   |
25 | impl<'a> TonicGeneratedGrpcService for MyStruct<'a> {
   |      ^^
note: ...so that the expression is assignable
  --> src/main.rs:29:39
   |
29 |         *self.data_ref.borrow_mut() = Some(some_of_data);
   |                                       ^^^^^^^^^^^^^^^^^^
   = note: expected `Option<&'a MyData>`
              found `Option<&MyData>`

I can't change the source code of TonicGeneratedGrpcService trait because it may be in the third party crate or auto generated code, and now I cannot find any way to make work the my_fun_is_gone method implementation.

Should I avoid the lifetime and use reference counted pointers (Rc, Arc) rather then save reference (&MyData) directly in struct MyStruct? Or there any way to make work this?

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
Ug-Projekt
  • 19
  • 2
  • 1
    Have you read [Why can't I store a value and a reference to that value in the same struct?](/q/32300132/2189130) – kmdreko Jul 18 '22 at 03:07
  • Does this answer your question? [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct) – Jmb Jul 18 '22 at 07:03

1 Answers1

0

As others said, Rust's lifetime system doesn't allow self-referential struct.

To solve this, you may directly store the index integer in the data_ref if data vec is only appended. Depending on your use case, you can also consider other options here Why can't I store a value and a reference to that value in the same struct?

Steve Z
  • 300
  • 2
  • 10