`, a vector with element type `A`.
diff --git a/src/types/pointer.md b/src/types/pointer.md
new file mode 100644
index 000000000..e61f0fa1d
--- /dev/null
+++ b/src/types/pointer.md
@@ -0,0 +1,57 @@
+# Pointer types
+
+All pointers in Rust are explicit first-class values. They can be moved or
+copied, stored into data structs, and returned from functions.
+
+## Shared references (`&`)
+
+> **Syntax**\
+> _ReferenceType_ :\
+> `&` [_Lifetime_]? `mut`? [_TypeNoBounds_]
+
+These point to memory _owned by some other value_. When a shared reference to
+a value is created it prevents direct mutation of the value. [Interior
+mutability] provides an exception for this in certain circumstances. As the
+name suggests, any number of shared references to a value may exit. A shared
+reference type is written `&type`, or `&'a type` when you need to specify an
+explicit lifetime. Copying a reference is a "shallow" operation: it involves
+only copying the pointer itself, that is, pointers are `Copy`. Releasing a
+reference has no effect on the value it points to, but referencing of a
+[temporary value] will keep it alive during the scope of the reference itself.
+
+## Mutable references (`&mut`)
+
+These also point to memory owned by some other value. A mutable reference type
+is written `&mut type` or `&'a mut type`. A mutable reference (that hasn't been
+borrowed) is the only way to access the value it points to, so is not `Copy`.
+
+## Raw pointers (`*const` and `*mut`)
+
+> **Syntax**\
+> _RawPointerType_ :\
+> `*` ( `mut` | `const` ) [_TypeNoBounds_]
+
+Raw pointers are pointers without safety or liveness guarantees. Raw pointers
+are written as `*const T` or `*mut T`, for example `*const i32` means a raw
+pointer to a 32-bit integer. Copying or dropping a raw pointer has no effect
+on the lifecycle of any other value. Dereferencing a raw pointer is an
+[`unsafe` operation], this can also be used to convert a raw pointer to a
+reference by reborrowing it (`&*` or `&mut *`). Raw pointers are generally
+discouraged in Rust code; they exist to support interoperability with foreign
+code, and writing performance-critical or low-level functions.
+
+When comparing pointers they are compared by their address, rather than by
+what they point to. When comparing pointers to [dynamically sized types] they
+also have their addition data compared.
+
+## Smart Pointers
+
+The standard library contains additional 'smart pointer' types beyond references
+and raw pointers.
+
+[Interior mutability]: interior-mutability.html
+[_Lifetime_]: trait-bounds.html
+[_TypeNoBounds_]: types.html#type-expressions
+[`unsafe` operation]: unsafety.html
+[dynamically sized types]: dynamically-sized-types.html
+[temporary value]: expressions.html#temporary-lifetimes
diff --git a/src/types/slice.md b/src/types/slice.md
new file mode 100644
index 000000000..3a5a05d08
--- /dev/null
+++ b/src/types/slice.md
@@ -0,0 +1,32 @@
+# Slice types
+
+> **Syntax**\
+> _SliceType_ :\
+> `[` [_Type_] `]`
+
+A slice is a [dynamically sized type] representing a 'view' into a sequence of
+elements of type `T`. The slice type is written as `[T]`.
+
+To use a slice type it generally has to be used behind a pointer for example
+as:
+
+* `&[T]`, a 'shared slice', often just called a 'slice', it doesn't own the
+ data it points to, it borrows it.
+* `&mut [T]`, a 'mutable slice', mutably borrows the data it points to.
+* `Box<[T]>`, a 'boxed slice'
+
+Examples:
+
+```rust
+// A heap-allocated array, coerced to a slice
+let boxed_array: Box<[i32]> = Box::new([1, 2, 3]);
+
+// A (shared) slice into an array
+let slice: &[i32] = &boxed_array[..];
+```
+
+All elements of slices are always initialized, and access to a slice is always
+bounds-checked in safe methods and operators.
+
+[_Type_]: types.html#type-expressions
+[dynamically sized type]: dynamically-sized-types.html
diff --git a/src/types/struct.md b/src/types/struct.md
new file mode 100644
index 000000000..a398d1b91
--- /dev/null
+++ b/src/types/struct.md
@@ -0,0 +1,28 @@
+# Struct types
+
+A `struct` *type* is a heterogeneous product of other types, called the
+*fields* of the type.[^structtype]
+
+New instances of a `struct` can be constructed with a [struct expression].
+
+The memory layout of a `struct` is undefined by default to allow for compiler
+optimizations like field reordering, but it can be fixed with the
+`#[repr(...)]` attribute. In either case, fields may be given in any order in a
+corresponding struct *expression*; the resulting `struct` value will always
+have the same memory layout.
+
+The fields of a `struct` may be qualified by [visibility modifiers], to allow
+access to data in a struct outside a module.
+
+A _tuple struct_ type is just like a struct type, except that the fields are
+anonymous.
+
+A _unit-like struct_ type is like a struct type, except that it has no fields.
+The one value constructed by the associated [struct expression] is the only
+value that inhabits such a type.
+
+[^structtype]: `struct` types are analogous to `struct` types in C, the
+ *record* types of the ML family, or the *struct* types of the Lisp family.
+
+[struct expression]: expressions/struct-expr.html
+[visibility modifiers]: visibility-and-privacy.html
diff --git a/src/types/textual.md b/src/types/textual.md
new file mode 100644
index 000000000..e5fe6db7a
--- /dev/null
+++ b/src/types/textual.md
@@ -0,0 +1,16 @@
+# Textual types
+
+The types `char` and `str` hold textual data.
+
+A value of type `char` is a [Unicode scalar value] (i.e. a code point that
+is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to
+0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` is effectively a UCS-4 / UTF-32
+string.
+
+A value of type `str` is a Unicode string, represented as an array of 8-bit
+unsigned bytes holding a sequence of UTF-8 code points. Since `str` is a
+[dynamically sized type], it is not a _first-class_ type, but can only be
+instantiated through a pointer type, such as `&str`.
+
+[Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
+[dynamically sized type]: dynamically-sized-types.html
diff --git a/src/types/trait-object.md b/src/types/trait-object.md
new file mode 100644
index 000000000..eb31a1bbd
--- /dev/null
+++ b/src/types/trait-object.md
@@ -0,0 +1,114 @@
+# Trait objects
+
+> **Syntax**\
+> _TraitObjectType_ :\
+> `dyn`? [_TypeParamBounds_]
+>
+> _TraitObjectTypeOneBound_ :\
+> `dyn`? [_TraitBound_]
+
+A *trait object* is an opaque value of another type that implements a set of
+traits. The set of traits is made up of an [object safe] *base trait* plus any
+number of [auto traits].
+
+Trait objects implement the base trait, its auto traits, and any [supertraits]
+of the base trait.
+
+Trait objects are written as the optional keyword `dyn` followed by a set of
+trait bounds, but with the following restrictions on the trait bounds. All
+traits except the first trait must be auto traits, there may not be more than
+one lifetime, and opt-out bounds (e.g. `?sized`) are not allowed. Furthermore,
+paths to traits may be parenthesized.
+
+For example, given a trait `Trait`, the following are all trait objects:
+
+* `Trait`
+* `dyn Trait`
+* `dyn Trait + Send`
+* `dyn Trait + Send + Sync`
+* `dyn Trait + 'static`
+* `dyn Trait + Send + 'static`
+* `dyn Trait +`
+* `dyn 'static + Trait`.
+* `dyn (Trait)`
+
+> **Edition Differences**: In the 2015 edition, if the first bound of the
+> trait object is a path that starts with `::`, then the `dyn` will be treated
+> as a part of the path. The first path can be put in parenthesis to get
+> around this. As such, if you want a trait object with the trait
+> `::your_module::Trait`, you should write it as `dyn (::your_module::Trait)`.
+>
+> Beginning in the 2018 edition, `dyn` is a true keyword and is not allowed in
+> paths, so the parentheses are not necessary.
+
+> Note: For clarity, it is recommended to always use the `dyn` keyword on your
+> trait objects unless your codebase supports compiling with Rust 1.26 or lower.
+
+Two trait object types alias each other if the base traits alias each other and
+if the sets of auto traits are the same and the lifetime bounds are the same.
+For example, `dyn Trait + Send + UnwindSafe` is the same as
+`dyn Trait + Unwindsafe + Send`.
+
+
+
+***Warning:*** With two trait object types, even when the complete set of traits
+is the same, if the base traits differ, the type is different. For example,
+`dyn Send + Sync` is a different type from `dyn Sync + Send`. See [issue 33140].
+
+
+
+Due to the opaqueness of which concrete type the value is of, trait objects are
+[dynamically sized types]. Like all
+DSTs, trait objects are used
+behind some type of pointer; for example `&dyn SomeTrait` or
+`Box`. Each instance of a pointer to a trait object includes:
+
+ - a pointer to an instance of a type `T` that implements `SomeTrait`
+ - a _virtual method table_, often just called a _vtable_, which contains, for
+ each method of `SomeTrait` and its [supertraits] that `T` implements, a
+ pointer to `T`'s implementation (i.e. a function pointer).
+
+The purpose of trait objects is to permit "late binding" of methods. Calling a
+method on a trait object results in virtual dispatch at runtime: that is, a
+function pointer is loaded from the trait object vtable and invoked indirectly.
+The actual implementation for each vtable entry can vary on an object-by-object
+basis.
+
+An example of a trait object:
+
+```rust
+trait Printable {
+ fn stringify(&self) -> String;
+}
+
+impl Printable for i32 {
+ fn stringify(&self) -> String { self.to_string() }
+}
+
+fn print(a: Box) {
+ println!("{}", a.stringify());
+}
+
+fn main() {
+ print(Box::new(10) as Box);
+}
+```
+
+In this example, the trait `Printable` occurs as a trait object in both the
+type signature of `print`, and the cast expression in `main`.
+
+## Trait Object Lifetime Bounds
+
+Since a trait object can contain references, the lifetimes of those references
+need to be expressed as part of the trait object. This lifetime is written as
+`Trait + 'a`. There are [defaults] that allow this lifetime to usually be
+inferred with a sensible choice.
+
+[_TraitBound_]: trait-bounds.html
+[_TypeParamBounds_]: types.html#type-expressions
+[auto traits]: special-types-and-traits.html#auto-traits
+[defaults]: lifetime-elision.html#default-trait-object-lifetimes
+[dynamically sized types]: dynamically-sized-types.html
+[issue 33140]: https://github.com/rust-lang/rust/issues/33140
+[object safe]: items/traits.html#object-safety
+[supertraits]: items/traits.html#supertraits
diff --git a/src/types/tuple.md b/src/types/tuple.md
new file mode 100644
index 000000000..195346b2d
--- /dev/null
+++ b/src/types/tuple.md
@@ -0,0 +1,34 @@
+# Tuple types
+
+> **Syntax**\
+> _TupleType_ :\
+> `(` `)`\
+> | `(` ( [_Type_] `,` )+ [_Type_]? `)`
+
+A tuple *type* is a heterogeneous product of other types, called the *elements*
+of the tuple. It has no nominal name and is instead structurally typed.
+
+Tuple types and values are denoted by listing the types or values of their
+elements, respectively, in a parenthesized, comma-separated list.
+
+Because tuple elements don't have a name, they can only be accessed by
+pattern-matching or by using `N` directly as a field to access the `N`th
+element.
+
+An example of a tuple type and its use:
+
+```rust
+type Pair<'a> = (i32, &'a str);
+let p: Pair<'static> = (10, "ten");
+let (a, b) = p;
+
+assert_eq!(a, 10);
+assert_eq!(b, "ten");
+assert_eq!(p.0, 10);
+assert_eq!(p.1, "ten");
+```
+
+For historical reasons and convenience, the tuple type with no elements (`()`)
+is often called ‘unit’ or ‘the unit type’.
+
+[_Type_]: types.html#type-expressions
diff --git a/src/types/union.md b/src/types/union.md
new file mode 100644
index 000000000..68f851549
--- /dev/null
+++ b/src/types/union.md
@@ -0,0 +1,15 @@
+# Union types
+
+A *union type* is a nominal, heterogeneous C-like union, denoted by the name of
+a [`union` item].
+
+A union contains the value of any one of its fields. Since the accessing the
+wrong field can cause unexpected or undefined behaviour, `unsafe` is required
+to read from a union field or to write to a field that doesn't implement
+[`Copy`].
+
+The memory layout of a `union` is undefined by default, but the `#[repr(...)]`
+attribute can be used to fix a layout.
+
+[`Copy`]: special-types-and-traits.html#copy
+[`union` item]: items/unions.html
diff --git a/src/unsafety.md b/src/unsafety.md
index 0f4fab9e6..e9bb78652 100644
--- a/src/unsafety.md
+++ b/src/unsafety.md
@@ -16,5 +16,5 @@ Rust:
[`union`]: items/unions.html
[mutable static variable]: items/static-items.html#mutable-statics
[external static variable]: items/external-blocks.html
-[raw pointer]: types.html#pointer-types
+[raw pointer]: types/pointer.html
[unsafe trait]: items/traits.html#unsafe-traits