我在 Rust 中有一个“ View ”数据结构,其中包含对另一个数据结构的引用,并且我想自动测试在 View 数据结构上实现的 getter 方法。这是一个只有一个 getter 的 MRE:
/// View data structure.
struct View<'a> {
value: &'a u32,
}
impl<'a> View<'a> {
/// Getter method.
pub fn value(&self) -> u32 {
*self.value
}
}
/// Attempt to automate unit testing of the getter: create an underlying value,
/// then create a `View`, then apply the getter method to the `View` and ensure
/// we get the expected value out.
fn check_getter(getter: fn(&View) -> u32) {
let value: u32 = 7;
let view = View { value: &value };
assert!(getter(&view) == 7);
}
check_getter(View::value);
编译失败,出现以下错误:
mismatched types
expected fn pointer `for<'r, 's> fn(&'r tests::test_adcs::View<'s>) -> _`
found fn pointer `for<'r> fn(&'r tests::test_adcs::View<'_>) -> _`
我认为我需要使用 HRTB,并尝试了各种排列,但无法编译任何内容。
最佳答案
TL;DR:使用闭包(如果您愿意,可以使用宏):
check_getter(|v| v.value());
你掉进了early-bound vs. late-bound lifetimes的陷阱.
View::value
没有有签名 for<'a> fn <View<'a>>::value()
。相反,它具有签名 fn <View<'some_concrete_lifetime>>::value()
。即'a
不是任何生命周期,而是一些推断的生命周期。因此 HRTB 不起作用——只有一个生命周期与给定的函数匹配。 You can read more about early-bound and late-bound lifetimes in this recent answer I wrote ,但问题的关键在于,因为生命周期'a
出现在 impl
,而不是函数本身,它会成为早期绑定(bind),并且对于函数的每个实例只有一个具体的生命周期,而不是后期绑定(bind)并允许与任何生命周期一起使用。
修复方法只是用一个闭包包裹它,使其成为后期绑定(bind)。
关于rust - 使用 HRTB 自动化 getter 方法单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73006849/