quickcheck::Testable trait is not implemented for function?


Hi, I was trying out quickcheck today, and stumbled upon the as keyword in rust. Since I’m new to rust I am not sure I fully understand what this keyword does, except some kind of type casting.

Having this code as an example:

fn dummy() {
    fn prop(v: u16) -> TestResult {
        assert_eq!(double(v), v * 2);
    QuickCheck::new().quickcheck(prop as fn(u16) -> TestResult);

I don’t understand why it’s necessary to use prop as fn(u16) -> TestResult, and why changing that line to QuickCheck::new().quickcheck(prop); will result in the following error:

| ^^^^^^^^^^ the trait tests::quickcheck::Testable is not implemented for fn(u16) -> tests::quickcheck::TestResult {tests::dummy::prop}

Is it possible to use a closure ? Something like:

QuickCheck::new().quickcheck(|v: u16| {
            assert_eq!(double(v), v * 2);

What is the as keyword doing, and why is it necessary ?

Thank you all for being a great community !


It’s been an issue for a while: https://github.com/BurntSushi/quickcheck/issues/56

Here is a Rust tracking issue, specifically for making it work for closures: https://github.com/rust-lang/rust/issues/25041


In this case the as keyword is converting a specific function pointer into a general function pointer. All functions in Rust are qualified by their name, but can be coerced into a function pointer. But you can only coerce types at specific coercion points. You can only coerce types in places where all of the types are known! So, in the case of a generic function, where the types need to be inferred, Rust does not try to coerce types. This means that specific function pointers do not coerce into general function pointers. Closures that do not borrow from their environment at all can be coerced into a function pointer.


Thank you all for the explanation and information provided ! Now I have a better understanding of what’s actually happening. Have a nice weekend !