I'm trying to write a chat bot that supports the matrix protocol, and I ran into this problem that I can't wrap my head around. On its own the code compiles without issue, but adding "surf" as a dependency to the Cargo.toml causes a "dyn log::kv::source::Source` cannot be shared between threads safely" error.
This is the minimal code for which this happens:
main.rs:
use std::convert::TryFrom;
use matrix_sdk::{
Client, Result,
ruma::{UserId},
};
use async_trait::async_trait;
async fn new_matrix_connector() -> Option<()> {
let username = "NAME";
let password = "PASSWORD";
let alice = match UserId::try_from(username) {
Ok(user) => user,
Err(_) => {return None;}
};
let client = match Client::new_from_user_id(alice.clone()).await {
Ok(client) => client,
Err(_) => {return None;}
};
match client.login(alice.localpart(), password, None, None).await {
Ok(_) => {},
Err(_) => {return None;}
}
Some(())
}
#[async_trait]
trait Loader {
async fn load(&self) -> Option<()>;
}
struct TestLoader {}
#[async_trait]
impl Loader for TestLoader {
async fn load(&self) -> Option<()> {
new_matrix_connector().await
}
}
#[tokio::main]
async fn main() -> Result<()> {
let loader = TestLoader{};
let _res = loader.load();
Ok(())
}
Cargo.toml:
[package]
name = "matrixtest"
version = "0.1.0"
edition = "2018"
[dependencies]
matrix-sdk = "0.4.1"
tokio = { version = "1", features = ["full"] }
async-trait = "0.1.52"
surf = "2.3.2"
These are the full errors caused:
error[E0277]: `dyn log::kv::source::Source` cannot be shared between threads safely
--> src/main.rs:38:40
|
38 | async fn load(&self) -> Option<()> {
| ________________________________________^
39 | | new_matrix_connector().await
40 | | }
| |_____^ `dyn log::kv::source::Source` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `dyn log::kv::source::Source`
= note: required because of the requirements on the impl of `Send` for `&dyn log::kv::source::Source`
= note: required because it appears within the type `log::KeyValues<'_>`
= note: required because it appears within the type `log::Record<'_>`
= note: required because it appears within the type `log::RecordBuilder<'_>`
= 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> {ResumeTy, log::Level, log::Metadata<'r>, &'s (dyn log::Log + 't0), &'t1 mut log::RecordBuilder<'t2>, log::RecordBuilder<'t3>, &'t4 str, std::option::Option<&'t5 str>, u32, std::option::Option<u32>, [&'t6 str; 2], &'t7 [&'t8 str], &'t9 [&'t10 str; 2], &'t11 matrix_sdk::Client, impl for<'t12> std::future::Future, (), tracing_core::subscriber::Interest, &'t13 tracing_core::metadata::Metadata<'t14>, tracing_core::field::Iter, &'t15 tracing_core::field::FieldSet, &'t16 mut tracing_core::field::Iter, std::option::Option<tracing_core::field::Field>, tracing_core::field::Field, &'t17 tracing_core::field::Field, LoginInfo<'t18>, matrix_sdk::ruma::api::ruma_client_api::r0::session::login::Request<'t19>, std::option::Option<RequestConfig>, impl for<'t20, 't21> std::future::Future, matrix_sdk::ruma::api::ruma_client_api::r0::session::login::Response, matrix_sdk::Client, &'t22 matrix_sdk_base::client::BaseClient, matrix_sdk_base::client::BaseClient, &'t23 matrix_sdk::ruma::api::ruma_client_api::r0::session::login::Response, impl for<'t24, 't25> std::future::Future}`
= note: required because it appears within the type `[static generator@matrix_sdk::Client::login::{closure#0}::{closure#0}]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@matrix_sdk::Client::login::{closure#0}::{closure#0}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10> {ResumeTy, &'r matrix_sdk::Client, &'s str, std::option::Option<&'t0 str>, tracing::span::Span, impl for<'t1, 't2, 't3, 't4, 't5> std::future::Future, tracing::instrument::Instrumented<impl for<'t6, 't7, 't8, 't9, 't10> std::future::Future>, ()}`
= note: required because it appears within the type `[static generator@matrix_sdk::Client::login::{closure#0}]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@matrix_sdk::Client::login::{closure#0}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6> {ResumeTy, &'r str, matrix_sdk::ruma::UserId, &'s matrix_sdk::ruma::UserId, impl std::future::Future, (), matrix_sdk::Client, &'t0 matrix_sdk::Client, std::option::Option<&'t1 str>, impl for<'t2, 't3, 't4, 't5, 't6> std::future::Future}`
= note: required because it appears within the type `[static generator@src/main.rs:8:47: 27:2]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@src/main.rs:8:47: 27:2]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `for<'r> {ResumeTy, &'r TestLoader, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@src/main.rs:38:40: 40:6]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@src/main.rs:38:40: 40:6]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required for the cast to the object type `dyn std::future::Future<Output = std::option::Option<()>> + Send`
error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
--> src/main.rs:38:40
|
38 | async fn load(&self) -> Option<()> {
| ________________________________________^
39 | | new_matrix_connector().await
40 | | }
| |_____^ `core::fmt::Opaque` cannot be shared between threads safely
|
= help: within `[ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque`
= note: required because it appears within the type `&core::fmt::Opaque`
= note: required because it appears within the type `ArgumentV1<'_>`
= note: required because it appears within the type `[ArgumentV1<'_>]`
= note: required because of the requirements on the impl of `Send` for `&[ArgumentV1<'_>]`
= note: required because it appears within the type `Arguments<'_>`
= note: required because it appears within the type `log::Record<'_>`
= note: required because it appears within the type `log::RecordBuilder<'_>`
= 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> {ResumeTy, log::Level, log::Metadata<'r>, &'s (dyn log::Log + 't0), &'t1 mut log::RecordBuilder<'t2>, log::RecordBuilder<'t3>, &'t4 str, std::option::Option<&'t5 str>, u32, std::option::Option<u32>, [&'t6 str; 2], &'t7 [&'t8 str], &'t9 [&'t10 str; 2], &'t11 matrix_sdk::Client, impl for<'t12> std::future::Future, (), tracing_core::subscriber::Interest, &'t13 tracing_core::metadata::Metadata<'t14>, tracing_core::field::Iter, &'t15 tracing_core::field::FieldSet, &'t16 mut tracing_core::field::Iter, std::option::Option<tracing_core::field::Field>, tracing_core::field::Field, &'t17 tracing_core::field::Field, LoginInfo<'t18>, matrix_sdk::ruma::api::ruma_client_api::r0::session::login::Request<'t19>, std::option::Option<RequestConfig>, impl for<'t20, 't21> std::future::Future, matrix_sdk::ruma::api::ruma_client_api::r0::session::login::Response, matrix_sdk::Client, &'t22 matrix_sdk_base::client::BaseClient, matrix_sdk_base::client::BaseClient, &'t23 matrix_sdk::ruma::api::ruma_client_api::r0::session::login::Response, impl for<'t24, 't25> std::future::Future}`
= note: required because it appears within the type `[static generator@matrix_sdk::Client::login::{closure#0}::{closure#0}]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@matrix_sdk::Client::login::{closure#0}::{closure#0}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10> {ResumeTy, &'r matrix_sdk::Client, &'s str, std::option::Option<&'t0 str>, tracing::span::Span, impl for<'t1, 't2, 't3, 't4, 't5> std::future::Future, tracing::instrument::Instrumented<impl for<'t6, 't7, 't8, 't9, 't10> std::future::Future>, ()}`
= note: required because it appears within the type `[static generator@matrix_sdk::Client::login::{closure#0}]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@matrix_sdk::Client::login::{closure#0}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6> {ResumeTy, &'r str, matrix_sdk::ruma::UserId, &'s matrix_sdk::ruma::UserId, impl std::future::Future, (), matrix_sdk::Client, &'t0 matrix_sdk::Client, std::option::Option<&'t1 str>, impl for<'t2, 't3, 't4, 't5, 't6> std::future::Future}`
= note: required because it appears within the type `[static generator@src/main.rs:8:47: 27:2]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@src/main.rs:8:47: 27:2]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `for<'r> {ResumeTy, &'r TestLoader, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@src/main.rs:38:40: 40:6]`
= note: required because it appears within the type `from_generator::GenFuture<[static generator@src/main.rs:38:40: 40:6]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required for the cast to the object type `dyn std::future::Future<Output = std::option::Option<()>> + Send`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `matrix` due to 2 previous errors
Without the surf dependency this compiles without issue. It also doesn't happen if the load() function is implemented for the TestLoader struct directly.