即使将&T
定义为实现Fn
特质,编译器在调用它作为可调用对象时也会拒绝它:
trait Trait {
fn act(self);
}
//passes
fn test_ref_input_as_trait<'a, T>(t: &'a T)
where
&'a T: Trait,
{
t.act();
}
//fails
fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
where
&'a T: Fn(),
{
t();
}
//passes
fn test_input_as_fntrait<T>(t: T)
where
T: Fn(),
{
t();
}
编译器使用以下命令拒绝第二个函数的定义:
error[E0618]: expected function, found `&'a T`
--> src/lib.rs:18:5
|
14 | fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
| - `&'a T` defined here
...
18 | t();
| ^^^ not a function
在每晚(1.32)时,错误消息将替换为:
error[E0618]: expected function, found `&'a T`
--> src/lib.rs:18:5
|
14 | fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
| - `&'a T` defined here
...
18 | t();
| ^--
| |
| call expression requires function
也许我遗漏了一些东西,但是为什么编译器会接受该定义但不允许调用它?在我这方面的语法缺陷是否使它理解其他问题?
答案 0 :(得分:4)
有一个open issue (#42736)。但是,docs for Fn
状态:
对于任何实现
F
的类型Fn
,&F
也实现Fn
。
这意味着可以进行以下操作:
fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
where
T: Fn(),
{
t();
}
答案 1 :(得分:3)
这可能是一个错误(例如,如果您将&'a T
替换为(&'a T,)
,它将起作用)。不过,您可以这样调用函数:
fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
where
&'a T: Fn(),
{
(&t)();
}
但是由于T: Fn()
会自动包含&T: Fn()
,因此像上一个示例一样编写起来会更容易和习惯。
fn test_ref_input_as_fntrait<F: Fn()>(t: F) {
t();
}
fn main() {
test_ref_input_as_fntrait(&|| println!("it's okay!"));
}