함수 항목 타입
함수 항목 타입
함수 항목, 혹은 튜플 구조체나 enum 변형(variant)의 생성자를 이름으로 가리키면, 그 이름은 **함수 항목 타입(function item type)**의 **크기 0 값(zero-sized value)**이 돼요.
출처: Rust Reference
본문
이 타입은 그 함수를 명시적으로 식별해요. 함수의 이름, 타입 인자, 그리고 early-bound 수명 인자(함수를 호출할 때에야 비로소 정해지는 late-bound 수명 인자는 제외)까지 모두 담고 있죠. 그래서 그 값이 실제 함수 포인터를 들고 있을 필요도 없고, 함수를 호출할 때 간접 참조(indirection)도 필요 없어요.
함수 항목 타입을 직접 가리키는 문법은 따로 없어요. 다만 컴파일러는 에러 메시지에서 이 타입을 fn(u32) -> i32 {fn_name}처럼 표시해 줘요.
함수 항목 타입이 함수를 정확히 식별하기 때문에, 서로 다른 함수의 항목 타입은 언제나 서로 다르다는 점이 중요해요. 다른 항목이든, 아니면 같은 항목에 다른 제네릭을 준 것이든 모두 별개의 타입이라서, 이들을 섞으면 타입 에러가 나요.
#![allow(unused)]
fn main() {
fn foo<T>() { }
let x = &mut foo::<i32>;
*x = foo::<u32>; //~ ERROR mismatched types
}
다만 같은 시그니처를 가진 함수 항목에서 **함수 포인터로의 강제 변환(coercion)**은 존재해요. 이 강제 변환은 함수 포인터가 직접 기대되는 자리에 함수 항목을 쓸 때뿐만 아니라, 같은 시그니처를 가진 서로 다른 함수 항목 타입들이 같은 if나 match의 서로 다른 분기(arm)에서 만날 때도 일어나요.
#![allow(unused)]
fn main() {
let want_i32 = false;
fn foo<T>() { }
// `foo_ptr_1` has function pointer type `fn()` here
let foo_ptr_1: fn() = foo::<i32>;
// ... and so does `foo_ptr_2` - this type-checks.
let foo_ptr_2 = if want_i32 {
foo::<i32>
} else {
foo::<u32>
};
}
모든 함수 항목은 Copy, Clone, Send, Sync를 구현해요. 그리고 다음 중 어느 하나라도 해당하지 않는 한 Fn, FnMut, FnOnce도 구현해요.
unsafe한정자(qualifier)가 붙어 있거나target_feature속성이 있거나- ABI가
"Rust"가 아니거나
더 알아보기
- 함수 포인터 타입과의 관계, 그리고
Fn/FnMut/FnOnce호출 트레이트에 대해 더 살펴보면 함수 항목 타입이 실제 코드에서 어떤 자리를 차지하는지 명확해져요.