Почему ссылка на тип, который реализует Fn, не распознается как вызываемый? - PullRequest
0 голосов
/ 05 декабря 2018

Даже если &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

С nightly (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

Возможно, я что-то упускаю, но почему компилятор принимает определение, но не разрешает егобыть вызванным?Это синтаксический недостаток с моей стороны, который заставляет его понять что-то еще?

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Существует открытый выпуск (# 42736) по этому поводу.Тем не менее, документы для Fn состояния:

для любого типа F, который реализует Fn, &F также реализует Fn.

Это означает, что работает следующее:

fn test_ref_input_as_fntrait<'a, T>(t: &'a T)
where
    T: Fn(),
{
    t();
}
0 голосов
/ 05 декабря 2018

Возможно, это ошибка (например, она работает, если вы замените &'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!"));
}
...