@cafce25 thanks for pointing me in the right direction!
#![feature(type_alias_impl_trait)]
use futures::{stream::{FuturesUnordered, Next}, StreamExt};
#[tokio::main]
async fn main() {
    let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(1));
    let mut task_manager = TaskManager::new();
    loop {
        tokio::select! {
            _ = interval.tick() => {
                task_manager.push();
            },
            Some(_) = task_manager.next() => {
                // Some logic
            }
        }
    }
}
pub type TaskManagerOpaqueFuture = impl std::future::Future<Output = ()>;
struct TaskManager {
    futures: FuturesUnordered<TaskManagerOpaqueFuture>
}
impl TaskManager {
    pub fn new() -> Self {
        Self {
            futures: FuturesUnordered::new(),
        }
    }
    #[define_opaque(TaskManagerOpaqueFuture)]
    pub fn push(&self) {
        self.futures.push(async {
            // Some logic
        });
    }
    pub fn next(&mut self) -> Next<'_, FuturesUnordered<TaskManagerOpaqueFuture>> {
        self.futures.next()
    }
}