|
|
Subscribe / Log in / New account

Rust syntax is only getting worse

Rust syntax is only getting worse

Posted Sep 27, 2025 18:10 UTC (Sat) by NYKevin (subscriber, #129325)
In reply to: Rust syntax is only getting worse by geofft
Parent article: Canceling asynchronous Rust

Re composition with Result: Honestly, I think this concern is exaggerated. Option and Result each provide conversion methods into the other, and it would not be unreasonably difficult to do the same with a custom enum. Once you have a conversion method, composition is straightforward enough.

As for general flexibility, this seems like a place where Rust's return-type dispatch might be useful. Here's how it might be spelled:

use std::convert::Infallible; // TODO: Replace with ! when it is stabilized in some future version of Rust.
use std::time::Duration;
use tokio::time::error::Elapsed;

pub enum Timeout<V, E>{
    Ok(V),
    Err(E),
    Timeout(Elapsed),
}

// const wrap needed so that Result<V, Infallible> and V don't
// have overlapping impls. Ugly hack, but it should work.
pub trait IntoTimeout<V, E, const wrap: bool>{
    fn into_timeout(self) -> Timeout<V, E>;
}

impl<V, E> IntoTimeout<V, E, false> for Result<V, E>{
    fn into_timeout(self) -> Timeout<V, E>{
        match self {
            Ok(v) => Timeout::Ok(v),
            Err(e) => Timeout::Err(e),
        }
    }
}

impl<T> IntoTimeout<T, (), false> for Option<T>{
    fn into_timeout(self) -> Timeout<T, ()>{
        match self {
            Some(t) => Timeout::Ok(t),
            None => Timeout::Err(()),
        }
    }
}

impl<T> IntoTimeout<T, Infallible, true> for T{
    fn into_timeout(self) -> Timeout<T, Infallible>{
        Timeout::Ok(self)
    }
}

pub fn timeout<F, T, V, E, const wrap: bool>(d: Duration, fut: F) -> impl Future<Output=Timeout<V, E>>
where
    F: IntoFuture<Output=T>,
    T: IntoTimeout<V, E, wrap>
{
    // Ugly hack to work around ! not implementing Future.
    // But this is just placeholder code anyway.
    std::future::ready(todo!())
}

Clients can implement IntoTimeout if they want to return some exotic thing and convert it into a timeout result. Otherwise, the impls shown above should cover all reasonable cases.

Minor caveat: The real Timeout type is itself a Future, which timeout() returns directly. I did not want to bother actually showing how to implement a Future since it is irrelevant, so I repurposed the name Timeout for the final result type and hid the Future's name behind return-position impl trait. In a proper API, it is usually preferable to give a name to the type you return rather than hiding it in this way, at least in most cases.


to post comments


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds