The 以下代码是完整的类型注释:
fn enter<'a, F, R>(x: &'a i32, func: F) -> R
where
F: for<'b> FnOnce(&'b i32) -> R,
{
func(x)
}
fn identity<'a>(x: &'a i32) -> &'a i32 {
x
}
fn main() {
let x = &42;
enter(x, identity);
}
编译器编译的时候报错:
error[E0308]: mismatched types
--> src/main.rs:14:5
|
14 | enter(x, identity);
| ^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected trait `for<'b> FnOnce<(&'b i32,)>`
found trait `for<'a> FnOnce<(&'a i32,)>`
note: the lifetime requirement is introduced here
--> src/main.rs:3:35
|
3 | F: for<'b> FnOnce(&'b i32) -> R,
| ^
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error
我的理解是特质绑定for<'b> FnOnce(&'b i32) -> R
比更一般identity
的签名for<'a> fn(&'a i32) -> &'a i32
,所以它应该通过。
然而,通用的-> R
似乎是停止编译的罪魁祸首,但我不知道为什么。
我注意到有类似的问题,但他们遇到了错误,因为他们的类型没有完全注释并且编译器错误地推断了类型。
Related:
- Rust“预期类型”错误打印完全相同的不匹配类型
- 一种类型(函数指针)比另一种更通用
- Rust 中的“一种类型比另一种更普遍”错误,而类型相同
- 为 Fn 特征创建别名会导致“一种类型比另一种类型更通用”错误
- https://users.rust-lang.org/t/solved-one-type-is-more-general-than-the-other-but-they-are-exactly-the-same/25194
我的理解是特质绑定for<'b> FnOnce(&'b i32) -> R
比更一般identity
的签名for<'a> fn(&'a i32) -> &'a i32
,所以它应该通过。
不它不是。什么时候R
被宣布,'b
不在上下文中,因此它不能依赖于它(这是查看这一点的一种方式,还有其他方式)。
This is 必要的对于像这样的 APIstd::thread::LocalKey::with()健全:如果R
被允许包含生命周期(在以下情况下隐含)with()
),对线程本地的引用可以逃脱闭包并且with()
,然后在不同的线程上使用,造成UB。
据我所知,没有办法拥有通用的返回类型并允许它引用参数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)