Skip to content

Commit 56c3cd5

Browse files
authoredJul 1, 2024··
feat(client): remove Send +Sync bounds requirement of http2::Connection executor (#3682)
1 parent 9580b35 commit 56c3cd5

File tree

2 files changed

+218
-2
lines changed

2 files changed

+218
-2
lines changed
 

‎src/client/conn/http2.rs

+217-1
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,219 @@ 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::<
483+
_,
484+
_,
485+
http_body_util::Empty<bytes::Bytes>,
486+
>(LocalTokioExecutor, io)
487+
.await
488+
.unwrap();
489+
490+
tokio::task::spawn_local(async move {
491+
conn.await.unwrap();
492+
});
493+
}
494+
}
495+
496+
#[tokio::test]
497+
#[ignore] // only compilation is checked
498+
async fn not_send_not_sync_executor_of_not_send_futures() {
499+
#[derive(Clone)]
500+
struct LocalTokioExecutor {
501+
_x: std::marker::PhantomData<std::rc::Rc<()>>,
502+
}
503+
504+
impl<F> crate::rt::Executor<F> for LocalTokioExecutor
505+
where
506+
F: std::future::Future + 'static, // not requiring `Send`
507+
{
508+
fn execute(&self, fut: F) {
509+
// This will spawn into the currently running `LocalSet`.
510+
tokio::task::spawn_local(fut);
511+
}
512+
}
513+
514+
#[allow(unused)]
515+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Unpin + 'static) {
516+
let (_sender, conn) =
517+
crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(
518+
LocalTokioExecutor {
519+
_x: Default::default(),
520+
},
521+
io,
522+
)
523+
.await
524+
.unwrap();
525+
526+
tokio::task::spawn_local(async move {
527+
conn.await.unwrap();
528+
});
529+
}
530+
}
531+
532+
#[tokio::test]
533+
#[ignore] // only compilation is checked
534+
async fn send_not_sync_executor_of_not_send_futures() {
535+
#[derive(Clone)]
536+
struct LocalTokioExecutor {
537+
_x: std::marker::PhantomData<std::cell::Cell<()>>,
538+
}
539+
540+
impl<F> crate::rt::Executor<F> for LocalTokioExecutor
541+
where
542+
F: std::future::Future + 'static, // not requiring `Send`
543+
{
544+
fn execute(&self, fut: F) {
545+
// This will spawn into the currently running `LocalSet`.
546+
tokio::task::spawn_local(fut);
547+
}
548+
}
549+
550+
#[allow(unused)]
551+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Unpin + 'static) {
552+
let (_sender, conn) =
553+
crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(
554+
LocalTokioExecutor {
555+
_x: Default::default(),
556+
},
557+
io,
558+
)
559+
.await
560+
.unwrap();
561+
562+
tokio::task::spawn_local(async move {
563+
conn.await.unwrap();
564+
});
565+
}
566+
}
567+
568+
#[tokio::test]
569+
#[ignore] // only compilation is checked
570+
async fn send_sync_executor_of_send_futures() {
571+
#[derive(Clone)]
572+
struct TokioExecutor;
573+
574+
impl<F> crate::rt::Executor<F> for TokioExecutor
575+
where
576+
F: std::future::Future + 'static + Send,
577+
F::Output: Send + 'static,
578+
{
579+
fn execute(&self, fut: F) {
580+
tokio::task::spawn(fut);
581+
}
582+
}
583+
584+
#[allow(unused)]
585+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Send + Unpin + 'static) {
586+
let (_sender, conn) = crate::client::conn::http2::handshake::<
587+
_,
588+
_,
589+
http_body_util::Empty<bytes::Bytes>,
590+
>(TokioExecutor, io)
591+
.await
592+
.unwrap();
593+
594+
tokio::task::spawn(async move {
595+
conn.await.unwrap();
596+
});
597+
}
598+
}
599+
600+
#[tokio::test]
601+
#[ignore] // only compilation is checked
602+
async fn not_send_not_sync_executor_of_send_futures() {
603+
#[derive(Clone)]
604+
struct TokioExecutor {
605+
// !Send, !Sync
606+
_x: std::marker::PhantomData<std::rc::Rc<()>>,
607+
}
608+
609+
impl<F> crate::rt::Executor<F> for TokioExecutor
610+
where
611+
F: std::future::Future + 'static + Send,
612+
F::Output: Send + 'static,
613+
{
614+
fn execute(&self, fut: F) {
615+
tokio::task::spawn(fut);
616+
}
617+
}
618+
619+
#[allow(unused)]
620+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Send + Unpin + 'static) {
621+
let (_sender, conn) =
622+
crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(
623+
TokioExecutor {
624+
_x: Default::default(),
625+
},
626+
io,
627+
)
628+
.await
629+
.unwrap();
630+
631+
tokio::task::spawn_local(async move {
632+
// can't use spawn here because when executor is !Send
633+
conn.await.unwrap();
634+
});
635+
}
636+
}
637+
638+
#[tokio::test]
639+
#[ignore] // only compilation is checked
640+
async fn send_not_sync_executor_of_send_futures() {
641+
#[derive(Clone)]
642+
struct TokioExecutor {
643+
// !Sync
644+
_x: std::marker::PhantomData<std::cell::Cell<()>>,
645+
}
646+
647+
impl<F> crate::rt::Executor<F> for TokioExecutor
648+
where
649+
F: std::future::Future + 'static + Send,
650+
F::Output: Send + 'static,
651+
{
652+
fn execute(&self, fut: F) {
653+
tokio::task::spawn(fut);
654+
}
655+
}
656+
657+
#[allow(unused)]
658+
async fn run(io: impl crate::rt::Read + crate::rt::Write + Send + Unpin + 'static) {
659+
let (_sender, conn) =
660+
crate::client::conn::http2::handshake::<_, _, http_body_util::Empty<bytes::Bytes>>(
661+
TokioExecutor {
662+
_x: Default::default(),
663+
},
664+
io,
665+
)
666+
.await
667+
.unwrap();
668+
669+
tokio::task::spawn_local(async move {
670+
// can't use spawn here because when executor is !Send
671+
conn.await.unwrap();
672+
});
673+
}
674+
}
675+
}

‎src/proto/h2/client.rs

+1-1
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)
Please sign in to comment.