Detailed changes
@@ -1,6 +1,6 @@
use crate::{
rpc::{self, Client},
- util::log_async_errors,
+ util::TryFutureExt,
};
use anyhow::{anyhow, Context, Result};
use gpui::{
@@ -76,7 +76,7 @@ impl ChannelList {
pub fn new(rpc: Arc<rpc::Client>, cx: &mut ModelContext<Self>) -> Self {
cx.spawn(|this, mut cx| {
let rpc = rpc.clone();
- log_async_errors(async move {
+ async move {
let response = rpc
.request(proto::GetChannels {})
.await
@@ -87,7 +87,8 @@ impl ChannelList {
cx.notify();
});
Ok(())
- })
+ }
+ .log_err()
})
.detach();
Self {
@@ -185,7 +186,7 @@ impl Channel {
});
let rpc = self.rpc.clone();
cx.spawn(|this, mut cx| {
- log_async_errors(async move {
+ async move {
let request = rpc.request(proto::SendChannelMessage { channel_id, body });
let response = request.await?;
this.update(&mut cx, |this, cx| {
@@ -205,7 +206,7 @@ impl Channel {
}
});
Ok(())
- })
+ }.log_err()
})
.detach();
cx.notify();
@@ -1,7 +1,11 @@
-use futures::Future;
+use futures::{Future};
pub use gpui::sum_tree::Bias;
use rand::prelude::*;
-use std::cmp::Ordering;
+use std::{
+ cmp::Ordering,
+ pin::Pin,
+ task::{Context, Poll},
+};
pub fn post_inc(value: &mut usize) -> usize {
let prev = *value;
@@ -60,12 +64,58 @@ impl<T: Rng> Iterator for RandomCharIter<T> {
}
}
-pub async fn log_async_errors<F>(f: F)
+pub trait ResultExt {
+ type Ok;
+
+ fn log_err(self) -> Option<Self::Ok>;
+}
+
+impl<T> ResultExt for anyhow::Result<T> {
+ type Ok = T;
+
+ fn log_err(self) -> Option<T> {
+ match self {
+ Ok(value) => Some(value),
+ Err(error) => {
+ log::error!("{:?}", error);
+ None
+ }
+ }
+ }
+}
+
+pub trait TryFutureExt {
+ fn log_err(self) -> LogErrorFuture<Self>
+ where
+ Self: Sized;
+}
+
+impl<F, T> TryFutureExt for F
where
- F: Future<Output = anyhow::Result<()>>,
+ F: Future<Output = anyhow::Result<T>>,
{
- if let Err(error) = f.await {
- log::error!("{}", error)
+ fn log_err(self) -> LogErrorFuture<Self>
+ where
+ Self: Sized,
+ {
+ LogErrorFuture(self)
+ }
+}
+
+pub struct LogErrorFuture<F>(F);
+
+impl<F, T> Future for LogErrorFuture<F>
+where
+ F: Future<Output = anyhow::Result<T>>,
+{
+ type Output = Option<T>;
+
+ fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };
+ match inner.poll(cx) {
+ Poll::Ready(output) => Poll::Ready(output.log_err()),
+ Poll::Pending => Poll::Pending,
+ }
}
}
@@ -9,7 +9,7 @@ use crate::{
language::LanguageRegistry,
rpc::{self, proto},
time::{self, ReplicaId},
- util::{log_async_errors, Bias},
+ util::{Bias, TryFutureExt},
};
use ::ignore::gitignore::Gitignore;
use anyhow::{anyhow, Result};
@@ -330,10 +330,13 @@ impl Worktree {
.open_remote_buffer(envelope, cx);
cx.background()
- .spawn(log_async_errors(async move {
- rpc.respond(receipt, response.await?).await?;
- Ok(())
- }))
+ .spawn(
+ async move {
+ rpc.respond(receipt, response.await?).await?;
+ Ok(())
+ }
+ .log_err(),
+ )
.detach();
Ok(())
@@ -465,22 +468,25 @@ impl Worktree {
});
cx.background()
- .spawn(log_async_errors(async move {
- let (version, mtime) = save.await?;
-
- rpc.respond(
- receipt,
- proto::BufferSaved {
- worktree_id,
- buffer_id,
- version: (&version).into(),
- mtime: Some(mtime.into()),
- },
- )
- .await?;
+ .spawn(
+ async move {
+ let (version, mtime) = save.await?;
- Ok(())
- }))
+ rpc.respond(
+ receipt,
+ proto::BufferSaved {
+ worktree_id,
+ buffer_id,
+ version: (&version).into(),
+ mtime: Some(mtime.into()),
+ },
+ )
+ .await?;
+
+ Ok(())
+ }
+ .log_err(),
+ )
.detach();
Ok(())