함수 항목 타입

함수 항목 타입

함수 항목, 혹은 튜플 구조체나 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)**은 존재해요. 이 강제 변환은 함수 포인터가 직접 기대되는 자리에 함수 항목을 쓸 때뿐만 아니라, 같은 시그니처를 가진 서로 다른 함수 항목 타입들이 같은 ifmatch의 서로 다른 분기(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 호출 트레이트에 대해 더 살펴보면 함수 항목 타입이 실제 코드에서 어떤 자리를 차지하는지 명확해져요.