Типы функциональных элементов
При ссылке на функциональный элемент или конструктор кортежной структуры или варианта перечисления получается значение нулевого размера его типа функционального элемента.
Этот тип явно идентифицирует функцию - ее имя, аргументы типа и ранние аргументы времени жизни (но не поздние аргументы времени жизни, которые назначаются только при вызове функции) - поэтому значение не нужно содержать фактический указатель на функцию, и не требуется косвенное обращение при вызове функции.
Нет синтаксиса, который бы непосредственно ссылался на тип функционального элемента, но
компилятор будет отображать тип как что-то вроде fn(u32) -> i32 {fn_name} в
сообщениях об ошибках.
Поскольку тип функционального элемента явно идентифицирует функцию, типы элементов разных функций - разных элементов или одного и того же элемента с разными обобщениями - различны, и их смешение вызовет ошибку типа:
#![allow(unused)] fn main() { fn foo<T>() { } let x = &mut foo::<i32>; *x = foo::<u32>; //~ ОШИБКА: несоответствие типов }
Однако существует приведение из функциональных элементов в указатели на функции с
той же сигнатурой, которое срабатывает не только когда функциональный элемент используется
там, где ожидается указатель на функцию, но и когда разные типы функциональных элементов с той же сигнатурой встречаются в разных ветвях одного if или
match:
#![allow(unused)] fn main() { let want_i32 = false; fn foo<T>() { } // `foo_ptr_1` здесь имеет тип указателя на функцию `fn()` let foo_ptr_1: fn() = foo::<i32>; // ... и `foo_ptr_2` тоже - это проходит проверку типов. let foo_ptr_2 = if want_i32 { foo::<i32> } else { foo::<u32> }; }
Все функциональные элементы реализуют Copy, Clone, Send и Sync.
Fn, FnMut и FnOnce реализуются, если только функция не имеет любого из следующего:
- квалификатор
unsafe - атрибут
target_feature - ABI, отличный от
"Rust"