Skip to content

Commit d060cbc

Browse files
committed
Perform type erasure by returning result as T instead of St::Ok
1 parent cd5baab commit d060cbc

File tree

2 files changed

+21
-11
lines changed

2 files changed

+21
-11
lines changed

src/run_query_dsl/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ pub mod return_futures {
146146
///
147147
/// This is essentially `impl Future<Output = QueryResult<U>>`
148148
pub type GetResult<'conn, 'query, Q: LoadQuery<'query, Conn, U>, Conn, U> =
149-
utils::AndThen<Q::LoadFuture<'conn>, utils::LoadNext<Pin<Box<Q::Stream<'conn>>>>>;
149+
utils::AndThen<Q::LoadFuture<'conn>, utils::LoadNext<Pin<Box<Q::Stream<'conn>>>, U>>;
150150
}
151151

152152
/// Methods used to execute queries.

src/run_query_dsl/utils.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::task::{Context, Poll};
44

55
use diesel::QueryResult;
66
use futures_core::{TryFuture, TryStream};
7+
use futures_util::stream::TryCollect;
78
use futures_util::{TryFutureExt, TryStreamExt};
89

910
// We use a custom future implementation here to erase some lifetimes
@@ -84,29 +85,38 @@ where
8485
/// Consumes the entire stream to ensure proper cleanup before returning which is
8586
/// required to fix: https://github.com/weiznich/diesel_async/issues/269
8687
#[repr(transparent)]
87-
pub struct LoadNext<T: TryStreamExt> {
88-
future: futures_util::stream::TryCollect<T, Vec<T::Ok>>,
88+
pub struct LoadNext<F, T>
89+
where
90+
F: TryStream<Ok = T, Error = diesel::result::Error>,
91+
{
92+
future: TryCollect<F, Vec<T>>,
8993
}
9094

91-
impl<T> LoadNext<T>
95+
impl<F, T> LoadNext<F, T>
9296
where
93-
T: TryStream<Error = diesel::result::Error> + Unpin,
97+
F: TryStream<Ok = T, Error = diesel::result::Error>,
9498
{
95-
pub(crate) fn new(stream: T) -> Self {
99+
pub(crate) fn new(stream: F) -> Self {
96100
Self {
97101
future: stream.try_collect(),
98102
}
99103
}
100104
}
101105

102-
impl<T> Future for LoadNext<T>
106+
impl<F, T> Future for LoadNext<F, T>
103107
where
104-
T: TryStream<Error = diesel::result::Error> + Unpin,
108+
F: TryStream<Ok = T, Error = diesel::result::Error>,
109+
TryCollect<F, Vec<T>>: Future<Output = Result<Vec<T>, diesel::result::Error>>,
105110
{
106-
type Output = QueryResult<T::Ok>;
111+
type Output = QueryResult<T>;
107112

108-
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
109-
match Pin::new(&mut self.future).poll(cx) {
113+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
114+
match unsafe {
115+
// SAFETY: This projects pinning to the only inner field
116+
self.map_unchecked_mut(|s| &mut s.future)
117+
}
118+
.poll(cx)
119+
{
110120
Poll::Ready(Ok(results)) => match results.into_iter().next() {
111121
Some(first) => Poll::Ready(Ok(first)),
112122
None => Poll::Ready(Err(diesel::result::Error::NotFound)),

0 commit comments

Comments
 (0)