Confusing error from surf when trying to read response

So I'm trying to read a surf response in chunks to get a progress bar working but I can't seem to read from the request. I get an error about read not found on surf::Response. It tells me that the method is implemented but I need to import the AsyncReadExt trait so I do that but then I get the same suggestion and an unused import warning for the trait it's telling me to include.

It also says that the method is available for a Boxed response so I tried wrapping it with Box::new but then it says it needs to be Pinned. I changed it to Box::pin and then it tells me that the method is available on a Boxed Pinned Boxed Response so I think that's just going to recurse boxes and pins infinitely.

warning: unused import: `AsyncRead`
 --> src/main.rs:1:24
  |
1 | use futures_util::io::{AsyncRead, AsyncReadExt};
  |                        ^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0599]: no method named `read` found for struct `surf::Response` in the current scope
   --> src/main.rs:21:21
    |
21  |         let n = res.read(&mut buf).await?;
    |                     ^^^^ method not found in `surf::Response`
    |
   ::: /home/iain/.cargo/registry/src/github.com-1ecc6299db9ec823/surf-1.0.3/src/response.rs:17:1
    |
17  | pub struct Response {
    | -------------------
    | |
    | doesn't satisfy `surf::Response: futures_util::AsyncReadExt`
    | doesn't satisfy `surf::Response: futures_util::io::AsyncRead`
    |
   ::: /home/iain/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.19/src/io/mod.rs:217:8
    |
217 |     fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>
    |        ---- the method is available for `std::boxed::Box<surf::Response>` here
    |
    = note: the method `read` exists but the following trait bounds were not satisfied:
            `surf::Response: futures_util::io::AsyncRead`
            which is required by `surf::Response: futures_util::AsyncReadExt`
    = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
1   | use futures_util::io::AsyncReadExt;
    |

warning: unused import: `AsyncReadExt`
 --> src/main.rs:1:35
  |
1 | use futures_util::io::{AsyncRead, AsyncReadExt};
  |                                   ^^^^^^^^^^^^

error: aborting due to previous error; 2 warnings emitted

For more information about this error, try `rustc --explain E0599`.

I can't see any documentation in the surf project for how to do this so I'm not sure if it's just not meant to be used like this or not.

Hopefully someone knows what I'm doing wrong!

The error messages are confusing enough for me to suspect it's an issue with crate version mismatch:

  • It is likely (latest stable release) you are depending on ::futures-util v0.3.5 or something along those lines.

  • It is also likely (latest stable release) you are depending on ::surf v 1.0.3

And it so happens that that version of surf does not use that version (or a semver-compatible one) of futures-util. This leads to surf implementing some AsyncRead{,Ext} traits, and you attempting to use another different set of traits, which just happen to be equally named, hence the weird error messages.

Solution

Got it in one! Thanks! I've added

futures-preview = "0.3.0-alpha.19"
futures-util-preview = "0.3.0-alpha.19"

to my Cargo.toml and now it's working