Implementation of trait not general enough

I have been trying to let an implementation of Manager instantiate a generic that may have lifetime parameters of its' own.
This is the furthest i have gotten, hopefully you can see what i am going for.

use std::marker::PhantomData;

pub trait Manager {
    fn update(&self, n: &i32, );
}

pub struct GenericManager<T> {
    __phantom_t: PhantomData<T>,
}

pub trait Data<'a> {
    fn new(n: &'a i32,) -> Self;
}

impl <T: for<'a> Data<'a>> Manager for GenericManager<T> {
    fn update(&self, n: &i32) { T::new(n); }
}

pub struct BorrowData<'a> { pub data: &'a i32 }

impl <'a, 'b: 'a> Data<'b> for BorrowData<'a> {
    fn new(n: &'b i32) -> Self { BorrowData { data: n } }
}


fn main() {
    let mut managers: Vec<Box<dyn Manager>> = vec![];
    managers.push(Box::new(GenericManager::<BorrowData> {__phantom_t: PhantomData}));
    let n = 5;
    for m in &managers {
        m.update(&n);
    }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error: implementation of `Data` is not general enough
  --> src/main.rs:28:19
   |
11 | / pub trait Data<'a> {
12 | |     fn new(n: &'a i32,) -> Self;
13 | | }
   | |_- trait `Data` defined here
...
28 |       managers.push(Box::new(GenericManager::<BorrowData> {__phantom_t: PhantomData}));
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Data` is not general enough
   |
   = note: `BorrowData<'_>` must implement `Data<'0>`, for any lifetime `'0`...
   = note: ...but `BorrowData<'_>` actually implements `Data<'1>`, for some specific lifetime `'1`

error: aborting due to previous error

error: could not compile `playground`.

To learn more, run the command again with --verbose.

It looks like you are expecting the type of the value you are boxing to be inferred as something like for<'a> GenericManager<BorrowData<'a>> or GenericManager<for<'a> BorrowData<'a>>. Neither of those is a real type though so it isn't something that inference would produce.

It should work if you stick the higher ranked type behind an associated type:

pub trait WithData<'a> {
    type Data: Data<'a>;
}

struct WithBorrowData;

impl<'a> WithData<'a> for WithBorrowData {
    type Data = BorrowData<'a>;
}

impl<T: for<'a> WithData<'a>> Manager for GenericManager<T> {
    fn update(&self, n: &i32) {
        T::Data::new(n);
    }
}
managers.push(Box::new(
    GenericManager::<WithBorrowData> {__phantom_t: PhantomData},
));
2 Likes

Thank you, that worked. I should probably study the type system in a bit more detail.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.