我尝试使用Rust版本1.22.1编译以下代码:
use std::str::Split;
use std::iter::Peekable;
// This is fine...
fn tokenize<'a>(code: &'a str) -> Split<'a, fn(char) -> bool> {
code.split(char::is_whitespace)
}
// ...but this is not...
fn tokenize_peekable_bad<'a>(code: &'a str) -> Peekable<Split<'a, fn(char) -> bool>> {
code.split(char::is_whitespace).peekable()
}
// ...however this is?
fn tokenize_peekable<'a>(code: &'a str) -> Peekable<Split<'a, fn(char) -> bool>> {
tokenize(&code).peekable()
}
在我看来,tokenize_peekable_bad
和tokenize_peekable
应该具有完全相同的类型签名,但tokenize_peekable_bad
会产生编译错误,而tokenize_peekable
就好了。
错误是
error[E0308]: mismatched types
--> src/main.rs:11:5
|
11 | code.split(char::is_whitespace).peekable()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found fn item
|
= note: expected type `std::iter::Peekable<std::str::Split<'a, fn(char) -> bool>>`
found type `std::iter::Peekable<std::str::Split<'_, fn(char) -> bool {std::char::<impl char>::is_whitespace}>>`
有人可以解释这个令人费解的结果吗?
答案 0 :(得分:4)
您需要将函数指针从其特定的具体类型转换为非特定的函数指针类型:
fn tokenize_peekable_ok_now<'a>(code: &'a str) -> Peekable<Split<'a, fn(char) -> bool>> {
code.split(char::is_whitespace as fn(char) -> bool).peekable()
}
当您调用tokenize
函数时,您的工作解决方案会自动执行此操作,因为类型系统必须执行的步骤数只有一个(Split<'a, fn(char) -> bool {specific}>
- &gt; Split<'a, fn(char) -> bool>
)。在tokenize_peekable_bad
中,当它检查返回类型时,它已在Split
内部包裹Peekable
,因此它不知道将演员表流回到原来的位置。具体而言,它不在coercion site。
另见: