Orphan Rules
The orphan rule is a compile-time coherence restriction requiring that in every impl Trait for Type block, either Trait or Type (or both) must be defined in the current crate. You cannot implement an external trait (such as std::fmt::Display) for an external type (such as std::vec::Vec<T>).
Why the Orphan Rule Exists
Without the orphan rule, two independent library crates crate_a and crate_b could both define conflicting implementations of impl Display for Vec<u8>. If a binary crate depended on both crate_a and crate_b, the compiler would have no deterministic way to choose which Display implementation to run.
Trait Locality
Local Trait External Trait (e.g., Display)
+-------------------+------------------------------+
Local Type | ALLOWED | ALLOWED |
(e.g., MyVec) | impl MyTrait | impl Display |
| for MyVec | for MyVec |
+-------------------+------------------------------+
External Type | ALLOWED | FORBIDDEN (Orphan Rule E0117)|
(e.g., Vec<T>)| impl MyTrait | impl Display |
| for Vec<T> | for Vec<i32> (❌) |
+-------------------+------------------------------+
Compiler Diagnostic E0117
Attempting to implement std::fmt::Display directly for Vec<String> triggers error E0117:
// ❌ does not compile
use std::fmt;
impl fmt::Display for Vec<String> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.join(", "))
}
}
fn main() {}
error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> src/main.rs:4:1
|
4 | impl fmt::Display for Vec<String> {
| ^^^^^^^^^^^^^^^^^^^^^^-----------
| |
| `Vec` is not defined in the current crate
| `String` is not defined in the current crate
|
= note: impl doesn't have any local type before any uncovered type parameters
= note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
= note: define and implement a trait or new type instead
Bypassing the Orphan Rule with the Newtype Pattern
To implement an external trait on an external type, wrap the external type in a single-field local tuple struct—called a newtype (struct Wrapper(Vec<String>);). Because Wrapper is defined in your crate, the orphan rule allows implementing any external trait (Display, From, Deref) on Wrapper:
use std::fmt;
use std::ops::Deref;
struct CommaList(Vec<String>);
impl fmt::Display for CommaList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
}
// Optional: implement Deref so all &[String] / Vec<String> read methods work directly on CommaList
impl Deref for CommaList {
type Target = Vec<String>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn main() {
let list = CommaList(vec![
String::from("alpha"),
String::from("beta"),
String::from("gamma"),
]);
println!("Formatted: {list}");
println!("Length via Deref: {}", list.len());
}
Formatted: [alpha, beta, gamma]
Length via Deref: 3
Because a single-field tuple struct has the exact same memory representation as its inner field (Vec<String>), the newtype wrapper incurs zero runtime allocation or indirection cost.
Covered Generic Type Parameters in External Traits
When an external trait has generic type parameters (such as From<T>), you can implement From<LocalType> for ExternalType when your LocalType appears as a type argument before any uncovered generic type parameter:
struct UserId(u64);
// Allowed: `From<UserId>` is an external trait and `u64` is an external type,
// but the local type `UserId` appears in the trait's type parameter list!
impl From<UserId> for u64 {
fn from(id: UserId) -> Self {
id.0
}
}
fn main() {
let raw: u64 = u64::from(UserId(500));
println!("raw = {raw}");
}
raw = 500