I'm trying to implement a factory method that returns a Service
with an associated type. I got it to work without the associated type, but once I add that, I can't get it to compile regardless of how I massage it..
This is the Service
:
trait QType {}
trait Service {
type Query: QType;
fn sanitize(&self, query: &str) -> Result<Self::Query, String>;
fn run(&self, query: &Self::Query) -> Result<(), String>;
}
So the idea is that the sanitize
function returns an instance of the Query
, which can then be passed to the run
function.
The factory looks like this (doesn't compile):
fn factory<Q: QType>(name: &str) -> Box<dyn Service<Query = Q>> {
match name {
"amazon" => Box::new(amzn::Amazon {}),
other => panic!("Invalid service {}", other),
}
}
Now I only have one service here and I could be specific in the type Parameters in the signature -- which would make it compile -- but I want to have a generic factory method and add more services.
Here's the implementation of the Amazon
service:
mod amzn {
use super::*;
pub struct Amazon {}
pub struct Product {
name: String,
}
impl QType for Product {}
impl Service for Amazon {
type Query = Product;
fn sanitize(&self, query: &str) -> Result<Product, String> {}
fn run(&self, query: &Product) -> Result<(), String> {}
}
}
The compiler says:
error[E0271]: type mismatch resolving `::Query == Q` --> src/main.rs:9:21 | 9 | "amazon" => Box::new(amzn::Amazon {}), | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found struct `amzn::Product` | = note: expected type `Q` found type `amzn::Product` = help: type parameters must be constrained to match other types = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters = note: required for the cast to the object type `dyn Service`
Based on this error message, I 'm not sure how to specify the type parameter. I have tried extracting the creation of Amazon
and giving it explicit type parameters, but that just leaves to different errors. Also, following the linked chapter 10.02 in the book doesn't give any explanations on the case with associated types. Lastly, I also tried the route of RFC-1598: Generic Associated Types, but I could neither get it to compile nor am I sure whether I really need that.
Also please note that I added the Box
wrapper and QType
restriction based on other answers here on SO around similar issues, but I could very be completely on the wrong path here..
Any help is much appreciated.