我写了一些编译好的代码,然后我转了 T
进入 Option<T>
现在我收到了这个错误:
error[E0308]: mismatched type...one type is more general than the other
在构建最小案例时,我注意到如果我更改 data: &str
进入 data: String
代码再次编译正常。Playground link
pub trait Subscriber {
fn recv(&mut self, data: &str);
}
pub struct Task<T>(pub Option<T>)
where
T: Fn(&str);
impl<T> Subscriber for Task<T>
where
T: Fn(&str),
{
fn recv(&mut self, data: &str) {
self.0.take().unwrap()(data)
}
}
fn main() {
Task(Some(|_| ()));
}
有人可以帮助我了解这里发生了什么吗?
最佳答案
你似乎在编译器中遇到了一个怪癖。马桶盖 ( |_|()
) 泛化为一个函数,该函数在其输入类型 ( <T> Fn(T)
) 上是通用的,
但这种方式在 T
的生命周期内无法满足预期的约束.我们在这里需要的是一个函数,由于边界for<'a> Fn(&'a str)
,它在输入的生命周期内是通用的。在执行 Subscriber
为 Task<T>
.
(由于当前的生命周期省略规则, Subscriber
中排名较高的特征边界可以在不明确指示的情况下写入 for<'a>
。为清楚起见,在上一段中进行了扩展。)
如果您尝试实际使用 Task
,编译器会更清楚地说明这一点。值作为 Subscriber
:
let mut task = Task(Some(|_| ()));
task.recv("Message");
错误信息:error[E0599]: no method named `recv` found for struct `Task<[closure@src/main.rs:19:30: 19:36]>` in the current scope
--> src/main.rs:20:10
|
5 | / pub struct Task<T>(pub Option<T>)
6 | | where
7 | | T: Fn(&str);
| | -
| | |
| |________________method `recv` not found for this
| doesn't satisfy `_: Subscriber`
...
19 | let mut task = Task(Some(|_| ()));
| ------
| |
| doesn't satisfy `<_ as std::ops::FnOnce<(&str,)>>::Output = ()`
| doesn't satisfy `_: std::ops::Fn<(&str,)>`
20 | task.recv("Message");
| ^^^^ method not found in `Task<[closure@src/main.rs:19:30: 19:36]>`
|
= note: the method `recv` exists but the following trait bounds were not satisfied:
`<[closure@src/main.rs:19:30: 19:36] as std::ops::FnOnce<(&str,)>>::Output = ()`
which is required by `Task<[closure@src/main.rs:19:30: 19:36]>: Subscriber`
`[closure@src/main.rs:19:30: 19:36]: std::ops::Fn<(&str,)>`
which is required by `Task<[closure@src/main.rs:19:30: 19:36]>: Subscriber`
通过明确地将闭包的单个输入参数标记为引用,闭包将不再泛化参数类型 T
,但在引用输入的更高排名生命周期内'a
在 &'a _
.let mut task = Task(Some(|_: &_| ()));
task.recv("Message");
Playground .虽然并非不可能,但调整编译器以成功推断原始闭包的正确类型可能需要对当前的单态化规则进行重大更改。
也可以看看:
关于rust - 为什么 "one type is more general than the other"在包含闭包的选项中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63916821/