Rust中参数改为&mut u8为何导致fn item无法转为fn pointer?
问题分析与解决办法
为什么参数改成&mut u8会报错?
当haha的参数是u8时,这个async函数返回的impl Future不依赖任何外部生命周期——因为u8是值类型,没有生命周期关联,编译器可以自动让它满足'static约束,所以能直接适配set_func要求的fn(u8) -> T函数指针(其中T: 'static)。
但把参数换成&mut u8后,情况变了:async函数会捕获参数的生命周期'a,返回的impl Future实际上是impl Future<Output=u8> + 'a——它的生命周期和输入的&mut u8绑定,不再是'static。而set_func里的约束要求T: 'static,这就导致函数项haha无法被转换为符合要求的函数指针:函数指针要求返回的T必须是固定的'static类型,但haha的返回Future的生命周期是随输入参数变化的,两者的泛型约束不匹配,所以编译器报错“one type is more general than the other”。
保留&mut u8参数的解决方法
方法1:调整set_func的生命周期约束,让返回Future的生命周期和参数绑定
修改set_func,引入生命周期参数,让T的生命周期和输入的&mut u8对齐,而不是强制要求'static:
use core::future::Future; async fn haha(ctx: &mut u8) -> u8 { 2u8 } // 新增生命周期参数'a,绑定输入参数和返回Future的生命周期 fn set_func<'a, T>(path: &'static str, f: fn(&'a mut u8) -> T) -> u8 where T: Future<Output = u8> + Send + 'a, { 8u8 } fn main() { set_func("haha", haha); }
方法2:用高阶生命周期(HRTB)支持任意生命周期的参数
如果set_func需要接受适配任意生命周期的函数,可以用HRTB语法,让函数指针支持所有可能的'a生命周期:
use core::future::Future; async fn haha(ctx: &mut u8) -> u8 { 2u8 } // 使用for<'a>语法,让函数指针适配任意生命周期的&mut u8参数 fn set_func<T>(path: &'static str, f: for<'a> fn(&'a mut u8) -> T) -> u8 where T: for<'a> Future<Output = u8> + Send + 'a, { 8u8 } fn main() { set_func("haha", haha); }
补充说明
如果你的场景必须要求T: 'static,那只能把&mut u8包装成拥有'static生命周期的类型(比如Box<mut u8>),但这会改变函数的参数类型,不符合你“保留&mut u8参数”的要求,所以优先推荐前两种方法。
内容的提问来源于stack exchange,提问作者Kenneth
相关产品推荐
相关产品推荐

