From defdc4418a2da483f8adeb2928c1ba1cddc5f7de Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 21 Apr 2015 19:44:54 -0400 Subject: [PATCH] TRPL: type aliases and unsized types --- src/doc/trpl/type-aliases.md | 75 ++++++++++++++++++++++++++++++++++- src/doc/trpl/unsized-types.md | 57 +++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 2 deletions(-) diff --git a/src/doc/trpl/type-aliases.md b/src/doc/trpl/type-aliases.md index fffa0ae1383..d175da35f5e 100644 --- a/src/doc/trpl/type-aliases.md +++ b/src/doc/trpl/type-aliases.md @@ -1,3 +1,76 @@ % `type` Aliases -Coming soon +The `type` keyword lets you declare an alias of another type: + +```rust +type Name = String; +``` + +You can then use this type as if it were a real type: + +```rust +type Name = String; + +let x: Name = "Hello".to_string(); +``` + +Note, however, that this is an _alias_, not a new type entirely. In other +words, because Rust is strongly typed, you’d expect a comparison between two +different types to fail: + +```rust,ignore +let x: i32 = 5; +let y: i64 = 5; + +if x == y { + // ... +} +``` + +this gives + +```text +error: mismatched types: + expected `i32`, + found `i64` +(expected i32, + found i64) [E0308] + if x == y { + ^ +``` + +But, if we had an alias: + +```rust +type Num = i32; + +let x: i32 = 5; +let y: Num = 5; + +if x == y { + // ... +} +``` + +This compiles without error. Values of a `Num` type are the same as a value of +type `i32`, in every way. + +You can also use type aliases with generics: + +```rust +use std::result; + +enum ConcreteError { + Foo, + Bar, +} + +type Result = result::Result; +``` + +This creates a specialized version of the `Result` type, which always has a +`ConcreteError` for the `E` part of `Result`. This is commonly used +in the standard library to create custom errors for each subsection. For +example, [io::Result][ioresult]. + +[ioresult]: ../std/io/type.Result.html diff --git a/src/doc/trpl/unsized-types.md b/src/doc/trpl/unsized-types.md index f307f23f011..756abeff06d 100644 --- a/src/doc/trpl/unsized-types.md +++ b/src/doc/trpl/unsized-types.md @@ -1,3 +1,58 @@ % Unsized Types -Coming Soon! +Most types have a particular size, in bytes, that is knowable at compile time. +For example, an `i32` is thirty-two bits big, or four bytes. However, there are +some types which are useful to express, but do not have a defined size. These are +called ‘unsized’ or ‘dynamically sized’ types. One example is `[T]`. This type +represents a certain number of `T` in sequence. But we don’t know how many +there are, so the size is not known. + +Rust understands a few of these types, but they have some restrictions. There +are three: + +1. We can only manipulate an instance of an unsized type via a pointer. An + `&[T]` works just fine, but a `[T]` does not. +2. Variables and arguments cannot have dynamically sized types. +3. Only the last field in a `struct` may have a dynamically sized type; the + other fields must not. Enum variants must not have dynamically sized types as + data. + +So why bother? Well, because `[T]` can only be used behind a pointer, if we +didn’t have language support for unsized types, it would be impossible to write +this: + +```rust,ignore +impl Foo for str { +``` + +or + +```rust,ignore +impl Foo for [T] { +``` + +Instead, you would have to write: + +```rust,ignore +impl Foo for &str { +``` + +Meaning, this implementation would only work for [references][ref], and not +other types of pointers. With this `impl`, all pointers, including (at some +point, there are some bugs to fix first) user-defined custom smart pointers, +can use this `impl`. + +# ?Sized + +If you want to write a function that accepts a dynamically sized type, you +can use the special bound, `?Sized`: + +```rust +struct Foo { + f: T, +} +``` + +This `?`, read as “T may be `Sized`”, means that this bound is special: it +lets us match more kinds, not less. It’s almost like every `T` implicitly has +`T: Sized`, and the `?` undoes this default.