Hi everyone, as below code, I try to use generic_associated_types
and type_alias_impl_trait
features together to define a trait, it returns a Future
which returns a lifetime bound Iterator
. The version A is my original approach, then I found the weird thing: I have to define a useless lifetime parameter 'future
in the definition of FutureIterator::Future
, if I try to remove this parameter in Version B, I got a hidden type capturing error. I think: great, maybe type_alias_impl_trait
helped me handled the 'future
parameter implicitly in Version A. However, when I try to define the type of FutureIterator::Future
explicitly with 'future
, I got the big problem: I can not define a valid type of it as impl trait
does (such as Version C). The final effect that impl trait
does seems like HRTB
over GAT
: whatever 'future
is, if it is valid in method get_iter
then it works, but I can not manually use HRTB
over GAT
, or if my thoughts are wrong, what is the explicitly version of the imply trait
does? Hope for anyone's help, thanks.
Version A:
#![feature(generic_associated_types)]
#![feature(type_alias_impl_trait)]
use std::future::Future;
trait FutureIterator: 'static {
type Iterator<'iter>: Iterator<Item = ()>;
type Future<'iter, 'future>: Future<Output = Self::Iterator<'iter>>;
fn get_iter<'iter, 'future>(&'iter self, arg: &'future ()) -> Self::Future<'iter, 'future>;
}
struct It<'s> {
_inner: &'s FutIt,
}
impl Iterator for It<'_> {
type Item = ();
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
struct FutIt {}
impl FutureIterator for FutIt {
type Iterator<'iter> = It<'iter>;
type Future<'iter, 'future> = impl Future<Output = Self::Iterator<'iter>>;
fn get_iter<'iter, 'future>(&'iter self, arg: &'future ()) -> Self::Future<'iter, 'future> {
async move {
let _ = &arg;
It { _inner: self }
}
}
}
fn main() {}
Version B:
#![feature(generic_associated_types)]
#![feature(type_alias_impl_trait)]
use std::future::Future;
trait FutureIterator: 'static {
type Iterator<'iter>: Iterator<Item = ()>;
type Future<'iter>: Future<Output = Self::Iterator<'iter>>;
fn get_iter<'iter>(&'iter self, arg: &()) -> Self::Future<'iter>;
}
struct It<'s> {
_inner: &'s FutIt,
}
impl Iterator for It<'_> {
type Item = ();
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
struct FutIt {}
impl FutureIterator for FutIt {
type Iterator<'iter> = It<'iter>;
type Future<'iter> = impl Future<Output = Self::Iterator<'iter>>;
fn get_iter<'iter>(&'iter self, arg: &()) -> Self::Future<'iter> {
async move {
let _ = &arg;
It { _inner: self }
}
}
}
fn main() {}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0700]: hidden type for `<FutIt as FutureIterator>::Future<'iter>` captures lifetime that does not appear in bounds
--> src/main.rs:33:9
|
32 | fn get_iter<'iter>(&'iter self, arg: &()) -> Self::Future<'iter> {
| --- hidden type `impl Future<Output = It<'iter>>` captures the anonymous lifetime defined here
33 | / async move {
34 | | let _ = &arg;
35 | | It { _inner: self }
36 | | }
| |_________^
For more information about this error, try `rustc --explain E0700`.
error: could not compile `playground` due to previous error
Version C:
#![feature(generic_associated_types)]
#![feature(type_alias_impl_trait)]
use std::future::Future;
trait FutureIterator: 'static {
type Iterator<'iter>: Iterator<Item = ()>;
type Future<'iter, 'future>: Future<Output = Self::Iterator<'iter>> + 'future;
fn get_iter<'iter, 'future>(&'iter self, arg: &'future ()) -> Self::Future<'iter, 'future>;
}
struct It<'s> {
_inner: &'s FutIt,
}
impl Iterator for It<'_> {
type Item = ();
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
struct FutIt {}
impl FutureIterator for FutIt {
type Iterator<'iter> = It<'iter>;
type Future<'iter, 'future> = impl Future<Output = Self::Iterator<'iter>> + 'future;
fn get_iter<'iter, 'future>(&'iter self, arg: &'future ()) -> Self::Future<'iter, 'future> {
async move {
print!("{:?}", &arg);
It { _inner: self }
}
}
}
fn main() {}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0477]: the type `<FutIt as FutureIterator>::Future<'iter, 'future>` does not fulfill the required lifetime
--> src/main.rs:30:35
|
30 | type Future<'iter, 'future> = impl Future<Output = Self::Iterator<'iter>> + 'future;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: type must outlive the lifetime `'future` as defined here as required by this binding
--> src/main.rs:30:24
|
30 | type Future<'iter, 'future> = impl Future<Output = Self::Iterator<'iter>> + 'future;
| ^^^^^^^
error: lifetime may not live long enough
--> src/main.rs:33:9
|
32 | fn get_iter<'iter, 'future>(&'iter self, arg: &'future ()) -> Self::Future<'iter, 'future> {
| ----- ------- lifetime `'future` defined here
| |
| lifetime `'iter` defined here
33 | / async move {
34 | | print!("{:?}", &arg);
35 | | It { _inner: self }
36 | | }
| |_________^ associated function was supposed to return data with lifetime `'future` but it is returning data with lifetime `'iter`
|
= help: consider adding the following bound: `'iter: 'future`
For more information about this error, try `rustc --explain E0477`.
error: could not compile `playground` due to 2 previous errors