是 Rust 太难了,还是主流编程本来就这么折磨人? | 您所在的位置:网站首页 › rust太难了 › 是 Rust 太难了,还是主流编程本来就这么折磨人? |
where H: Fn(& 'a Update) -> Fut + Send + Sync + 'a, Fut: Future + Send + 'a, { self.0.push(Box::new(move |upd| Box::pin(handler(upd)))); } } fn main { let mut dp = Dispatcher(vec![]); dp.push_handler(|upd| async move { println!("{:?}", upd); }); } 在这里,我们使用由 HRTB 生命周期 for src/main.rs:12:21 | 12 | fn push_handler限定的BoxFuture: use futures::future::BoxFuture; #[derive(Debug)] struct Update; typeHandler = Box BoxFuture< 'a, > + Send + Sync>; struct Dispatcher(Vec); impl Dispatcher { fn push_handler(&mut self, handler: H) where H: for BoxFuture Self::Out; } impl PushHandler forDispatcherEnd { typeOut = Dispatcher; fn push_handler(self, handler: NewH) -> Self::Out { Dispatcher { handler, tail: DispatcherEnd, } } } impl PushHandler forDispatcher where Tail: PushHandler, { typeOut = Dispatcher; fn push_handler(self, handler: NewH) -> Self::Out { Dispatcher { handler: self.handler, tail: self.tail.push_handler(handler), } } } 有些朋友可能不太熟悉所谓类型级归纳,其实这就是一种常规递归,只是适用对象是类型(trait)、而非值: 这里的 base case 就是 impl PushHandler for DispatcherEnd。我们构建一个 dispatcher,其中只包含一个处理程序。 而 step case 则是 impl PushHandler for Dispatcher。这里我们只将归纳传播至 self.tail。我们再以同样的方式实现 execute: trait Execute< 'a> { #[must_use] fn execute(&' a self, upd: & 'a Update) -> BoxFuture Execute { Box::pin(async {}) } } impl for Dispatcher where H: Fn(&' a Update) -> Fut + Send + Sync + 'a, Fut: Future + Send + ' a, Tail: Execute< 'a> + Send + Sync + 'a, { fn execute(& 'a self, upd: &'a Update) -> BoxFuture< 'a, > { Box::pin(async move { (self.handler)(upd).await; self.tail.execute(upd).await; }) } } 但这还不够。因为我们 Execute, { dp.execute(&upd).await; } 好了,现在我们要来测试这种神奇的解决方案: #[tokio::main] async fn main{ letdp = DispatcherEnd; letdp = dp.push_handler(|upd| async move { println!( "{:?}", upd); }); execute(dp, Update).await; } 可惜还是行不通: error: implementation of `Execute` is not general enough --> src/main.rs:83:5 | 83 | execute(dp, Update).await; | ^^^^^^^ implementation of `Execute` is not general enough | = note: `Dispatcher` must implement `Execute< '0>`, for any lifetime `'0`... = note: ...but it actually implements `Execute< '1>`, for some specific lifetime `'1` 到这里,很多朋友应该体会到借用检查器的可惜之处了吧?而且无论怎么调整,以上代码都没办法正常编译。原因如下:传递给 dp.push_handler 的闭包接收到一条具体生命周期为'1 的 upd,但因为 where 子句中引入了 HRTB 边界,所以 execute 要求 Dp 只在生命周期 '0 上实现 Execute fn(&'r Update): error[E0308]: mismatched types --> src/main.rs:9:9 | 9 | let= dbg_update_fn; | ^^ ------------- this expression has type` for< 'r> fn(&'r Update) {dbg_update_fn}` | | | expected fn item, found `` | = note: expected fn item ` for< 'r> fn(&'r Update) {dbg_update_fn}` found unit type`` 话虽如此,但这样一个包含异构列表的答案也不符合我们的预期:它太过混乱、僵化、复杂,而且也装不进闭包。另外,这里不建议在 Rust 中使用复杂的类型机制。如果大家在处理 dispatcher 类型时突然遇到类型检查失败,那麻烦可就大了。想象一下,我们正在维护一套用 Rust 编写的生产系统,而且需要尽快修复一些关键 bug。而在完成了代码库的必要更改之后,却看到了以下编译输出: error[E0308]: mismatched types --> src/main.rs:123:9 | 123 | let= dp; | ^^ -- this expression has type`Dispatcher< for< '_> fn(&Update) -> impl futures::Future {dbg_update0}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update2}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update4}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update6}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update8}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update0}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update2}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update4}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update6}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update8}, Dispatcher |
CopyRight 2018-2019 实验室设备网 版权所有 |