rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.04k stars 12.69k forks source link

custom_test_frameworks doesn't work with plain functions #65210

Open exFalso opened 5 years ago

exFalso commented 5 years ago

The following code:

#![feature(custom_test_frameworks)]
#![test_runner(my_test_runner)]

fn my_test_runner(tests: &[&fn() -> ()]) {
    for test in tests {
        test();
    }
}

#[test_case]
fn test_1() {}

#[test_case]
fn test_2() {}

results in

11 | fn test_1() {}
   | ^^^^^^^^^^^^^^ expected fn pointer, found fn item
   |
   = note: expected type `&fn()`
              found type `&fn() {test_1}`

The workaround mentioned in https://stackoverflow.com/questions/27895946/expected-fn-item-found-a-different-fn-item-when-working-with-function-pointer doesn't work, as these functions are passed in by the compiler, so we cannot do the coercion.

Other variants that don't work:

fn my_test_runner(tests: &[fn() -> ()]) {
fn my_test_runner<F: Fn() -> ()>(tests: &[F]) {
fn my_test_runner<F: Fn() -> ()>(tests: &[&F]) {
exFalso commented 5 years ago

If anyone hits this, my current workaround is to use static lambdas, i.e:

#[test_case]
static TEST_1: fn() -> () = || {};

#[test_case]
static TEST_2: fn() -> () = || {};
yannick-was-taken commented 1 year ago

Note for anyone coming across this issue:

You can use dyn Fn() instead of &fn() -> (), which works:

fn my_test_runner(tests: &[&dyn Fn()]) {
    for test in tests {
        test();
    }
}