How can I write this in stable (or even unstable) Rust?
pub trait Queryable<B, D> {
fn query<'a, Q: Query<B> + 'a>(&'a self, query: Q) -> impl Iterator<Item = (ID, &'a D)> + 'a;
}
- If
impl Trait
in traits existed then this would just work.
- If GAT existed then an associated type would work.
- HRTB almost works, but it then I can't get the Iterator type to depend on the query type.
I'm always very cautious around lifetime parameters on traits, but maybe this is a case where it's necessary? FWIW, this compiles:
use std::collections::HashMap;
pub trait Query {}
#[derive(PartialEq, Eq, Hash)]
pub struct ID;
pub trait Queryable<'a, D: 'a> {
type QueryIter: 'a + Iterator<Item = (&'a ID, &'a D)>;
fn query<Q: Query + 'a>(&'a self, query: Q) -> Self::QueryIter;
}
impl<'a, D: 'a> Queryable<'a, D> for HashMap<ID, D> {
type QueryIter = std::collections::hash_map::Iter<'a, ID, D>;
fn query<Q: Query + 'a>(&'a self, query: Q) -> Self::QueryIter {
self.iter()
}
}
(Playground link)
Perhaps not how you wanted it to look, but instead you might be able to box it up?
Playground
Yeah, I'm boxing it for now and it works.
@troiganto: That almost works, except where you want the type QueryIter to depend on the type Q (which is very common), in which case you need GATs.
2 Likes