У меня следующий упрощенный код.
use async_trait::async_trait; // 0.1.36
use std::error::Error;
#[async_trait]
trait Metric: Send {
type Output;
type Error: Error;
async fn refresh_metric(&mut self) -> Result<Self::Output, Self::Error>;
}
#[derive(Default)]
struct StaticMetric;
#[async_trait]
impl Metric for StaticMetric {
type Output = ();
type Error = Box<dyn Error>;
async fn refresh_metric(&mut self) -> Result<Self::Output, Self::Error> {
Ok(())
}
}
struct LocalSystemData<T> {
inner: T,
}
impl<T> LocalSystemData<T>
where
T: Metric,
<T as Metric>::Error: 'static,
{
fn new(inner: T) -> LocalSystemData<T> {
LocalSystemData { inner }
}
async fn refresh_all(&mut self) -> Result<(), Box<dyn Error>> {
self.inner.refresh_metric().await?;
Ok(())
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let mut sys_data = LocalSystemData::new(StaticMetric::default());
sys_data.refresh_all().await?;
Ok(())
}
Playground
Компилятор выдает следующую ошибку
error[E0277]: the size for values of type `(dyn std::error::Error + 'static)` cannot be known at compilation time
--> src/main.rs:18:18
|
5 | trait Metric: Send {
| ------ required by a bound in this
6 | type Output;
7 | type Error: Error;
| ----- required by this bound in `Metric`
...
18 | type Error = Box<dyn Error>;
| ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::error::Error + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because of the requirements on the impl of `std::error::Error` for `std::boxed::Box<(dyn std::error::Error + 'static)>`
I ' m не совсем уверен, правильно ли я понимаю проблему.
Я использую Box<dyn Error>
, потому что у меня нет конкретного типа, и упаковка ошибки может обработать все ошибки. В моей реализации LocaSystemData
я добавил <T as Metric>::Error: 'static
(компилятор дал мне эту подсказку, а не мою идею). После того, как я добавил требование 'static
, компилятор жалуется, что размер неизвестен. Это происходит потому, что размер типа 'static
всегда должен быть известен во время компиляции, потому что значение stati c.
Я изменил черту Metric
, чтобы избавиться от type Error;
Now У меня есть следующая функция asyn c, и мой код компилируется
Playground
async fn refresh_metric(&mut self) -> Result<Self::Output, Box<dyn Error>>;
Почему моя вторая версия компилируется, а первая - нет? Для меня как человека код делает то же самое. Кажется, я обманул компилятор: -).