Lifetime issue with structs contained Rc<RefCell<T>>

Hi All,

This is simplified version of code I am working on:

use std::cell::RefCell;
use std::rc::Rc;

struct Inner<'a> {
    pub val: u32,
    pub callback: Box<dyn FnMut(u32) + 'a>


struct A<'a> {
    inner: Rc<RefCell<Inner<'a>>>,

impl<'a> A<'a> {
    pub fn new<F: 'a>(val: u32, callback: F) -> A<'a>
        where F: FnMut(u32) 
        A{inner: Rc::new(RefCell::new(Inner{val, callback: Box::new(callback)})),}
    pub fn create<'b>(&'a self) -> B<'b> {
        B{inner: self.inner.clone()}

struct B<'b> {
    inner: Rc<RefCell<Inner<'b>>>,

fn main() {

    let val: u32 = 128;

    let obj = A::new(0xaa, |v: u32| { println!("--> v {}, val {}", v, val)});
    let h = obj.create();
    //let b = B{inner: obj.inner.clone()}; // works
    println!("--> {:?}",h.inner.borrow().val);

This is the playground

The problem is with 'create' function: "cannot infer an appropriate lifetime for lifetime parameter 'b due to conflicting requirements".

Lifetime of B should be less than A, so I have tried to do something like this:

    pub fn create<'b>(&'a self) -> B<'b>
    where 'a: 'b
        B{inner: self.inner.clone()}

But this did not help.

Can anybody explain what lifetime configuration should be for 'create' function?

Thank you in advance.

The only lifetimes that will compile are:

pub fn borrow(&self) -> B<'a> {
    B{inner: self.inner.clone()}

It should be same. If not you can overwrite the Box<dyn FnMut(u32) + 'a> in-place with the value with shorter lifetime which allows dangling reference access.

That's work. Thank you.

Yeah, good point. Indeed the lifetime A and B should be the same. It can be less than A only if 'callback' field in Inner is immutable. It is not needed, but just to learn new: is it possible to make one field in structure immutable?

Thank you.

Instead of to coarsely wrap the entire struct with RefCell, you can wrap each fields with it and share the Rc<Inner> for the fine-grained control.

I got it. Thank you.

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.