rusttraits

How do I stub out an impl Trait-returning function?


If I have a function that I haven't yet had time to implement while I'm working on its higher-leve callers, I can stub it out with a panic:

fn foo() -> u64 {
  panic!("TODO");
}

However, if I want to do the same for something that returns a future without a concrete result type, it doesn't work, providing a rather surprising error:

// error[E0277]: `!` is not a future
fn foo() -> impl Future {
  panic!("TODO");
}

Is there any easy way to stub out a function like this?


Solution

  • Generally, the way panic!() (or similar macros, e.g. todo!()) allow you to return any type is that they return ! (the never type), which coerces to any type.

    But here the compiler doesn't have a specific type to coerce into, so if ! does not impl the trait, it won't work. Furthermore, ! can't impl every trait, even if std was to add every possible impl - think e.g. Default. We cannot return anything in default(), because the never type by definition cannot exist.

    Therefore, you need to put something extra there. If you have a type that implements the trait and can put a value of it there (e.g std::future::pending::<()>()), great; otherwise, if you have a type but not a value of it, you coerce explicitly:

    fn foo() -> impl Future {
        panic!("TODO") as std::future::Ready<()>
    }
    

    (Beware the compiler will warn you about unreachable code, you'll need to #[allow] that. This is going to change soon, hopefully).

    If you have no type, you're out of luck.