Byron / google-apis-rs

A binding and CLI generator for all Google APIs
http://byron.github.io/google-apis-rs
Other
1.01k stars 131 forks source link

Future is not send #296

Open recmo opened 3 years ago

recmo commented 3 years ago

Using version https://crates.io/crates/google-storage1/2.0.7+20210330 which has #294 fixed.

With the new error I'm still not able to do an upload in a Future that is Send (i.e. inside tokio::spawn):

error[E0277]: `dyn std::io::Read` cannot be sent between threads safely
    = help: the trait `std::marker::Send` is not implemented for `dyn std::io::Read`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::io::Read`
    = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10, 't11, 't12, 't13, 't14, 't15, 't16, 't17, 't18, 't19, 't20, 't21, 't22, 't23, 't24, 't25, 't26, 't27, 't28, 't29, 't30, 't31, 't32, 't33, 't34> {std::future::ResumeTy, google_storage1::api::ObjectInsertCall<'r>, std::io::Cursor<&[u8]>, mime::Mime, &'s str, google_storage1::client::DefaultDelegate, &'t0 mut (dyn google_storage1::Delegate + 't1), std::vec::Vec<(&'t2 str, std::string::String)>, std::string::String, url::Url, std::io::Cursor<std::vec::Vec<u8>>, u64, bool, std::option::Option<std::string::String>, google_storage1::Storage, &'t3 google_storage1::Storage, &'t4 yup_oauth2::authenticator::Authenticator<hyper_rustls::HttpsConnector<hyper::client::HttpConnector>>, yup_oauth2::authenticator::Authenticator<hyper_rustls::HttpsConnector<hyper::client::HttpConnector>>, &'t5 std::collections::BTreeMap<std::string::String, ()>, std::collections::BTreeMap<std::string::String, ()>, std::collections::btree_map::Keys<'t6, std::string::String, ()>, &'t7 std::vec::Vec<&'t8 std::string::String>, std::vec::Vec<&'t9 std::string::String>, std::ops::RangeFull, [&'t10 std::string::String], &'t11 [&'t12 std::string::String], impl for<'t13, 't14> futures::Future, (), yup_oauth2::AccessToken, google_storage1::client::MultiPartReader<'t15>, &'t16 mut (dyn std::io::Read + 't17), (reqwest::header::HeaderName, std::string::String), hyper::Client<hyper_rustls::HttpsConnector<hyper::client::HttpConnector>>, &'t18 hyper::Client<hyper_rustls::HttpsConnector<hyper::client::HttpConnector>>, hyper::http::request::Builder, std::vec::Vec<u8>, std::result::Result<hyper::Request<hyper::Body>, hyper::http::Error>, hyper::Request<hyper::Body>, hyper::client::ResponseFuture, std::result::Result<hyper::Response<hyper::Body>, hyper::Error>, hyper::Response<hyper::Body>, &'t19 mut hyper::Response<hyper::Body>, &'t20 mut hyper::Body, impl for<'t21> futures::Future, &'t22 &'t23 str, std::option::Option<u64>, &'t24 std::string::String, &'t25 mut (dyn google_storage1::client::ReadSeek + 't26), &'t27 mut std::io::Cursor<&[u8]>, &'t28 mime::Mime, &'t29 mut google_storage1::client::ResumableUploadHelper<'t30, yup_oauth2::authenticator::Authenticator<hyper_rustls::HttpsConnector<hyper::client::HttpConnector>>>, google_storage1::client::ResumableUploadHelper<'t31, yup_oauth2::authenticator::Authenticator<hyper_rustls::HttpsConnector<hyper::client::HttpConnector>>>, impl for<'t32, 't33, 't34> futures::Future}`
    = note: required because it appears within the type `[static generator@google_storage1::api::ObjectInsertCall<'<empty>>::doit<std::io::Cursor<&[u8]>>::{closure#0}]`
    = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@google_storage1::api::ObjectInsertCall<'<empty>>::doit<std::io::Cursor<&[u8]>>::{closure#0}]>`
    = note: required because it appears within the type `impl futures::Future`
    = note: required because it appears within the type `impl futures::Future`
    = note: required because it appears within the type `for<'r, 's, 't0, 't1> {std::future::ResumeTy, google_storage1::api::ObjectInsertCall<'r>, std::io::Cursor<&[u8]>, mime::Mime, &'s str, impl for<'t0, 't1> futures::Future, ()}`
    = note: required because it appears within the type `[static generator@google_storage1::api::ObjectInsertCall<'<empty>>::upload<std::io::Cursor<&[u8]>>::{closure#0}]`
    = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@google_storage1::api::ObjectInsertCall<'<empty>>::upload<std::io::Cursor<&[u8]>>::{closure#0}]>`
    = note: required because it appears within the type `impl futures::Future`
    = note: required because it appears within the type `impl futures::Future`
recmo commented 3 years ago

FWIW, the reader I'm providing is Send and if I use the following unsafe hack to force the Future to be Send it appears to be working:

pub struct ForceSendFuture<F: Future>(F);

impl<F: Future> Future for ForceSendFuture<F> {
    type Output = F::Output;

    fn poll(
        self: Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Self::Output> {
        // See <https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning>
        let inner = unsafe { self.map_unchecked_mut(|s| &mut s.0) };
        inner.poll(cx)
    }
}

unsafe impl<F: Future> Send for ForceSendFuture<F> {}

pub unsafe fn unsafe_force_send<F: Future>(future: F) -> ForceSendFuture<F> {
    ForceSendFuture(future)
}
Byron commented 3 years ago

Thanks for the heads-up! I have added the respective trait bounds whereever dyn-traits are used and published the storage 1 crate as version 2.0.8. Maybe now it works :).

Rudo2204 commented 3 years ago

I am having this same problem using google_drive3 crate (using latest version "2.0.7+20210322")

Byron commented 3 years ago

@Rudo2204 drive3 was just re-released with the fixes. I have been hesitant to re-release all crates but might as well do that as the recent improvements seem to have made it worth it.

Rudo2204 commented 3 years ago

@Byron I have just updated and it works now! Thank you. The next question is how I am gonna play around the google drive quota limitation... :smile: