Skip to content

Commit 770c1ca

Browse files
committed
Make Future implementation on Connection unconditional on executor being Send + Sync.
1 parent 0eb1b6c commit 770c1ca

File tree

2 files changed

+170
-2
lines changed

2 files changed

+170
-2
lines changed

src/client/conn/http2.rs

Lines changed: 169 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ where
230230
B::Data: Send,
231231
E: Unpin,
232232
B::Error: Into<Box<dyn Error + Send + Sync>>,
233-
E: Http2ClientConnExec<B, T> + 'static + Send + Sync + Unpin,
233+
E: Http2ClientConnExec<B, T> + Unpin
234234
{
235235
type Output = crate::Result<()>;
236236

@@ -457,3 +457,171 @@ where
457457
}
458458
}
459459
}
460+
461+
#[cfg(test)]
462+
mod tests {
463+
464+
#[tokio::test]
465+
#[ignore] // only compilation is checked
466+
async fn send_sync_executor_of_non_send_futures() {
467+
#[derive(Clone)]
468+
struct LocalTokioExecutor;
469+
470+
impl<F> crate::rt::Executor<F> for LocalTokioExecutor
471+
where
472+
F: std::future::Future + 'static, // not requiring `Send`
473+
{
474+
fn execute(&self, fut: F) {
475+
// This will spawn into the currently running `LocalSet`.
476+
tokio::task::spawn_local(fut);
477+
}
478+
}
479+
480+
#[allow(unused)]
481+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Unpin + 'static) {
482+
let (_sender, conn) = crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(LocalTokioExecutor, io).await.unwrap();
483+
484+
tokio::task::spawn_local(async move {
485+
conn.await.unwrap();
486+
});
487+
}
488+
}
489+
490+
#[tokio::test]
491+
#[ignore] // only compilation is checked
492+
async fn not_send_not_sync_executor_of_not_send_futures() {
493+
#[derive(Clone)]
494+
struct LocalTokioExecutor {
495+
_x: std::marker::PhantomData<std::rc::Rc<()>>
496+
}
497+
498+
impl<F> crate::rt::Executor<F> for LocalTokioExecutor
499+
where
500+
F: std::future::Future + 'static, // not requiring `Send`
501+
{
502+
fn execute(&self, fut: F) {
503+
// This will spawn into the currently running `LocalSet`.
504+
tokio::task::spawn_local(fut);
505+
}
506+
}
507+
508+
#[allow(unused)]
509+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Unpin + 'static) {
510+
let (_sender, conn) = crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(LocalTokioExecutor { _x: Default::default() }, io).await.unwrap();
511+
512+
tokio::task::spawn_local(async move {
513+
conn.await.unwrap();
514+
});
515+
}
516+
}
517+
518+
#[tokio::test]
519+
#[ignore] // only compilation is checked
520+
async fn send_not_sync_executor_of_not_send_futures() {
521+
#[derive(Clone)]
522+
struct LocalTokioExecutor {
523+
_x: std::marker::PhantomData<std::cell::Cell<()>>
524+
}
525+
526+
impl<F> crate::rt::Executor<F> for LocalTokioExecutor
527+
where
528+
F: std::future::Future + 'static, // not requiring `Send`
529+
{
530+
fn execute(&self, fut: F) {
531+
// This will spawn into the currently running `LocalSet`.
532+
tokio::task::spawn_local(fut);
533+
}
534+
}
535+
536+
#[allow(unused)]
537+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Unpin + 'static) {
538+
let (_sender, conn) = crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(LocalTokioExecutor { _x: Default::default() }, io).await.unwrap();
539+
540+
tokio::task::spawn_local(async move {
541+
conn.await.unwrap();
542+
});
543+
}
544+
}
545+
546+
#[tokio::test]
547+
#[ignore] // only compilation is checked
548+
async fn send_sync_executor_of_send_futures() {
549+
#[derive(Clone)]
550+
struct TokioExecutor;
551+
552+
impl<F> crate::rt::Executor<F> for TokioExecutor
553+
where
554+
F: std::future::Future + 'static + Send,
555+
F::Output: Send + 'static,
556+
{
557+
fn execute(&self, fut: F) {
558+
tokio::task::spawn(fut);
559+
}
560+
}
561+
562+
#[allow(unused)]
563+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Send + Unpin + 'static) {
564+
let (_sender, conn) = crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(TokioExecutor, io).await.unwrap();
565+
566+
tokio::task::spawn(async move {
567+
conn.await.unwrap();
568+
});
569+
}
570+
}
571+
572+
#[tokio::test]
573+
#[ignore] // only compilation is checked
574+
async fn not_send_not_sync_executor_of_send_futures() {
575+
#[derive(Clone)]
576+
struct TokioExecutor { // !Send, !Sync
577+
_x: std::marker::PhantomData<std::rc::Rc<()>>
578+
}
579+
580+
impl<F> crate::rt::Executor<F> for TokioExecutor
581+
where
582+
F: std::future::Future + 'static + Send,
583+
F::Output: Send + 'static,
584+
{
585+
fn execute(&self, fut: F) {
586+
tokio::task::spawn(fut);
587+
}
588+
}
589+
590+
#[allow(unused)]
591+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Send + Unpin + 'static) {
592+
let (_sender, conn) = crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(TokioExecutor { _x: Default::default() }, io).await.unwrap();
593+
594+
tokio::task::spawn_local(async move { // can't use spawn here because when executor is !Send
595+
conn.await.unwrap();
596+
});
597+
}
598+
}
599+
600+
#[tokio::test]
601+
#[ignore] // only compilation is checked
602+
async fn send_not_sync_executor_of_send_futures() {
603+
#[derive(Clone)]
604+
struct TokioExecutor { // !Sync
605+
_x: std::marker::PhantomData<std::cell::Cell<()>>
606+
}
607+
608+
impl<F> crate::rt::Executor<F> for TokioExecutor
609+
where
610+
F: std::future::Future + 'static + Send,
611+
F::Output: Send + 'static,
612+
{
613+
fn execute(&self, fut: F) {
614+
tokio::task::spawn(fut);
615+
}
616+
}
617+
618+
#[allow(unused)]
619+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Send + Unpin + 'static) {
620+
let (_sender, conn) = crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(TokioExecutor { _x: Default::default() }, io).await.unwrap();
621+
622+
tokio::task::spawn_local(async move { // can't use spawn here because when executor is !Send
623+
conn.await.unwrap();
624+
});
625+
}
626+
}
627+
}

src/proto/h2/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ where
611611
B: Body + 'static + Unpin,
612612
B::Data: Send,
613613
B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
614-
E: Http2ClientConnExec<B, T> + 'static + Send + Sync + Unpin,
614+
E: Http2ClientConnExec<B, T> + Unpin,
615615
T: Read + Write + Unpin,
616616
{
617617
type Output = crate::Result<Dispatched>;

0 commit comments

Comments
 (0)