So I am currently experimenting a bit with gals and I got stuck with this piece of code which I can not get to work:
#![feature(generic_associated_types)]
use core::hash::Hash;
use core::borrow::Borrow;
use core::marker::PhantomData;
pub trait ToIter<T> {
type Iter<'b>: Iterator<Item = &'b T>
// Why must one constrain T to live for 'b?
// this is implied by &'b T !
where
T: 'b;
/// Returns an immutable iterator over the remaining items in the
/// iterator.
fn iter(&self) -> Self::Iter<'_>;
}
pub trait Set<T> {
type Iter<'a>: Iterator<Item = &'a T> where T: 'a;
fn iter(&self) -> Self::Iter<'_>;
/// Returns true if the value is in the set, false if it is not.
#[must_use]
fn contains<Q: ?Sized>(&self, value: &Q) -> bool
where
T: Borrow<Q>,
Q: Hash + Eq;
}
/// This iterator returns all elements that are in a but not in b.
/// In math one writes it as `A \ B`
pub struct Difference<'a, T, A: Set<T>, B: Set<T>>
where
T: 'a,
{
a: A::Iter<'a>,
b: &'a B,
_p: PhantomData<T>,
}
impl<'a, T: Hash + Eq, A: Set<T>, B: Set<T>> Iterator for Difference<'a, T, A, B> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
// implementation is relatively straight forward
for element in self.a.by_ref() {
if !self.b.contains(element) {
return Some(element);
}
}
None
}
}
// this is where things get confusing
// either the compiler is not smart enough or I am not smart enough to see
// the problem
impl<'a, T: Hash + Eq, A: Set<T>, B: Set<T>> ToIter<T> for Difference<'a, T, A, B>
where
A::Iter<'a>: Clone,
{
type Iter<'b>
where
T: 'b,
B: 'b,
A: 'b,
= Difference<'b, T, A, B>;
fn iter(&self) -> Self::Iter<'_> {
Difference {
a: self.a.clone(),
b: self.b,
_p: PhantomData,
}
}
}
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:90:9
|
90 | Difference {
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 89:13...
--> src/main.rs:89:13
|
89 | fn iter(&self) -> Difference<'_, T, A, B> {
| ^^^^^
note: ...so that the types are compatible
--> src/main.rs:90:9
|
90 | / Difference {
91 | | a: self.a.clone(),
92 | | b: self.b,
93 | | _p: PhantomData,
94 | | }
| |_________^
= note: expected `Difference<'_, _, _, _>`
found `Difference<'_, _, _, _>`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 85:6...
--> src/main.rs:85:6
|
85 | impl<'a, T: Hash + Eq, A: Set<T>, B: Set<T>> Difference<'a, T, A, B>
| ^^
note: ...so that the expression is assignable
--> src/main.rs:91:16
|
91 | a: self.a.clone(),
| ^^^^^^^^^^^^^^
= note: expected `<A as Set<T>>::Iter<'_>`
found `<A as Set<T>>::Iter<'a>`
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground` due to previous error
It seems like the A::Iter<'a>: Clone
is the problem, because it creates a copy with the same lifetime and not with the lifetime of 'b
, but how can this be solved?