Rust生命周期问题:返回含本地闭包引用的futures-signals setter包装结构体报错如何解决
你的思路本身没有问题,报错的核心是你在SetterWrapper中存储了闭包的临时引用,而闭包是wrap_setter函数的局部变量,函数返回后闭包会被销毁,自然会产生悬垂引用错误。
修改方案
第一步:调整SetterWrapper定义
把deser_and_set字段从引用类型改为持有所有权的Box trait对象,绑定和入参Mutable一致的生命周期:
struct SetterWrapper<'a> { name: &'static str, deser_and_set: Box<dyn Fn(Value) -> Result<(), Error> + 'a>, // 其余不相关字段保持不变 }
如果你使用的futures-signals的Mutable是引用计数类型(默认实现就是Arc包装,clone成本极低),也可以选择去掉生命周期约束,后续使用更灵活:
// 无生命周期版本 struct SetterWrapper { name: &'static str, deser_and_set: Box<dyn Fn(Value) -> Result<(), Error>>, }
第二步:修改wrap_setter实现
给闭包加上move关键字捕获Mutable的引用/所有权,用Box::new包裹闭包存入包装器:
// 带生命周期版本 fn wrap_setter<'a, T>(name: &'static str, mutable: &'a Mutable<T>) -> SetterWrapper<'a> where T: for<'de> Deserialize<'de> { let deser_and_set = move |v: Value| { mutable.set(serde_json::from_value::<T>(v)?); Ok(()) }; SetterWrapper { name, deser_and_set: Box::new(deser_and_set), } }
如果用无生命周期版本,入参改为直接传Mutable(调用时clone即可):
// 无生命周期版本 fn wrap_setter<T>(name: &'static str, mutable: Mutable<T>) -> SetterWrapper where T: for<'de> Deserialize<'de> { let deser_and_set = move |v: Value| { mutable.set(serde_json::from_value::<T>(v)?); Ok(()) }; SetterWrapper { name, deser_and_set: Box::new(deser_and_set), } } // 调用示例 let my_int_setter = wrap_setter("my_int", my_int.clone());
修改后原有调用逻辑完全不需要改动,Box<dyn Fn>可以直接像函数引用一样执行。
内容的提问来源于stack exchange,提问作者Felk
相关产品推荐
相关产品推荐

