Extending Foreign Types
An extension trait is a local trait definition whose primary purpose is to attach new methods to foreign types.
#![allow(unused)] fn main() { mod ext { pub trait StrExt { fn is_palindrome(&self) -> bool; } impl StrExt for &str { fn is_palindrome(&self) -> bool { self.chars().eq(self.chars().rev()) } } } // Bring the extension trait into scope... pub use ext::StrExt as _; // ...then invoke its methods as if they were inherent methods assert!("dad".is_palindrome()); assert!(!"grandma".is_palindrome()); }
-
The
Extsuffix is conventionally attached to the name of extension traits.It communicates that the trait is primarily used for extension purposes, and it is therefore not intended to be implemented outside the crate that defines it.
Refer to the “Extension Trait” RFC as the authoritative source for naming conventions.
-
The extension trait implementation for a foreign type must be in the same crate as the trait itself, otherwise you’ll be blocked by Rust’s orphan rule.
-
The extension trait must be in scope when its methods are invoked.
Comment out the
usestatement in the example to show the compiler error that’s emitted if you try to invoke an extension method without having the corresponding extension trait in scope. -
The example above uses an underscore import (
use ext::StringExt as _) to minimize the likelihood of a naming conflict with other imported traits.With an underscore import, the trait is considered to be in scope and you’re allowed to invoke its methods on types that implement the trait. Its symbol, instead, is not directly accessible. This prevents you, for example, from using that trait in a
whereclause.Since extension traits aren’t meant to be used in
whereclauses, they are conventionally imported via an underscore import.