]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/types/trait-object.md
New upstream version 1.38.0+dfsg1
[rustc.git] / src / doc / reference / src / types / trait-object.md
CommitLineData
13cf67c4
XL
1# Trait objects
2
3> **<sup>Syntax</sup>**\
4> _TraitObjectType_ :\
5> &nbsp;&nbsp; `dyn`<sup>?</sup> [_TypeParamBounds_]
6>
7> _TraitObjectTypeOneBound_ :\
8> &nbsp;&nbsp; `dyn`<sup>?</sup> [_TraitBound_]
9
10A *trait object* is an opaque value of another type that implements a set of
11traits. The set of traits is made up of an [object safe] *base trait* plus any
12number of [auto traits].
13
14Trait objects implement the base trait, its auto traits, and any [supertraits]
15of the base trait.
16
17Trait objects are written as the optional keyword `dyn` followed by a set of
18trait bounds, but with the following restrictions on the trait bounds. All
19traits except the first trait must be auto traits, there may not be more than
532ac7d7 20one lifetime, and opt-out bounds (e.g. `?Sized`) are not allowed. Furthermore,
13cf67c4
XL
21paths to traits may be parenthesized.
22
23For example, given a trait `Trait`, the following are all trait objects:
24
25* `Trait`
26* `dyn Trait`
27* `dyn Trait + Send`
28* `dyn Trait + Send + Sync`
29* `dyn Trait + 'static`
30* `dyn Trait + Send + 'static`
31* `dyn Trait +`
32* `dyn 'static + Trait`.
33* `dyn (Trait)`
34
35> **Edition Differences**: In the 2015 edition, if the first bound of the
36> trait object is a path that starts with `::`, then the `dyn` will be treated
37> as a part of the path. The first path can be put in parenthesis to get
38> around this. As such, if you want a trait object with the trait
39> `::your_module::Trait`, you should write it as `dyn (::your_module::Trait)`.
40>
41> Beginning in the 2018 edition, `dyn` is a true keyword and is not allowed in
42> paths, so the parentheses are not necessary.
43
44> Note: For clarity, it is recommended to always use the `dyn` keyword on your
45> trait objects unless your codebase supports compiling with Rust 1.26 or lower.
46
47Two trait object types alias each other if the base traits alias each other and
48if the sets of auto traits are the same and the lifetime bounds are the same.
49For example, `dyn Trait + Send + UnwindSafe` is the same as
50`dyn Trait + Unwindsafe + Send`.
51
52<div class="warning">
53
54***Warning:*** With two trait object types, even when the complete set of traits
55is the same, if the base traits differ, the type is different. For example,
56`dyn Send + Sync` is a different type from `dyn Sync + Send`. See [issue 33140].
57
58</div>
59
60Due to the opaqueness of which concrete type the value is of, trait objects are
61[dynamically sized types]. Like all
62<abbr title="dynamically sized types">DSTs</abbr>, trait objects are used
63behind some type of pointer; for example `&dyn SomeTrait` or
64`Box<dyn SomeTrait>`. Each instance of a pointer to a trait object includes:
65
66 - a pointer to an instance of a type `T` that implements `SomeTrait`
67 - a _virtual method table_, often just called a _vtable_, which contains, for
68 each method of `SomeTrait` and its [supertraits] that `T` implements, a
69 pointer to `T`'s implementation (i.e. a function pointer).
70
71The purpose of trait objects is to permit "late binding" of methods. Calling a
72method on a trait object results in virtual dispatch at runtime: that is, a
73function pointer is loaded from the trait object vtable and invoked indirectly.
74The actual implementation for each vtable entry can vary on an object-by-object
75basis.
76
77An example of a trait object:
78
79```rust
80trait Printable {
81 fn stringify(&self) -> String;
82}
83
84impl Printable for i32 {
85 fn stringify(&self) -> String { self.to_string() }
86}
87
88fn print(a: Box<dyn Printable>) {
89 println!("{}", a.stringify());
90}
91
92fn main() {
93 print(Box::new(10) as Box<dyn Printable>);
94}
95```
96
97In this example, the trait `Printable` occurs as a trait object in both the
98type signature of `print`, and the cast expression in `main`.
99
100## Trait Object Lifetime Bounds
101
102Since a trait object can contain references, the lifetimes of those references
103need to be expressed as part of the trait object. This lifetime is written as
104`Trait + 'a`. There are [defaults] that allow this lifetime to usually be
105inferred with a sensible choice.
106
416331ca
XL
107[_TraitBound_]: ../trait-bounds.md
108[_TypeParamBounds_]: ../types.md#type-expressions
109[auto traits]: ../special-types-and-traits.md#auto-traits
110[defaults]: ../lifetime-elision.md#default-trait-object-lifetimes
111[dynamically sized types]: ../dynamically-sized-types.md
13cf67c4 112[issue 33140]: https://github.com/rust-lang/rust/issues/33140
416331ca
XL
113[object safe]: ../items/traits.md#object-safety
114[supertraits]: ../items/traits.md#supertraits