I'm trying to implement a chainable query execution for TOML documents.
A Query
is a thing that changes a TOML document and might return another Query
object which shall be executed after itself. A Query
which is executed gets the result of the previous query (if any).
The problem is that the return types are generic. A query might return a Vec<i64>
, but its successor might return a String
... thus, the return type of one Query
depends directly on the return type of its successor.
Here's my code so far:
extern crate either;
extern crate toml;
use either::Either;
use toml::Value;
type Result<T> = ::std::result::Result<T, ()>; // for simplicity
pub trait Query<Prev>
where
Prev: Sized,
Self: Sized,
{
type Output: Sized;
type Next: Query<Self::Output>;
fn execute(&self, target: &mut Value, prev_result: Option<Prev>) -> Result<Self::Output>;
fn next(self) -> Option<Self::Next>;
}
fn execute_query<Q, Prev>(
doc: &mut Value,
query: &Q,
prev_result: Option<Prev>,
) -> Result<Either<Q::Output, <Q::Next as Query<Q::Output>>::Output>>
where
Q: Query<Prev>,
{
let result = query.execute(doc, prev_result)?;
if let Some(next_query) = query.next() {
let next_result: <Q::Next as Query<Q::Output>>::Output =
match execute_query(doc, &next_query, Some(result)) {
Ok(Either::Left(t)) => t,
Ok(Either::Right(t)) => return Ok(Either::Right(t)), // error happens here
Err(e) => return Err(e),
};
Ok(Either::Right(next_result))
} else {
Ok(Either::Left(result))
}
}
The error is that the return type is recursive (as the whole problem is recursive):
error[E0308]: mismatched types
--> src/main.rs:37:65
|
37 | Ok(Either::Right(t)) => return Ok(Either::Right(t)), // error happens here
| ^ expected type parameter, found associated type
|
= note: expected type `<<Q as Query<Prev>>::Next as Query<<Q as Query<Prev>>::Output>>::Output`
found type `<<<Q as Query<Prev>>::Next as Query<<Q as Query<Prev>>::Output>>::Next as Query<<<Q as Query<Prev>>::Next as Query<<Q as Query<Prev>>::Output>>::Output>>::Output`
The title is not very expressive. I'm sorry about that, I don't know how to describe better.