How to handle stream map closure return type

This is perhaps not the best way to do this however for sanity sake and to better understand the language what would the return type be for the function below: I can’t seem to figure it out.

fn unpack_file(parser: &SomeProcessor, path: std::path::PathBuf) -> ??? {
    let file = OpenOptions::new()
            .read(true)
            .open(path.as_path()).unwrap();
    let reader = io::BufReader::new(file);
    let path_str = path.to_str().unwrap().to_string();
    let stream = reader.lines().enumerate().map(|(i,line)| {
        line.map_err(|e| LineError(SomeError::IoError(e), i,path_str.to_owned()))
          .and_then(|record: String| {
              parser.process(&record).map_err(|e| LineError(e, i,path_str.to_owned()))
          })
    });
    stream
}

Compiler says:

187 |     stream
    |     ^^^^^^ expected struct `???`, found struct `std::iter::Map`
    |
    = note: expected type `???'
               found type `std::iter::Map<std::iter::Enumerate<std::io::Lines<std::io::BufReader<std::fs::File>>>, [closure@src/main.rs:181:49: 186:6 path_str:_, parser:_]>`

found type std::iter::Map<std::iter::Enumerate<std::io::Lines<std::io::BufReader<std::fs::File>>>, [closure@src/main.rs:181:49: 186:6 path_str:_, parser:_]>

Yeah, that’s its type - you can’t write it down because you can’t write down the type of a closure. But one possible signature for the function would be (using the impl Trait syntax):

fn unpack_file(parser: &SomeProcessor, path: std::path::PathBuf) -> impl Iterator<Item = ???>

where ??? is the result of parser.process(&record), but with LineError as the error type.

So how do I return stream so I can use it in the caller?

Edited!

pub trait LineProcessor<T> {
    fn process(&self, line: &str) -> LineResult<T>;
}

so then I:

fn unpack_file(parser: &SomeProcessor, path: std::path::PathBuf) -> impl Iterator<Result<LineResult, LineError>> {
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected no type arguments

Sorry, I’m stupid! It’s actually:

fn unpack_file(parser: &SomeProcessor, path: std::path::PathBuf) -> impl Iterator<Item = ???>;

I guess that makes sense. Compiler still confused:

error: `impl Trait` in return position is experimental (see issue #34511)
   --> src/main.rs:174:76
    |
174 | fn unpack_file(parser: &SomeProcessor, path: std::path::PathBuf) -> impl Iterator<Item = LineResult> {
    |                                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0243]: wrong number of type arguments: expected 1, found 0
   --> src/main.rs:174:97
    |
174 | fn unpack_file(parser: &SomeProcessor, path: std::path::PathBuf) -> impl Iterator<Item = LineResult> {
    |                                                                                                 ^^^^^^^^^^ expected 1 type argument

error: aborting due to 2 previous errors

Is it because

LineResult<T>?

Probably? Also, you need to be on nightly and add #![feature(conservative_impl_trait)] to the top of your main.rs or lib.rs for impl Trait to work right now.

error[E0554]: #![feature] may not be used on the stable release channel
 --> src/main.rs:1:1
  |
1 | #![feature(conservative_impl_trait)]

not sure what this mean :stuck_out_tongue:

You need to use the nightly channel to use impl Trait right now, because the details and implementation are still being worked out. See the book for more information:

https://doc.rust-lang.org/book/first-edition/release-channels.html

Ok cool I will test that, thanks for the help. Just curious is there a way to do it with a non impl also?

You can return a Box<Iterator<Item=...>>.

^^^ Thanks!