Skip to content

Dyn compatibility

Level: 301 · deep dive

One line: A trait can be used as dyn Trait only if the compiler can build a vtable for it — no generic methods, no Self outside the receiver, no associated constants — and where Self: Sized is how a trait keeps such a method for concrete types while staying usable as dyn.

Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The bullets below are the questions the finished page has to answer.

What it has to cover

  • The Reference's rules on 1.98.0, one failing trait each: every supertrait dyn compatible, no Sized supertrait, no associated constants, no associated types with generics, and every method either dispatchable — no type parameters, Self only in the receiver, a receiver of &self, &mut self, Box<Self>, Rc<Self>, Arc<Self> or Pin<P> of one of those, no async fn, no return-position impl Trait — or explicitly non-dispatchable with where Self: Sized
  • The fix the compiler does not suggest: for fn scaled(&self, factor: f64) -> Self; the 1.98.0 E0038 says …because method scaled references the Self type in its return type and helps with consider moving scaled to another trait, while adding where Self: Sized to that one method makes Vec<Box<dyn Shape>> compile and keeps Square(1.0).scaled(3.0) working
  • What where Self: Sized costs: the method cannot be called on a Box<dyn Shape> — what does that error say, and is it better or worse than splitting the trait?
  • Splitting instead: a dyn-compatible core trait plus an extension trait with a blanket impl for the generic methods (Extension traits) — when is that worth a second trait name?
  • The name: object safety became dyn compatibility in rust-lang/rust PR #130826, merged September 2024 for 1.83.0. The Reference now notes the concept was formerly known as object safety, while the API Guidelines' C-OBJECT still says "object-safe" — search with both words
  • async fn: a trait with one is refused as dyn — …because method fetch is async on 1.98.0 — unless that method carries where Self: Sized, and the AsyncFn traits are not dyn compatible either. What do crates that need dyn and async methods together do instead?
  • The Cargo SemVer reference lists "adding a trait item that makes the trait non-object safe" as a major change — see SemVer hazards
  • Rust for Rustaceans ch. 3 → "Flexible" → "Object Safety" as the source, under its old name

The trap it exists for

Adding one convenience method — fn boxed_clone(&self) -> Self, or fn map<F: Fn(u32) -> u32>(&self, f: F) — to a trait your callers hold as Box<dyn Trait>. Your crate compiles and its tests pass, because nothing inside it writes dyn; the E0038 appears in theirs, at their dyn, after they upgrade.

Where this sits

Static vs dynamic dispatch introduces E0038 with a generic method and explains the rename; Returning a trait covers -> impl Trait against Box<dyn Trait>; Reading the ToOwned docs reads a not dyn compatible badge. This page is the trait author's side: the whole rule list, and how to keep a method without losing dyn.

See also

If you are coming from another language

  • C++. A member function template cannot be virtual — the same rule as "no generic methods in a dyn trait", for the same reason: a vtable has one slot per function, and a template is not one function.
  • Java. Any interface can be used as a type, generic methods included, because generics are erased and every object is already behind a reference. None of these restrictions has a Java counterpart, because none of Rust's per-type code generation does either.

Po polsku

Cecha nadaje się do użycia jako dyn Trait (dyn compatible, dawniej object safe) tylko wtedy, gdy kompilator może zbudować dla niej tablicę metod wirtualnych: bez metod generycznych, bez Self poza odbiorcą, bez stałych skojarzonych. Metodę łamiącą te zasady można zachować, dopisując where Self: Sized — wtedy działa dla typów konkretnych i znika z dyn. Pułapka autora biblioteki: dodanie jednej wygodnej metody nie psuje jego kompilacji, tylko kod użytkowników, którzy trzymają Box<dyn Trait>.

Szukaj po polsku: obiekt cechy · zgodność z dyn · rust dyn compatibility · rust object safety where Self: Sized · rust E0038