The Periodic Table of Rust Types
|
Immutable Pointer |
Mutable Pointer |
Owned Pointer |
|
Bare |
Unsized |
Raw |
*T
Immutable raw pointer
|
*mut T
Mutable raw pointer
|
Raw pointers do not have ownership, *T or *mut T should be used as appropriate.
|
|
|
|
|
|
|
Simple |
&'r T
Immutable borrowed reference
|
&'r mut T
Mutable borrowed reference
|
~T
Owned pointer
|
|
T
Primitive type, struct, enum and so on
|
Trait |
&'r Trait:K
Immutable borrowed trait object
|
&'r mut Trait:K
Mutable borrowed trait object
|
~Trait:K
Owned trait object
|
|
Trait
Unsized trait type
Impossible today, the trait should be wrapped inside a box.
|
Vector |
&'r [T]
Immutable borrowed vector slice
|
&'r mut [T]
Mutable borrowed vector slice
|
~[T]
Owned vector
|
|
[T, ..n]
Fixed-size vector
|
[T]
Unsized vector type
Impossible today, the vector should know its size at compile time or be wrapped inside a box.
|
String |
&'r str
Immutable borrowed string slice
|
&'r mut str
Mutable borrowed string slice
Impossible today, there are few operations available to the fixed-size mutable slice.
|
~str
Owned string
|
|
Fixed sized storage is impractical for the variable length UTF-8 encoding.
|
str
Unsized string type
Impossible today, the string should be wrapped inside a box.
|
|
|
|
|
|
|
|
Call-many |
&'r Fn<T…, U>:K
Closure with immutable environment
Impossible today, closures always assume a mutable environment.
|
'r |T…|:K -> U
≡ &'r mut FnMut<T…, U>:K
Closure with mutable environment
|
~Fn<T…, U>:K
~FnMut<T…, U>:K
Closure with owned environment
Impossible today, closures cannot be sent.
|
|
extern "ABI" fn(T…) -> U
Bare function type
|
|
Call-once |
Procedures should be able to be consumed.
|
Procedures should be able to be consumed.
|
proc(T…) -> U
≡ ~FnOnce<T…, U>:K
Procedure with owned environment
|
|
|
| Supported as of 0.10 |
| Proposed |
| Impossible |
'r Lifetime |
:K Trait bounds |
T… Function arguments |
-> U Function return |
extern "ABI" ABI definition |
What is this?
This "periodic table" is a cheatsheet for various Rust types. Rust programming language has a versatile type system that avoids a certain class of memory error in the safe context, and consequently has somewhat many types at the first glance. This table organizes them into an orthogonal tabular form, making them easier to understand and reason. I also hope that this makes very obvious why Rust needs such seemingly many types.
The periodic table was made by Kang Seonghoon as a thought experiment, and then... it have got redditted unexpectedly :p Henceforth I've made the URL permanent and added some descriptions. Some post-reddit changes include:
- 2014-01-15 08:30 UTC: The table was updated slightly to include a missing fixed-size vector
[T, ..n]
, so it has a new "unsized" column now.
- 2014-01-16 19:00 UTC: Axes and labels are now close to the official terminology. Proposed types are hidden by default (they led to much confusion). The trait row is now below the simple row, since these two rows have related to each other (particularly, types in the simple row can be coerced into those in the trait row). The unboxed types (
T
) occupy two cells since you can use trait methods to those types. Also proposed function traits are updated and some of them are marked impossible as per the comments by glaebhoerl. Thanks everyone in /r/rust and #rust-internals for suggestions!
- 2014-01-17 19:00 UTC: The table now reflects the fact that bare function types can be coerced into procedures.
Discussion: /r/rust, /r/programming, Hacker News
Guide
Columns indicate the ownership. There are two big groups from left to right: indirect (i.e. pointers) and direct. Particularly indirect types can be coerced horizontally: ~T
can be coerced to &mut T
or &T
and &mut T
can be coerced to &T
.
Rows indicate the different kind of types. There are three big groups from top to bottom: unsafe dereference, safe dereference and callable.
Colored backgrounds (sorry the accessibility!) indicate the current availability. Black background means the type is plain absurd and prohibited. Gray background means the type makes some sense but it is not yet in the language. Fortunately we have two proposals that cover all the missing types now:
- Dynamically sized types proposal (a.k.a. DST) brings unsized types to the language. Normally most types including borrowed references and owned pointers have their size known and thus are "sized", but
[T]
, str
and Trait
do not have their size known in the compile time. The proposal allows them in the limited context, and that is primarily useful for fully supporting custom smart pointers. This also has a side effect that allows for &mut str
, though it won't see much use since safe strings cannot be modified via indexing.
- Variadic generics proposal brings a variadic number of generic parameters, similar to that of C++11. Consequently it can turn closures and procedures into simple traits. The exact interface is not yet settled (one of the possible interface discussed is indicated below in the small print) so it can look differently in the future.
There are some optional syntactic parts possible in types. Many of them are turned off by default since they are normally verbose, but you can turn them on if you want.
Copyright © 2014, Kang Seonghoon. This work is licensed under a Creative Commons Attribution 4.0 International License.
a part of cosmic.mearie.org.