-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Gradually expanding libstd's keyword documentation #53931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
047aac5
1142bbd
c1bd8a9
6cbcfa2
f8d6261
f15a1ec
f91ad44
a5c4a38
f7a6638
5d05ae7
5393b27
738e58d
165690b
76a353b
50f631c
577dbc8
619dfeb
320ec81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,88 @@ | |
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
|
|
||
| #[doc(keyword = "as")] | ||
| // | ||
| /// The type coercion keyword. | ||
| /// | ||
| /// `as` is most commonly used to turn primitive types into other primitive types, but it has other | ||
| /// uses that include turning pointers into addresses, addresses into pointers, and pointers into | ||
| /// other pointers. | ||
| /// | ||
| /// ```rust | ||
| /// let thing1: u8 = 89.0 as u8; | ||
| /// assert_eq!('B' as u32, 66); | ||
| /// assert_eq!(thing1 as char, 'Y'); | ||
| /// let thing2: f32 = thing1 as f32 + 10.5; | ||
| /// assert_eq!(true as u8 + thing2 as u8, 100); | ||
| /// ``` | ||
| /// | ||
| /// In general, any coercion that can be performed via writing out type hints can also be done | ||
|
||
| /// using `as`, so instead of writing `let x: u32 = 123`, you can write `let x = 123 as u32` (Note: | ||
| /// `let x = 123u32` would be best in that situation). The same is not true in the other direction, | ||
|
||
| /// however, explicitly using `as` allows a few more coercions that aren't allowed implicitly, such | ||
| /// as changing the type of a raw pointer or turning closures into raw pointers. | ||
| /// | ||
| /// For more information on what `as` is capable of, see the [Reference] | ||
| /// | ||
| /// [Reference]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions | ||
| mod as_keyword { } | ||
|
|
||
| #[doc(keyword = "const")] | ||
| // | ||
| /// The keyword for defining constants. | ||
| /// | ||
| /// Sometimes a certain value is used many times throughout a program, and it can become | ||
| /// inconvenient to copy it over and over. What's more, it's not always possible or desirable to | ||
| /// make it a variable that gets carried around to each function that needs it. In these cases, the | ||
| /// `const` keyword provides a convenient alternative to code duplication. | ||
| /// | ||
| /// ```rust | ||
| /// const THING: u32 = 0xABAD1DEA; | ||
| /// | ||
| /// let foo = 123 + THING; | ||
| /// ``` | ||
| /// | ||
| /// Constants must be explicitly typed, unlike with `let` you can't ignore its type and let the | ||
| /// compiler figure it out. Any constant value can be defined in a const, which in practice happens | ||
| /// to be most things that would be reasonable to have a constant. For example, you can't have a | ||
|
||
| /// File as a const. | ||
| /// | ||
| /// The only lifetime allowed in a constant is 'static, which is the lifetime that encompasses all | ||
|
||
| /// others in a Rust program. For example, if you wanted to define a constant string, it would look | ||
| /// like this: | ||
| /// | ||
| /// ```rust | ||
| /// const WORDS: &'static str = "hello rust!"; | ||
| /// ``` | ||
| /// | ||
| /// Thanks to static lifetime elision, you usually don't have to explicitly use 'static: | ||
| /// | ||
| /// ```rust | ||
| /// const WORDS: &str = "hello convenience!"; | ||
| /// ``` | ||
| /// | ||
| /// `const` items looks remarkably similar to [`static`] items, which introduces some confusion as | ||
| /// to which one should be used at which times. To put it simply, constants are inlined wherever | ||
| /// they're used, making using them identical to simply replacing the name of the const with its | ||
| /// value. Static variables on the other hand point to a single location in memory, which all | ||
| /// accesses share. This means that, unlike with constants, they can't have destructors, but it | ||
| /// also means that (via unsafe code) they can be mutable, which is useful for the rare situations | ||
|
||
| /// in which you can't avoid using global state. | ||
| /// | ||
| /// Constants, as with statics, should always be in SCREAMING_SNAKE_CASE. | ||
| /// | ||
| /// The `const` keyword is also used in raw pointers in combination with `mut`, as seen in `*const | ||
| /// T` and `*mut T`. More about that can be read at the [pointer] primitive part of the Rust docs. | ||
| /// | ||
| /// For more detail on `const`, see the [Rust Book] or the [Reference] | ||
| /// | ||
| /// [`static`]: keyword.static.html | ||
| /// [pointer]: primitive.pointer.html | ||
| /// [Rust Book]: https://doc.rust-lang.org/stable/book/2018-edition/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants | ||
| /// [Reference]: https://doc.rust-lang.org/reference/items/constant-items.html | ||
| mod const_keyword { } | ||
|
|
||
| #[doc(keyword = "fn")] | ||
| // | ||
| /// The `fn` keyword. | ||
|
|
@@ -59,21 +141,109 @@ mod let_keyword { } | |
|
|
||
| #[doc(keyword = "struct")] | ||
| // | ||
| /// The `struct` keyword. | ||
| /// The keyword used to define structs. | ||
iirelu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /// | ||
| /// The `struct` keyword is used to define a struct type. | ||
| /// Structs in Rust come in three flavours: Regular structs, tuple structs, | ||
|
||
| /// and empty structs. | ||
|
||
| /// | ||
| /// Example: | ||
| /// ```rust | ||
| /// struct Regular { | ||
| /// field1: f32, | ||
| /// field2: String, | ||
| /// pub field3: bool | ||
| /// } | ||
| /// | ||
| /// struct Tuple(u32, String); | ||
| /// | ||
| /// struct Empty; | ||
|
||
| /// ``` | ||
| /// struct Foo { | ||
| /// field1: u32, | ||
| /// field2: String, | ||
| /// | ||
| /// Regular structs are the most commonly used. Each field defined within them has a name and a | ||
| /// type, and once defined can be accessed using `example_struct.field` syntax. The fields of a | ||
| /// struct share its mutability, so `foo.bar = 2;` would only be valid if `foo` was mutable. Adding | ||
| /// `pub` to a field makes it visible to code in other modules, as well as allowing it to be | ||
| /// directly accessed and modified. | ||
| /// | ||
| /// Tuple structs are similar to regular structs, but its fields have no names. They are used like | ||
| /// tuples, with deconstruction possible via `let TupleStruct(x, y) = foo;` syntax. For accessing | ||
| /// individual variables, the same syntax is used as with regular tuples, namely `foo.0`, `foo.1`, | ||
| /// etc, starting at zero. | ||
| /// | ||
| /// Empty structs, or unit-like structs, are most commonly used as markers, for example | ||
| /// [`PhantomData`]. Empty structs have a size of zero bytes, but unlike empty enums they can be | ||
|
||
| /// instantiated, making them similar to the unit type `()`. Unit-like structs are useful when you | ||
|
||
| /// need to implement a trait on something, but don't need to store any data inside it. | ||
| /// | ||
| /// # Instantiation | ||
| /// | ||
| /// Structs can be instantiated in a manner of different ways, each of which can be mixed and | ||
|
||
| /// matched as needed. The most common way to make a new struct is via a constructor method such as | ||
| /// `new()`, but when that isn't available (or you're writing the constructor itself), struct | ||
| /// literal syntax is used: | ||
| /// | ||
| /// ```rust | ||
| /// # struct Foo { field1: f32, field2: String, etc: bool } | ||
| /// let example = Foo { | ||
| /// field1: 42.0, | ||
| /// field2: "blah".to_string(), | ||
| /// etc: true, | ||
| /// }; | ||
| /// ``` | ||
| /// | ||
| /// It's only possible to directly instantiate a struct using struct literal syntax when all of its | ||
| /// fields are visible to you. | ||
| /// | ||
| /// There are a handful of shortcuts provided to make writing constructors more convenient, most | ||
| /// common of which is the Field Init shorthand. When there is a variable and a field of the same | ||
| /// name, the assignment can be simplified from `field: field` into simply `field`. The following | ||
| /// example of a hypothetical constructor demonstrates this: | ||
| /// | ||
| /// ```rust | ||
| /// struct User { | ||
| /// name: String, | ||
| /// admin: bool, | ||
| /// } | ||
| /// | ||
| /// impl User { | ||
| /// pub fn new(name: String) -> Self { | ||
| /// Self { | ||
| /// name, | ||
| /// admin: false, | ||
| /// } | ||
| /// } | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// There are different kinds of structs. For more information, take a look at the | ||
| /// [Rust Book][book]. | ||
| /// Another shortcut for struct instantiation is available when you need to make a new struct that | ||
| /// shares most of a previous struct's values called struct update syntax: | ||
| /// | ||
| /// ```rust | ||
| /// # struct Foo { field1: String, field2: () } | ||
| /// # let thing = Foo { field1: "".to_string(), field2: () }; | ||
| /// let updated_thing = Foo { | ||
| /// field1: "a new value".to_string(), | ||
| /// ..thing | ||
| /// }; | ||
| /// ``` | ||
| /// | ||
| /// Tuple structs are instantiated in the same way as tuples themselves, except with the struct's | ||
| /// name as a prefix: `Foo(123, false, 0.1)`. | ||
| /// | ||
| /// Empty structs are instantiated with just their name and nothing else. `let thing = | ||
|
||
| /// EmptyStruct;` | ||
| /// | ||
| /// | ||
|
||
| /// # Style conventions | ||
| /// | ||
| /// Structs are always written in CamelCase, with few exceptions. While the trailing comma on a | ||
| /// struct's list of fields can be omitted, it's usually kept for convenience in adding and | ||
| /// removing fields down the line. | ||
| /// | ||
| /// For more information on structs, take a look at the [Rust Book][book] or the | ||
| /// [Reference][reference]. | ||
| /// | ||
| /// [`PhantomData`]: marker/struct.PhantomData.html | ||
| /// [book]: https://doc.rust-lang.org/book/second-edition/ch05-01-defining-structs.html | ||
| /// [reference]: https://doc.rust-lang.org/reference/items/structs.html | ||
|
|
||
|
||
| mod struct_keyword { } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we call this "casting" instead of coercion -- see https://doc.rust-lang.org/book/second-edition/appendix-01-keywords.html.