I guess it maybe the Self in boxed_iter(&'b self) is &'b (dyn Iterable<'a, 'b, T> + 'a), but &'b (dyn Iterable<'a, 'b, T> + 'a) is not a Iterable.
And method calls will try receiver as the Self at first, then the calling will have the form of Iterable::boxed_iter(&'b (dyn Iterable<'a, 'b, T> + 'a)), will fit the signature of boxed_iter well.
But if this is what is happening, why the code is refued?
Given 'a: 'b, 'b, T: ?Sized + 'a, can dyn Iterable<'a, 'b, T> + 'a implement Iterable<'a, 'b, T> ?
trait Iterable<'a: 'b, 'b, T: ?Sized>: 'a
'a: 'b?
dyn Iterable<'a, 'b, T> + 'a: 'a?
'a: 'a?
T: 'a?
'b: 'a?
Remove the 'a bound from the trait and it compiles. (The entire lifetime 'a isn't doing anything useful in your playground, so better yet, remove it entirely.)
Why are you trying to introduce two lifetimes for one (covariant) thing? You are, once again, catastrophically overcomplicating it. You don't even need a single explicit lifetime for the trait definition, everything can be elided.
I don't see the problem, Quinedot's solution is basically the same as the one I just posted. Due to covariance, it compiles and runs even with the owned-boxed argument.
Point is, if you remove the useless lifetime annotations, and let the compiler infer most of it, then all of what you want compiles and runs correctly.
I felt I already wrote too much over there, so I didn't follow up, but FYI in case you keep playing with it -- ah I see perhaps you don't want spoilers too.
Click to reveal.
IIRC a key part of avoiding HRTB sadness is to avoid introducing a type variable...
// OP
// v
impl<'a, I: 'a + ?Sized, T: Borrow<O> + 'a + ?Sized, O: ?Sized> Iterable<'a, O> for I
where
&'a I: IntoIterator<Item = &'a T>,
// My long explanation
// vvvv
impl<Iter: ?Sized, Item: ?Sized, Temp: ?Sized> Iterable<Item> for Iter
where
for<'any> &'any Iter: IntoIterator<Item = &'any Temp>>,
Temp: Borrow<Item>,
If I modify the code by adding explicit bound to Iterable, then I have to add it to the other place.
However, I added it to the most basic definition so that rustc knows about this bound, thereby letting it know about this constraint, to avoid having to write it again in other places.
trait Iterable<'b, U: 'b + ?Sized> {
// ^ ----------------- add this
fn boxed_iter<'d>(&'d self) -> Box<dyn Iterator<Item = &'d U> + 'd>
where
'b: 'd;
}
impl<'b, I: ?Sized, T: Borrow<O> + 'b + ?Sized, O: 'b + ?Sized> Iterable<'b, O> for I
// ^ ------ then I have to add this
where
for<'c> &'c I: IntoIterator<Item = &'c T>,
{
fn boxed_iter<'d>(&'d self) -> Box<dyn Iterator<Item = &'d O> + 'd>
where
'b: 'd,
{
Box::new(self.into_iter().map(Borrow::borrow))
}
}
There's some tricks like mentioning &'d &'c () that makes 'c: 'd implicit, but it can be tricky or limiting to work that in underneath the binder. We don't have explicit conditional binders so far.
It's nicer than mine in the sense that you didn't need a helper trait and it still solved the "borrow forever", run_owned issue. It's not fully HRTB-friendly (uncomment check_hr to see the error), but it's flexible enough that it probably doesn't need to be. The lifetime parameter is invariant which could cause some problems, but that's probably extremely niche too.
You should should post it as an alternative in the other thread.