4

I'm trying to make a list that will hold Box<dyn Fn(&E)> where E is specified as part of the type. This works until E contains a reference, at which point it starts asking for lifetimes that aren't relevant.

A simpler example:

pub struct CallbackTest<E> {
    pub cb: Box<dyn Fn(&E)>,
}

impl<E> CallbackTest<E> {
    pub fn new<F>(cb: F) -> Self
    where
        F: Fn(&E)
    {
        Self { cb: Box::new(cb) }
    }
}

pub struct GameData { /* ... */ }

pub type TestRef = CallbackTest<(u32, &GameData)>;

This gives me a missing lifetime specifier error. I could put a lifetime parameter on TestRef to make it work, but that's not the correct lifetime. I don't want the &GameData to have to live for the entire lifetime of the CallbackTest, just during the function call.

EDIT: The &GameData is intentional. It's not a mistake. I hope my changes have made the goal behind this more obvious.

Any advice?

6
  • I don't know why, it does work with this way(play.rust-lang.org/…) , but i doubt it is trustworthy Commented Feb 6, 2020 at 7:53
  • 1
    Why do you want two reference ? play.rust-lang.org/… Commented Feb 6, 2020 at 8:20
  • As said by @Stargateur, I think that's due to the fact that you added mistakenly another reference layer to u32. In this situation, the compiler is right to ask for a lifetime. Commented Feb 6, 2020 at 9:55
  • The &u32 was intentional. I've changed it to be a bit more explicit that I'm trying to pass a tuple with multiple values, one of which is a reference. Commented Feb 6, 2020 at 14:36
  • I'm afraid your edits have left this sentence somewhat ambiguous: I don't want the &u32 to have to live for the entire lifetime of the CallbackTest, just during the function call. Does @ÖmerErden's suggestion work for you? Commented Feb 6, 2020 at 14:55

1 Answer 1

1

Here we are rust.playground

use std::marker::PhantomData;

pub struct CallbackTest<'a, E, Fa: 'a + Fn(&E)> {
    pub cb: Box<Fa>,
    _e: &'a PhantomData<E>,
}

impl<'a, E, Fa: 'a + Fn(&E)> CallbackTest<'a, E, Fa> {
    pub fn new(cb: Fa) -> Self
    {
        Self { 
            cb: Box::new(cb), 
            _e: &PhantomData
        }
    }
}

pub struct GameData { 
    pub field: i32,
}

pub type TestRef<'a, 'b, Fb> = CallbackTest<'b, (u32, &'a GameData, ), Fb>;

fn main() {
    let game_data = GameData{ field: 42};
    let test_ref: TestRef<_> = CallbackTest::new(|(val, gd): &(u32, &GameData)| { println!("val:{}, field:{}", val, (*gd).field)});
    (test_ref.cb)(&(24, &game_data));
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.