kirelagin
kirelagin

Reputation: 13616

Explicitly cast a type that involves a specific function item type

Here is an example:

use std::iter::Filter;
use std::slice::Iter;

fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
    fn nothing(_: &&i32) -> bool { false }

    let ys = xs.iter().filter(nothing);
    ys
}

fn main () {
}

Compilation fails with:

src/main.rs:8:5: 8:7 error: mismatched types:
 expected `core::iter::Filter<core::slice::Iter<'_, i32>, fn(&&i32) -> bool>`,
    found `core::iter::Filter<core::slice::Iter<'_, i32>, fn(&&i32) -> bool {test1::nothing}>`
(expected fn pointer,
    found fn item) [E0308]
src/main.rs:8     ys
                  ^~

This is because the inferred type of ys has the type of a specific function item in it. In this particular case the issue is easy to fix: one can either explicitly specify the type without the function item in the binding, or avoid the let altogether.

Both of these work:

fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
    fn nothing(_: &&i32) -> bool { false }

    let ys: Filter<Iter<i32>, fn(&&i32) -> bool> = xs.iter().filter(nothing);
    ys
}
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
    fn nothing(_: &&i32) -> bool { false }

    xs.iter().filter(nothing)
}

Therefore, as the Reference says, indeed Rust is capable of performing this coercion itself. But what if the code was more complex and I had to perform this cast manually? How would I do this?

In this case as won’t work, and transmute seems to be an overkill, although, I believe, it would do the job.

Upvotes: 2

Views: 319

Answers (1)

Matthieu M.
Matthieu M.

Reputation: 299810

You can actually cast using as:

fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
    fn nothing(_: &&i32) -> bool { false }

    let ys = xs.iter().filter(nothing as fn(&&i32) -> bool);
                                      ^~~~~~~~~~~~~~~~~~~~
    ys
}

However you need to use as to change the function's type, not the Filter type, as as is not allowed to change arbitrary types.


Personally, I consider the necessity of the cast a short-coming and hope that type inference will improve to the point it becomes unnecessary. The fact that it works for a direct return is a red-herring, it should probably work with an intermediate value too.

Upvotes: 3

Related Questions