-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Gradually expanding libstd's keyword documentation #53931
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "via type hints" -> "by ascribing the type" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. coercion -> cast |
||
/// 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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That However, explicit casting with |
||
/// 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "which in practice happens to be most things that would be reasonable to have a constant".. this is either not true or too vague to be useful. There are many things which could be |
||
/// File as a const. | ||
/// | ||
/// The only lifetime allowed in a constant is 'static, which is the lifetime that encompasses all | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
/// 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
cc @eddyb |
||
/// 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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "regular structs" -> "structs with named fields" |
||
/// and empty structs. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. empty structs -> unit structs. |
||
/// | ||
/// Example: | ||
/// ```rust | ||
/// struct Regular { | ||
/// field1: f32, | ||
/// field2: String, | ||
/// pub field3: bool | ||
/// } | ||
/// | ||
/// struct Tuple(u32, String); | ||
/// | ||
/// struct Empty; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Empty -> Unit |
||
/// ``` | ||
/// 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
/// instantiated, making them similar to the unit type `()`. Unit-like structs are useful when you | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. similar -> isomorphic |
||
/// 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "in a manner of different ways" -> "in different ways" |
||
/// 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 = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Weird wording and punctuation. |
||
/// EmptyStruct;` | ||
/// | ||
/// | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra empty line. |
||
/// # 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 | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for this line. |
||
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.