Rustc E0277: alternative better way to a self reference suggestion

I have the following code (simplified)

let store = store::InMemory::default();
let repository = Repository::from(store.clone());
let service = Service::from(repository);

I thought to reduce this to

let service = Service::new();

where

#[derive(Clone)]
pub struct Service<R>
where
    R: Repository<A, B>,
{
    repository: R,
}

impl<R> Service<R>
where
    R: Repository<A, B>,
{
    fn new() -> Self {
        let store = store::InMemory::default();
        let repository = Repository::from(store.clone());
        let service = Self::from(repository);
        service
    }
}
impl<R> From<R> for Service<R>
where
    R: Repository<A, B>,
{
    fn from(repository: R) -> Self {
        Self {
            repository,
        }
    }
}

It appears the source of the error is using Self:from(..) inside new().
I've obviously forgotten something fundamental/simple, because the compiler error suggests this:

error[E0277]: the trait bound `Service<R>: std::convert::From<Repository<A, B, InMemory<String, C>>>` is not satisfied
  --> src/application.rs:43:27
   |
43 |         let application = Self::from(repository);
   |                           ^^^^^^^^^^ the trait `std::convert::From<EventSourced<A, B, InMemory<String, C>>>` is not implemented for `Service<R>`
   |
help: consider extending the `where` bound, but there might be an alternative better way to express this requirement
   |
37 |     R: aggregate::Repository<A, B>, Service<R>: std::convert::From<EventSourced<A, B, InMemory<String, C>>>
   |                                                           
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0277`.

If I understand the suggestion correctly, it is to add a self referring trait bound (which fails):

impl<R> From<R> for Service<R>
where
    R: Repository<A, B>,
    Service<R>: std::convert::From<EventSourced<A, B, InMemory<String, C>>>                                                
{
    fn from(repository: R) -> Self {
        Self {
            repository,
        }
    }
}

So I'm wondering what have I missed and what are the alternative better ways?
The E02077 did not really help me so I'm likely over thinking what is wrong.

Appreciate any tips.

A more complete / self-contained code example would help. Where and how is Repository defined, and in particular what's the signature of Repository::from? Also it's not 100% clear to me if the original code that you're trying to reduce does actually work or not. A fully working (toy) example that demonstrates the original code working and reproduces the errors you got would clear up any such question.


In any case, judging by the error message, it seems like maybe what you need is to make this an

impl Service<EventSourced<A, B, InMemory<String, C>>> {
    fn new() -> Self { /* ... */ }
}

and the generic signature is just wrong, because the thing ought to produce values with only one concrete type in place of R.

Point taken. Thanks for your suggestion - if that doesn't fix things I'll try to get a MRE - the code isn't simple and uses crates not in the playground so it'll take a while if it is possible to distill.

Yes, if I remove fn new() {...} all proceeds fine.

Thanks I'll try that!

Unfortunately EventSource is a struct so I can't redefine the trait bound....

Not sure of the etiquette on pointing to examples in other's crates, but I really don't think I can distill things further.... the example in question is here:

The three lines of code I'm exploring refactoring into Service::new() are here (these trigger the compiler error E0277 when placed in the new()):

And the Service definition is here:

Appreciate any help.

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.