Type option needed intoiterator of other type

Hello, I'm facing an issue with None and the IntoIterator of another type.

struct MyStruct {}

fn test<I, T>(iter: I)
    I: IntoIterator<Item = T>,
    T: Into<MyStruct>,

fn main() {
    test(vec![MyStruct {}, MyStruct {}]);
    test(None); // Error !

Playground: Rust Playground.

The previous code give the following error:

error[E0283]: type annotations needed
  --> src/main.rs:13:5
3  | fn test<I, T>(iter: I)
   |    ---- required by a bound in this
6  |     T: Into<MyStruct>,
   |        -------------- required by this bound in `test`
13 |     test(None);
   |     ^^^^ cannot infer type for type parameter `T` declared on the function `test`
   = note: cannot satisfy `_: Into<MyStruct>`
help: consider specifying the type arguments in the function call
13 |     test::<I, T>(None);
   |         ^^^^^^^^

Which I understand, I must type the option since Rust can't infer the appropriate type, so doing the following: test(Option::<MyStruct>::None) works. Playground fixed: Rust Playground.

But for the sake of simplicity I would like the user of my API to only write None. Is it possible?

Thanks for the help.

I don't think this is possible - Rust doesn't support type inference defaults. Here are a few workarounds:

  • Take an IntoIterator<Item = MyStruct>, which would place more limitations for the non-empty case, but it would allow None to compile.
  • Don't change the function, but write None::<MyStruct> instead of Option::<MyStruct>::None.
  • Provide a separate function test_empty or something along those lines that internally calls test(iter::empty::<MyStruct>()).
1 Like

yet another alternatice

  • provide a const NO_STRUCT: Option<MyStruct> = None so that users can write test(NO_STRUCT).

Edit: Even better:

const NO_STRUCT: std::iter::Empty<MyStruct> = std::iter::empty();

This allows for nice optimizations since the compiler will know that .next() on the iterator type always returns None, and the iterator is zero-sized, etc..