6

I have a function passed to and_then that returns a type not known to the compiler. When chained with other option methods, type annotations are required.

fn main() {
    let w = Some("hi".to_string());
    let x: Option<&String> = w.as_ref();

    //fails:
    let y: Option<String> =
        x.and_then::<String, FnOnce(Option<&String>) -> Option<String>>(|_inner: &String| None);

    //ok:
    let y: Option<String> = x.and_then(|_inner: &String| None);
}

playground

Adding the mandatory annotations causes this compiler error:

error: the `and_then` method cannot be invoked on a trait object
 --> src/main.rs:7:11
  |
7 |         x.and_then::<String, FnOnce(Option<&String>) -> Option<String>>(|_inner: &String| None);
  |           ^^^^^^^^

I assume it is complaining about the FnOnce trait, but I don't see what this has to do with x.

I would like to understand what is going wrong here.

Ultimately, the goal is to have this and_then in a chained statement, which is why the annotations are needed.

let y = x
    .and_then::<String, FnOnce(Option<&String>) -> Option<String>>(|_inner: &String| None)
    .and(Some("new String".to_string()));
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
marathon
  • 7,881
  • 17
  • 74
  • 137

1 Answers1

4

There are multiple problems here:

  • Closures are an anonymous type, which means that you cannot name them.

  • It's currently impossible to have a bare trait like FnOnce because it is unsized.

  • || foo isn't a trait, it's a concrete type.

Instead, specify the return type of the closure:

let y = x
    .and_then(|_inner| -> Option<String> { None })
    .and(Some("new String".to_string()));

Or qualify the type of the None:

let y = x
    .and_then(|_inner| None::<String>)
    .and(Some("new String".to_string()));

Or avoid the chaining:

let y: Option<String> = x.and_then(|_inner| None);
let y = y.and(Some("new String".to_string()));
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366