Rust参数为何需存活超函数体?`spawn_blocking`生命周期问题
Rust生命周期问题:spawn_blocking引发的逃逸错误
问题场景
执行cargo check检查以下函数时:
// 此代码无法运行 pub async fn verify_passcode<'a>(pass: Passcode, hash: PasswordHash<'a>) -> Result<bool> { Ok(task::spawn_blocking(move || argon2_verify(pass, hash)).await?) }
收到如下错误提示,尽管闭包已获取hash的所有权,但编译器仍判定hash逃逸出函数体:
error[E0521]: borrowed data escapes outside of function --> src/auth.rs:31:8 | 30 | pub async fn verify_passcode<'a>(pass: Passcode, hash: PasswordHash<'a>) -> Result<bool> { | -- ---- `hash`是仅在函数体内有效的引用 | | | 生命周期`'a`在此处定义 31 | Ok(task::spawn_blocking(move || argon2_verify(pass, hash)).await?) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | `hash`在此处逃逸出函数体 | 参数要求`'a`必须存活至`'static`
按照编译器提示,为hash指定'static生命周期可解决问题:
// 此代码可运行 pub async fn verify_passcode(pass: Passcode, hash: PasswordHash<'static>) -> Result<bool> { Ok(task::spawn_blocking(move || argon2_verify(pass, hash)).await?) }
但原本认为'a生命周期就足够,'static并非最优解,因此有两个疑问:
- 当
hash在闭包或阻塞线程作用域结束后不再被引用时,为何会逃逸出函数?'a生命周期为什么不够用? - 如何在不使用
'static生命周期的前提下解决该错误?
完整示例代码
use anyhow::Result; use argon2::{ password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, Argon2, }; use tokio::task::{self}; type Passcode = [u8; 32]; // 此代码无法运行——`hash`逃逸出函数体 pub async fn verify_passcode<'a>(pass: Passcode, hash: PasswordHash<'a>) -> Result<bool> { Ok(task::spawn_blocking(move || argon2_verify(pass, hash)).await?) } fn argon2_hash<'a>(pass: Passcode) -> Result<PasswordHash<'a>> { let salt = SaltString::generate(&mut OsRng); let argon2 = Argon2::default(); Ok(argon2.hash_password(&pass, &salt).unwrap()) } fn argon2_verify(pass: Passcode, hash: PasswordHash) -> bool { Argon2::default().verify_password(&pass, &hash).is_ok() }
内容的提问来源于stack exchange,提问作者David Prichard
相关产品推荐
相关产品推荐

