Rust에서는 trait를 특정 유형에 대해 구현할 수 있는 경우는 다음과 같습니다:
이러한 조건을 고아 규칙(Orphan Rule)이라고 합니다. 이는 다른 crate에서 동일한 유형에 대해 동일한 trait가 독립적으로 구현되는 경우의 충돌을 방지합니다.
외부 유형에 대해 외부 trait를 구현하려면 직접적으로는 불가능합니다. 일반적으로 "newtype" 패턴을 사용합니다: 유형을 현재 crate 내의 구조체로 래핑한 다음, 자신의 유형에 대해 trait를 구현합니다.
예:
// 외부 유형 및 외부 trait (현재 crate에 없음) // struct ExternalType; trait ExternalTrait { ... } struct MyWrapper(ExternalType); impl ExternalTrait for MyWrapper { /* ... */ } // 이제 래퍼를 통해 작업합니다
질문: 외부 trait와 외부 유형이 모두 공개인 경우, use와 impl을 통해 외부 유형에 대해 외부 trait를 구현할 수 있나요?
잘못된 답변: 예, 단순히 자신의 crate에서 impl을 선언하면 됩니다, 그러면 모든 것이 작동합니다.
올바른 답변: 아니요, 컴파일러가 그것을 허용하지 않습니다. trait 또는 유형이 현재 crate에서 선언된 경우에만 trait를 구현할 수 있습니다. 그렇지 않으면 고아 규칙 오류가 발생합니다.
오류 예:
// extern crate other; // impl Display for other::ExternalType { ... } // 고아 규칙 오류
이야기
팀에서 외부 trait에 대한 impl을 통해 외부 로거의 지원이 필요하게 되었습니다. 외부 유형에 대해 구현하려고 했으나 고아 규칙 오류가 발생하고 그 원인에 대한 논쟁이 길어졌습니다. 결국 newtype에 맞춰 아키텍처를 재구성해야 했습니다.
이야기
오픈 소스 프로젝트에서 다른 라이브러리의 구조체에 대해 Debug를 구현하기로 했지만, 고아 규칙이 허용하지 않았습니다. 그 결과, 사용자들은 불편한 우회 방법을 사용해야 했고 자신만의 래퍼를 작성해야 했습니다.
이야기
심각한 버그: 외부 enum에 대해 문자열 파싱을 위해 FromStr을 구현하려고 했으나, 컴파일러가 고아 규칙을 통과하지 못했습니다. 개발자는 unsafe 변환을 통해 문제를 "해결"하려고 했고, 이는 생산 환경에서 UB를 유발했습니다.