我想撰寫一個帶有一個引數的函式:指向帶有生命周期引數的異步函式的指標。
這是一個最小的例子:
use std::future::Future;
async fn takes_i32_ref<'a>(r: &'a i32) { }
fn takes_fn<F: Future>(f: for<'a> fn(&'a i32) -> F) { }
fn main() {
takes_fn(takes_i32_ref);
}
當我嘗試運行它時,我收到訊息:
error[E0308]: mismatched types
--> src/main.rs:8:14
|
8 | takes_fn(takes_i32_ref);
| -------- ^^^^^^^^^^^^^ one type is more general than the other
| |
| arguments to this function are incorrect
|
= note: expected fn pointer `for<'a> fn(&'a i32) -> _`
found fn item `for<'a> fn(&'a i32) -> impl for<'a> Future<Output = ()> {takes_i32_ref}`
note: function defined here
--> src/main.rs:5:4
|
5 | fn takes_fn<F: Future>(f: for<'a> fn(&'a i32) -> F) { }
| ^^^^^^^^ ---------------------------
我發現了一個看起來非常相關的問題:為什么 `std::mem::drop` 與更高級別特征邊界中的閉包 |_|() 不完全相同?
我認為這個問題與我的不同。在該問題中,for<'a> FnOnce<(&'a &str,)>預期 aFnOnce<(&&str,)>并提供 a。提供的型別不如預期的型別通用,因為它缺少for.
但是,我的示例說 afor<'a> fn(&'a i32) -> _是預期的,并且for<'a> fn(&'a i32) -> impl for<'a> Future<Output = ()> {takes_i32_ref}提供了 a 。提供的型別比預期的型別更通用,因為它具有for.
為什么 Rust 不能做這種強制?
編輯:我還應該補充一點,當我擺脫takes_i32_refand簽名中的參考時,不會出現此錯誤f。異步函式采用具有生命周期的引數似乎很重要。
uj5u.com熱心網友回復:
函式回傳的未來async僅在引數存在時才有效。因此,回傳型別可能取決于引數的生命周期。因此,根據原始 RFC,型別takes_i32_ref實際上類似于
fn takes_i32_ref<'a>(r: &'a i32) -> impl Future<Output = ()> 'a
現在應該清楚為什么您的代碼不起作用:takes_fn'sF不能依賴于'a; 您已經撰寫了takes_fn一個函式,該函式forall 都'a回傳相同的 type F。takes_i32_ref不是這樣的功能,所以takes_fn(takes_i32_ref)失敗了。
在另一個宇宙/未來的 Rust 中,這可能可以通過更高種類的多型性來解決:
// imaginary syntax
fn takes_fn<F<'a>: Future 'a>(f: for<'a> fn(&'a i32) -> F<'a>) { }
// which would be the same as (also imaginary, but at least this one parses...)
fn takes_fn(f: for<'a> fn(&'a i32) -> (impl Future 'a)) { }
但我不認為你的代碼今天可以作業。處理具有與您一樣多的復雜型別/生命周期依賴項的函式并不容易。
要強制它作業,對于非零性能損失,您可以使用dyn.
fn takes_fn<O>(f: for<'a> fn(&'a i32) -> Box<dyn Future<Output = O> 'a>) { }
fn main() {
takes_fn(|r| Box::new(takes_i32_ref(r)));
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/511204.html
標籤:仿制药锈异步等待寿命
上一篇:如何在Expression<Func<T,TResult?>中轉換可以是物件或List<object>的TResult?
