Rust为Fn trait定义类型别名触发'static生命周期错误怎么解决?
错误原因
- Rust中的
trait对象默认携带'static生命周期约束,除非显式指定其他生命周期。 - 你最初的写法中,参数
pred: &dyn Fn(i32, i32) -> bool触发了编译器的生命周期自动省略规则,trait对象的生命周期会被推断为和引用本身的生命周期一致,因此可以正常捕获仅在run函数作用域内存在的map变量。 - 你定义类型别名
type XYPredicate = dyn Fn(i32, i32) -> bool;时没有声明生命周期,编译器默认给该类型加上了'static约束,后续参数pred: &XYPredicate就要求传入的闭包必须满足'static生命周期,而你使用的闭包捕获了局部变量map,生命周期仅在run函数内有效,不满足'static要求,因此触发生命周期不匹配的编译错误。
修复方案
给类型别名显式声明生命周期参数即可,正确的写法如下:
// 为类型别名绑定生命周期参数,表示该trait对象的生命周期为'a type XYPredicate<'a> = dyn Fn(i32, i32) -> bool + 'a; // 函数参数直接使用该类型即可,编译器会自动完成生命周期推断 fn compute_visible_tiles( x: i32, y: i32, range: i32, pred: &XYPredicate<'_>, ) -> Vec<(i32, i32)> { // 函数内部逻辑无需任何修改 let mut visible: Vec<(i32, i32)> = Vec::new(); let mut pos_x = x; let pos_y = y; while pred(pos_x, pos_y) && manhattan_dist(x, y, pos_x, pos_y) < range { visible.push((pos_x, pos_y)); pos_x += 1; } visible }
如果你不需要动态分发的特性,也可以改用泛型参数实现静态分发,性能更优,也不需要额外处理生命周期:
fn compute_visible_tiles<F: Fn(i32, i32) -> bool>( x: i32, y: i32, range: i32, pred: F, ) -> Vec<(i32, i32)> { // 内部逻辑和原来一致,调用时直接传入闭包即可,不需要取引用 }
内容的提问来源于stack exchange,提问作者Bernard Cloutier
相关产品推荐
相关产品推荐

