From ae361e1a09437dd75a15416a6a369226c5ca5ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Br=C3=A1ulio=20Bezerra?= Date: Mon, 2 Oct 2017 08:56:58 -0300 Subject: [PATCH] Divide items and expressions into sections - Links in other parts of the reference were updated - The following sections were moved inside others: * grouped expressions into operator-expr.md * while let into loop-expr.md * if let into if-expr.md * tuple indexing into tuple-expr.md --- src/SUMMARY.md | 30 + src/attributes.md | 4 +- src/behavior-considered-undefined.md | 2 +- src/crates-and-source-files.md | 2 +- src/dynamically-sized-types.md | 10 +- src/expressions.md | 1381 ++------------------------ src/expressions/array-expr.md | 53 + src/expressions/block-expr.md | 34 + src/expressions/call-expr.md | 89 ++ src/expressions/closure-expr.md | 58 ++ src/expressions/enum-variant-expr.md | 15 + src/expressions/field-expr.md | 43 + src/expressions/if-expr.md | 59 ++ src/expressions/literal-expr.md | 11 + src/expressions/loop-expr.md | 167 ++++ src/expressions/match-expr.md | 128 +++ src/expressions/method-call-expr.md | 51 + src/expressions/operator-expr.md | 359 +++++++ src/expressions/path-expr.md | 21 + src/expressions/range-expr.md | 20 + src/expressions/return-expr.md | 17 + src/expressions/struct-expr.md | 80 ++ src/expressions/tuple-expr.md | 38 + src/interior-mutability.md | 2 +- src/items.md | 1320 +----------------------- src/items/constant-items.md | 42 + src/items/enumerations.md | 69 ++ src/items/extern-crates.md | 37 + src/items/external-blocks.md | 83 ++ src/items/functions.md | 167 ++++ src/items/implementations.md | 76 ++ src/items/modules.md | 63 ++ src/items/static-items.md | 105 ++ src/items/structs.md | 45 + src/items/traits.md | 308 ++++++ src/items/type-aliases.md | 25 + src/items/unions.md | 141 +++ src/items/use-declarations.md | 113 +++ src/macros-by-example.md | 4 +- src/statements.md | 4 +- src/string-table-productions.md | 6 +- src/tokens.md | 6 +- src/types.md | 20 +- src/unsafety.md | 4 +- 44 files changed, 2673 insertions(+), 2639 deletions(-) create mode 100644 src/expressions/array-expr.md create mode 100644 src/expressions/block-expr.md create mode 100644 src/expressions/call-expr.md create mode 100644 src/expressions/closure-expr.md create mode 100644 src/expressions/enum-variant-expr.md create mode 100644 src/expressions/field-expr.md create mode 100644 src/expressions/if-expr.md create mode 100644 src/expressions/literal-expr.md create mode 100644 src/expressions/loop-expr.md create mode 100644 src/expressions/match-expr.md create mode 100644 src/expressions/method-call-expr.md create mode 100644 src/expressions/operator-expr.md create mode 100644 src/expressions/path-expr.md create mode 100644 src/expressions/range-expr.md create mode 100644 src/expressions/return-expr.md create mode 100644 src/expressions/struct-expr.md create mode 100644 src/expressions/tuple-expr.md create mode 100644 src/items/constant-items.md create mode 100644 src/items/enumerations.md create mode 100644 src/items/extern-crates.md create mode 100644 src/items/external-blocks.md create mode 100644 src/items/functions.md create mode 100644 src/items/implementations.md create mode 100644 src/items/modules.md create mode 100644 src/items/static-items.md create mode 100644 src/items/structs.md create mode 100644 src/items/traits.md create mode 100644 src/items/type-aliases.md create mode 100644 src/items/unions.md create mode 100644 src/items/use-declarations.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1d5cd29be52b8..c8dfe8630f1b9 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -23,12 +23,42 @@ - [Items and attributes](items-and-attributes.md) - [Items](items.md) + - [Modules](items/modules.md) + - [Extern crates](items/extern-crates.md) + - [Use declarations](items/use-declarations.md) + - [Functions](items/functions.md) + - [Type aliases](items/type-aliases.md) + - [Structs](items/structs.md) + - [Enumerations](items/enumerations.md) + - [Unions](items/unions.md) + - [Constant items](items/constant-items.md) + - [Static items](items/static-items.md) + - [Traits](items/traits.md) + - [Implementations](items/implementations.md) + - [External blocks](items/external-blocks.md) - [Visibility and Privacy](visibility-and-privacy.md) - [Attributes](attributes.md) - [Statements and expressions](statements-and-expressions.md) - [Statements](statements.md) - [Expressions](expressions.md) + - [Literal expressions](expressions/literal-expr.md) + - [Path expressions](expressions/path-expr.md) + - [Block expressions](expressions/block-expr.md) + - [Operator expressions](expressions/operator-expr.md) + - [Array and index expressions](expressions/array-expr.md) + - [Tuple and index expressions](expressions/tuple-expr.md) + - [Struct expressions](expressions/struct-expr.md) + - [Enum variant expressions](expressions/enum-variant-expr.md) + - [Call expressions](expressions/call-expr.md) + - [Method call expressions](expressions/method-call-expr.md) + - [Field access expressions](expressions/field-expr.md) + - [Closure expressions](expressions/closure-expr.md) + - [Loop expressions](expressions/loop-expr.md) + - [Range expressions](expressions/range-expr.md) + - [If and if let expressions](expressions/if-expr.md) + - [Match expressions](expressions/match-expr.md) + - [Return expressions](expressions/return-expr.md) - [Type system](type-system.md) - [Types](types.md) diff --git a/src/attributes.md b/src/attributes.md index d3ea9494956ab..c921d4739073a 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -137,8 +137,8 @@ On an `extern` block, the following attributes are interpreted: - `link` - indicate that a native library should be linked to for the declarations in this block to be linked correctly. `link` supports an optional `kind` key with three possible values: `dylib`, `static`, and `framework`. See - [external blocks](items.html#external-blocks) for more about external blocks. Two - examples: `#[link(name = "readline")]` and + [external blocks](items/external-blocks.html) for more about external blocks. + Two examples: `#[link(name = "readline")]` and `#[link(name = "CoreFoundation", kind = "framework")]`. - `linked_from` - indicates what native library this block of FFI items is coming from. This attribute is of the form `#[linked_from = "foo"]` where diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index 547c5b060a30c..1a6a8a6591179 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -39,4 +39,4 @@ to let `safe` code exhibit these behaviors. [`std::ptr::copy_nonoverlapping_memory`]: https://doc.rust-lang.org/std/ptr/fn.copy_nonoverlapping.html [`UnsafeCell`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html [`read_unaligned`]: https://doc.rust-lang.org/std/ptr/fn.read_unaligned.html -[`write_unaligned`]: https://doc.rust-lang.org/std/ptr/fn.write_unaligned.html \ No newline at end of file +[`write_unaligned`]: https://doc.rust-lang.org/std/ptr/fn.write_unaligned.html diff --git a/src/crates-and-source-files.md b/src/crates-and-source-files.md index 62f33343bfed8..a1cfd0c1b4756 100644 --- a/src/crates-and-source-files.md +++ b/src/crates-and-source-files.md @@ -96,7 +96,7 @@ fn main() { ECMA-335 CLI model, a *library* in the SML/NJ Compilation Manager, a *unit* in the Owens and Flatt module system, or a *configuration* in Mesa. -[module]: items.html#modules +[module]: items/modules.html [module path]: paths.html [attributes]: items-and-attributes.html [unit]: types.html#tuple-types diff --git a/src/dynamically-sized-types.md b/src/dynamically-sized-types.md index 0933a688afc93..e2fa8bcba1d25 100644 --- a/src/dynamically-sized-types.md +++ b/src/dynamically-sized-types.md @@ -24,9 +24,9 @@ Notably: [variables], function parameters, [const] and [static] items must be `Sized`. [sized]: the-sized-trait.html -[Slices]: #array-and-slice-types -[trait objects]: #trait-objects -[Pointer types]: #pointer-types +[Slices]: types.html#array-and-slice-types +[trait objects]: types.html#trait-objects +[Pointer types]: types.html#pointer-types [variables]: variables.html -[const]: items.html#constant-items -[static]: items.html#static-items +[const]: items/constant-items.html +[static]: items/static-items.html diff --git a/src/expressions.md b/src/expressions.md index 024fc2c3242c6..b2b4e03bd5d93 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -23,20 +23,17 @@ or _rvalue context_. The evaluation of an expression depends both on its own category and the context it occurs within. An lvalue is an expression that represents a memory location. These expressions -are [paths](#path-expressions) which refer to local variables, function and -method arguments, or static variables, -[dereferences](#the-dereference-operator) (`*expr`), [indexing -expressions](#index-expressions) (`expr[expr]`), [field -references](#field-expressions) (`expr.f`) and parenthesized lvalue +are paths which refer to local variables, function and method arguments, or +static variables, [dereferences] (`*expr`), [array indexing] expressions +(`expr[expr]`), [field] references (`expr.f`) and parenthesized lvalue expressions. All other expressions are rvalues. -The left operand of an [assignment](#assignment-expressions) or -[compound-assignment](#compound-assignment-expressions) expression is an lvalue -context, as is the single operand of a unary [borrow](#borrow-operators), and -the operand of any [implicit borrow](#implicit-borrows). The discriminant or -subject of a [match expression](#match-expressions) and right side of a `let` -binding may be an lvalue context, if ref bindings are made, but is otherwise an -rvalue context. All other expression contexts are rvalue contexts. +The left operand of an [assign]ment or [compound assignment] expression is an +lvalue context, as is the single operand of a unary [borrow], and the operand +of any [implicit borrow](#implicit-borrows). The discriminant or subject of a +[match] expression and right side of a `let` binding may be an lvalue context, +if ref bindings are made, but is otherwise an rvalue context. All other +expression contexts are rvalue contexts. ### Moved and copied types @@ -48,10 +45,10 @@ the following lvalues may be moved out of: * [Variables](variables.html) which are not currently borrowed. * [Temporary values](#temporary-lifetimes). -* [Fields](#field-expressions) of an lvalue which can be moved out of and +* [Field]s of an lvalue which can be moved out of and doesn't implement [`Drop`](the-drop-trait.html). -* The result of [dereferencing](#the-dereference-operator) an expression with - type `Box` and that can also be moved out of. +* The result of [dereferencing] an expression with type `Box` and that can + also be moved out of. Moving out of an lvalue deinitializes that location (if it comes from a local variable), so that it can't be read from again. In all other cases, trying to @@ -59,8 +56,8 @@ use an lvalue in an rvalue context is an error. ### Mutability -For an lvalue to be [assigned](#assignment-expressions) to, [mutably -borrowed](#borrow-operators), [implicitly mutably borrowed](#implicit-borrows) +For an lvalue to be [assign]ed to, mutably [borrow]ed, +[implicitly mutably borrowed](#implicit-borrows) or bound to a pattern containing `ref mut` it must be _mutable_, we call these contexts _mutable_ lvalue contexts, other lvalue contexts are called _immutable_. @@ -68,16 +65,15 @@ _immutable_. The following expressions can create mutable lvalues: * Mutable [variables](variables.html), which are not currently borrowed. -* [Mutable `static` items](items.html#mutable-statics). +* [Mutable `static` items](items/static-items.html#mutable-statics). * [Temporary values](#temporary-lifetimes). -* [Fields](#field-expressions), this evaluates the subexpression in a mutable - lvalue context. -* [Dereferences](#the-dereference-operator) of a `*mut T` pointer. +* [Field]s, this evaluates the subexpression in a mutable lvalue context. +* [Dereferences] of a `*mut T` pointer. * Dereference of a variable, or field of a variable, with type `&mut T`. Note: this is an exception to the requirement for the next rule. * Dereferences of a type that implements `DerefMut`, this then requires that the value being dereferenced is evaluated is a mutable lvalue context. -* [Indexing](#index-expressions) of a type that implements `DerefMut`, this +* [Array indexing] of a type that implements `DerefMut`, this then evaluates the value being indexed (but not the index) in mutable lvalue context. @@ -146,9 +142,8 @@ Here are some examples: ### Implicit Borrows Certain expressions will treat an expression as an lvalue by implicitly -borrowing it. For example, it is possible to compare two unsized -[slices](types.html#array-and-slice-types) for equality directly, because the -`==` operator implicitly borrows it's operands: +borrowing it. For example, it is possible to compare two unsized [slices] for +equality directly, because the `==` operator implicitly borrows it's operands: ```rust # let c = [1, 2, 3]; @@ -165,59 +160,51 @@ let b: &[i32]; Implicit borrows may be taken in the following expressions: -* Left operand in [method-call expressions](#method-call-expressions). -* Left operand in [field expressions](#field-expressions). -* Left operand in [call expressions](#call-expressions). -* Left operand in [index expressions](#index-expressions). -* Operand of the [dereference](#the-dereference-operator) (`*`) operator. -* Operands of [comparison operators](#comparison-operators). -* Left operands of the [compound assignment](#compound-assignment-expressions). +* Left operand in [method-call] expressions. +* Left operand in [field] expressions. +* Left operand in [call expressions]. +* Left operand in [array indexing] expressions. +* Operand of the [dereference] operator (`*`). +* Operands of [comparison]. +* Left operands of the [compound assignment]. ## Constant expressions Certain types of expressions can be evaluated at compile time. These are called _constant expressions_. Certain places, such as in -[constants](items.html#constant-items) and [statics](items.html#static-items), +[constants](items/constant-items.html) and [statics](items/static-items.html), require a constant expression, and are always evaluated at compile time. In other places, such as in [`let` statements](statements.html#let-statements), constant expressions may be evaluated at compile time. If errors, such as out -of bounds [array access](#index-expressions) or [overflow](#overflow) occurs, +of bounds [array indexing] or [overflow] occurs, then it is a compiler error if the value must be evaluated at compile time, otherwise it is just a warning, but the code will most likely panic when run. The following expressions are constant expressions, so long as any operands are also constant expressions: -* [Literals](#literal-expressions). -* [Paths](#path-expressions) to [functions](items.html#functions) and constants. +* [Literals]. +* [Paths] to [functions](items/functions.html) and constants. Recursively defining constants is not allowed. * Paths to statics, so long as only their address, not their value, is used. This includes using their value indirectly through a complicated expression. \* -* [Tuple expressions](#tuple-expressions). -* [Array expressions](#array-expressions). -* [Struct expressions](#struct-expressions), where the type does not implement - [`Drop`](the-drop-trait.html). -* [Variant expressions](#enumeration-variant-expressions), where the - enumeration type does not implement `Drop`. -* [Block expressions](#block-expressions) (and `unsafe` blocks) which contain - only items and possibly a (constant) tail expression. -* [Field expressions](#field-expressions). -* [Index expressions](#index-expressions), indexing a [array or - slice](types.html#array-and-slice-types) with a `usize`. -* [Range expressions](#range-expressions). -* [Closure expressions](#closure-expressions) which don't capture variables - from the environment. -* Built in [negation](#negation-operators), [arithmetic, - logical](#arithmetic-and-logical-binary-operators), - [comparison](#comparison-operators) or [lazy - boolean](#lazy-boolean-operators) operators used on integer and floating - point types, `bool` and `char`. -* Shared [borrow expressions](#borrow-operators). -* The [dereference operator](#the-dereference-operator), but not to circumvent the - rule on statics. -* [Grouped expressions](#grouped-expressions). -* [Cast expressions](#type-cast-expressions), except pointer to address and +* [Tuple expressions]. +* [Array expressions]. +* [Struct] expressions, where the type does not implement [`Drop`](the-drop-trait.html). +* [Enum variant] expressions, where the enumeration type does not implement `Drop`. +* [Block expressions] (and `unsafe` blocks) which contain only items and + possibly a (constant) tail expression. +* [Field] expressions. +* Index expressions, [array indexing] or [slice] with a `usize`. +* [Range expressions]. +* [Closure expressions] which don't capture variables from the environment. +* Built in [negation], [arithmetic, logical], [comparison] or [lazy boolean] + operators used on integer and floating point types, `bool` and `char`. +* Shared [borrow]. +* The [dereference operator], but not to circumvent the rule on statics. +* [Grouped] expressions. +* [Cast] expressions, except pointer to address and function pointer to address casts. \* Only in static items. @@ -228,1246 +215,34 @@ Many of the following operators and expressions can also be overloaded for other types using traits in `std::ops` or `std::cmp`, these traits here also exist in `core::ops` and `core::cmp` with the same names. -## Literal expressions - -A _literal expression_ consists of one of the [literal](tokens.html#literals) -forms described earlier. It directly describes a number, character, string, -or boolean value. - -```rust -"hello"; // string type -'5'; // character type -5; // integer type -``` - -## Path expressions - -A [path](paths.html) used as an expression context denotes either a local -variable or an item. Path expressions that resolve to local or static variables -are [lvalues](expressions.html#lvalues-and-rvalues), other paths -are rvalues. Using a `static mut` variable requires an [`unsafe` -block](#unsafe-blocks). - -```rust -# mod globals { -# pub static STATIC_VAR: i32 = 5; -# pub static mut STATIC_MUT_VAR: i32 = 7; -# } -# let local_var = 3; -local_var; -globals::STATIC_VAR; -unsafe { globals::STATIC_MUT_VAR }; -let some_constructor = Some::; -let push_integer = Vec::::push; -let slice_reverse = <[i32]>::reverse; -``` - -## Tuple expressions - -Tuples are written by enclosing zero or more comma-separated expressions in -parentheses. They are used to create [tuple-typed](types.html#tuple-types) -values. - -```rust -(0.0, 4.5); -("a", 4usize, true); -(); -``` - -You can disambiguate a single-element tuple from a value in parentheses with a -comma: - -```rust -(0,); // single-element tuple -(0); // zero in parentheses -``` - -## Struct expressions - -There are several forms of struct expressions. A _struct expression_ consists -of the [path](paths.html) of a [struct item](items.html#structs), followed by a -brace-enclosed list of zero or more comma-separated name-value pairs, providing -the field values of a new instance of the struct. A field name can be any -[identifier](identifiers.html), and is separated from its value expression by a -colon. In the case of a tuple struct the field names are numbers corresponding -to the position of the field. The numbers must be written in decimal, -containing no underscores and with no leading zeros or integer suffix. A value -of a [union](items.html#unions) type can also be created using this syntax, -except that it must specify exactly one field. - -Struct expressions can't be used directly in the head of a [loop](#loops) or an -[`if`](#if-expressions), [`if let`](#if-let-expressions) or -[`match`](#match-expressions) expression. But struct expressions can still be -in used inside parentheses, for example. - -A _tuple struct expression_ consists of the path of a struct item, followed by -a parenthesized list of one or more comma-separated expressions (in other -words, the path of a struct item followed by a tuple expression). The struct -item must be a tuple struct item. - -A _unit-like struct expression_ consists only of the path of a struct item. - -The following are examples of struct expressions: - -```rust -# struct Point { x: f64, y: f64 } -# struct NothingInMe { } -# struct TuplePoint(f64, f64); -# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } } -# struct Cookie; fn some_fn(t: T) {} -Point {x: 10.0, y: 20.0}; -NothingInMe {}; -TuplePoint(10.0, 20.0); -TuplePoint { 0: 10.0, 1: 20.0 }; // Results in the same value as the above line -let u = game::User {name: "Joe", age: 35, score: 100_000}; -some_fn::(Cookie); -``` - -A struct expression forms a new value of the named struct type. Note that for a -given *unit-like* struct type, this will always be the same value. - -A struct expression can terminate with the syntax `..` followed by an -expression to denote a functional update. The expression following `..` (the -base) must have the same struct type as the new struct type being formed. The -entire expression denotes the result of constructing a new struct (with the -same type as the base expression) with the given values for the fields that -were explicitly specified and the values in the base expression for all other -fields. Just as with all struct expressions, all of the fields of the struct -must be [visible](visibility-and-privacy.html), even those not explicitly -named. - -```rust -# struct Point3d { x: i32, y: i32, z: i32 } -let base = Point3d {x: 1, y: 2, z: 3}; -Point3d {y: 0, z: 10, .. base}; -``` - -#### Struct field init shorthand - -When initializing a data structure (struct, enum, union) with named (but not -numbered) fields, it is allowed to write `fieldname` as a shorthand for -`fieldname: fieldname`. This allows a compact syntax with less duplication. - -Example: - -```rust -# struct Point3d { x: i32, y: i32, z: i32 } -# let x = 0; -# let y_value = 0; -# let z = 0; -Point3d { x: x, y: y_value, z: z }; -Point3d { x, y: y_value, z }; -``` - -### Enumeration Variant expressions - -Enumeration variants can be constructed similarly to structs, using a path to -an enum variant instead of to a struct: - -```rust -# enum Message { -# Quit, -# WriteString(String), -# Move { x: i32, y: i32 }, -# } -let q = Message::Quit; -let w = Message::WriteString("Some string".to_string()); -let m = Message::Move { x: 50, y: 200 }; -``` - -## Block expressions - -A _block expression_ is similar to a module in terms of the declarations that -are possible, but can also contain [statements](statements.html) and end with -an expression. Each block conceptually introduces a new namespace scope. Use -items can bring new names into scopes and declared items are in scope for only -the block itself. - -A block will execute each statement sequentially, and then execute the -expression (if given). If the block doesn't end in an expression, its value is -`()`: - -```rust -let x: () = { println!("Hello."); }; -``` - -If it ends in an expression, its value and type are that of the expression: - -```rust -let x: i32 = { println!("Hello."); 5 }; - -assert_eq!(5, x); -``` - -Blocks are always [rvalues](expressions.html#lvalues-and-rvalues) and evaluate the last -expression in rvalue context. This can be used to force moving a value -if really needed. - -### `unsafe` blocks - -_See [`unsafe` block](unsafe-blocks.html) for more information on when to use `unsafe`_ - -A block of code can be prefixed with the `unsafe` keyword, to permit calling -`unsafe` functions or dereferencing raw pointers within a safe function. - -## Method-call expressions - -A _method call_ consists of an expression followed by a single dot, an -[identifier](identifiers.html), and a parenthesized expression-list. Method -calls are resolved to methods on specific traits, either statically dispatching -to a method if the exact `self`-type of the left-hand-side is known, or -dynamically dispatching if the left-hand-side expression is an indirect [trait -object](types.html#trait-objects). Method call expressions will automatically -take a shared or mutable borrow of the receiver if needed. - -```rust -let pi: Result = "3.14".parse(); -let log_pi = pi.unwrap_or(1.0).log(2.72); -# assert!(1.14 < log_pi && log_pi < 1.15) -``` - -When resolving method calls on an expression of type `A`, Rust will use the -following order: - -1. Inherent methods, with receiver of type `A`, `&A`, `&mut A`. -1. Trait methods with receiver of type `A`. -1. Trait methods with receiver of type `&A`. -1. Trait methods with receiver of type `&mut A`. -1. If it's possible, Rust will then repeat steps 1-5 with - `::Target`, and insert a dereference operator. -1. If `A` is now an [array](types.html#array-and-slice-types) type, then - repeat steps 1-4 with the corresponding slice type. - -Note: that in steps 1-4 the receiver is used, not the type of `Self` nor the -type of `A`. For example - -```rust,ignore -// `Self` is `&A`, receiver is `&A`. -impl<'a> Trait for &'a A { - fn method(self) {} -} -// If `A` is `&B`, then `Self` is `B` and the receiver is `A`. -impl B { - fn method(&self) {} -} -``` - -Another note: this process does not use the mutability or lifetime of the -receiver, or whether `unsafe` methods can currently be called to resolve -methods. These constraints instead lead to compiler errors. - -If a step is reached where there is more than one possible method (where -generic methods or traits are considered the same), then it is a compiler -error. These cases require a [more specific -syntax.](#disambiguating-function-calls) for method and function invocation. - -## Field expressions - -A _field expression_ consists of an expression followed by a single dot and an -[identifier](identifiers.html), when not immediately followed by a -parenthesized expression-list (the latter is always a [method call -expression](#method-call-expressions)). A field expression denotes a field of a -[struct](types.html#struct-types) or [union](items.html#unions). To call a -function stored in a struct parentheses are needed around the field expression - -```rust,ignore -mystruct.myfield; -foo().x; -(Struct {a: 10, b: 20}).a; -mystruct.method(); // Method expression -(mystruct.function_field)() // Call expression containing a field expression -``` - -A field access is an [lvalue](expressions.html#lvalues-and-rvalues) referring -to the location of that field. When the subexpression is -[mutable](#mutability), the field expression is also mutable. - -Also, if the type of the expression to the left of the dot is a pointer, it is -automatically dereferenced as many times as necessary to make the field access -possible. In cases of ambiguity, we prefer fewer autoderefs to more. - -Finally the fields of a struct, a reference to a struct are treated as separate -entities when borrowing. If the struct does not implement -[`Drop`](the-drop-trait.html) this also applies to moving out of each of its fields -where possible. This also does not apply if automatic dereferencing is done -though user defined types. - -```rust -# struct A { f1: String, f2: String, f3: String } -# let mut x = A { -# f1: "f1".to_string(), -# f2: "f2".to_string(), -# f3: "f3".to_string() -# }; -let a: &mut String = &mut x.f1; // x.f1 borrowed mutably -let b: &String = &x.f2; // x.f2 borrowed immutably -let c: &String = &x.f2; // Can borrow again -let d: String = x.f3; // Move out of x.f3 -``` - -### Tuple indexing expressions - -[Tuples](types.html#tuple-types) and [struct tuples](items.html#structs) can be -indexed using the number corresponding to the position of the field. The index -must be written as a [decimal literal](tokens.html#integer-literals) with no -underscores or suffix. Tuple indexing expressions also differ from field -expressions in that they can unambiguously be called as a function. In all -other aspects they have the same behavior. - -```rust -# struct Point(f32, f32); -let pair = (1, 2); -assert_eq!(pair.1, 2); -let unit_x = Point(1.0, 0.0); -assert_eq!(unit_x.0, 1.0); -``` - -## Call expressions - -A _call expression_ consists of an expression followed by a parenthesized -expression-list. It invokes a function, providing zero or more input variables. -If the function eventually returns, then the expression completes. For -[non-function types](types.html#function-item-types), the expression f(...) uses the -method on one of the `std::ops::Fn`, `std::ops::FnMut` or `std::ops::FnOnce` -traits, which differ in whether they take the type by reference, mutable -reference, or take ownership respectively. An automatic borrow will be taken if -needed. Rust will also automatically dereference `f` as required. Some examples -of call expressions: - -```rust -# fn add(x: i32, y: i32) -> i32 { 0 } -let three: i32 = add(1i32, 2i32); -let name: &'static str = (|| "Rust")(); -``` - -### Disambiguating Function Calls - -Rust treats all function calls as sugar for a more explicit, fully-qualified -syntax. Upon compilation, Rust will desugar all function calls into the explicit -form. Rust may sometimes require you to qualify function calls with trait, -depending on the ambiguity of a call in light of in-scope items. - -> **Note**: In the past, the Rust community used the terms "Unambiguous -> Function Call Syntax", "Universal Function Call Syntax", or "UFCS", in -> documentation, issues, RFCs, and other community writings. However, the term -> lacks descriptive power and potentially confuses the issue at hand. We mention -> it here for searchability's sake. - -Several situations often occur which result in ambiguities about the receiver or -referent of method or associated function calls. These situations may include: - -* Multiple in-scope traits define methods with the same name for the same types -* Auto-`deref` is undesirable; for example, distinguishing between methods on a - smart pointer itself and the pointer's referent -* Methods which take no arguments, like `default()`, and return properties of a - type, like `size_of()` - -To resolve the ambiguity, the programmer may refer to their desired method or -function using more specific paths, types, or traits. - -For example, - -```rust -trait Pretty { - fn print(&self); -} - -trait Ugly { - fn print(&self); -} - -struct Foo; -impl Pretty for Foo { - fn print(&self) {} -} - -struct Bar; -impl Pretty for Bar { - fn print(&self) {} -} -impl Ugly for Bar{ - fn print(&self) {} -} - -fn main() { - let f = Foo; - let b = Bar; - - // we can do this because we only have one item called `print` for `Foo`s - f.print(); - // more explicit, and, in the case of `Foo`, not necessary - Foo::print(&f); - // if you're not into the whole brevity thing - ::print(&f); - - // b.print(); // Error: multiple 'print' found - // Bar::print(&b); // Still an error: multiple `print` found - - // necessary because of in-scope items defining `print` - ::print(&b); -} -``` - -Refer to [RFC 132] for further details and motivations. - -[RFC 132]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md - -## Closure expressions - -A _closure expression_ defines a closure and denotes it as a value, in a single -expression. A closure expression is a pipe-symbol-delimited (`|`) list of -patterns followed by an expression. Type annotations may optionally be added -for the type of the parameters or for the return type. If there is a return -type, the expression used for the body of the closure must be a normal -[block](#block-expressions). A closure expression also may begin with the -`move` keyword before the initial `|`. - -A closure expression denotes a function that maps a list of parameters -(`ident_list`) onto the expression that follows the `ident_list`. The patterns -in the `ident_list` are the parameters to the closure. If a parameter's types -is not specified, then the compiler infers it from context. Each closure -expression has a unique anonymous type. - -Closure expressions are most useful when passing functions as arguments to other -functions, as an abbreviation for defining and capturing a separate function. - -Significantly, closure expressions _capture their environment_, which regular -[function definitions](items.html#functions) do not. Without the `move` -keyword, the closure expression infers how it captures each variable from its -environment, preferring to capture by shared reference, effectively borrowing -all outer variables mentioned inside the closure's body. If needed the compiler -will infer that instead mutable references should be taken, or that the values -should be moved or copied (depending on their type) from the environment. A -closure can be forced to capture its environment by copying or moving values by -prefixing it with the `move` keyword. This is often used to ensure that the -closure's type is `'static`. - -The compiler will determine which of the [closure -traits](types.html#closure-types) the closure's type will implement by how it -acts on its captured variables. The closure will also implement -[`Send`](the-send-trait.html) and/or [`Sync`](the-sync-trait.html) if all of -its captured types do. These traits allow functions to accept closures using -generics, even though the exact types can't be named. - -In this example, we define a function `ten_times` that takes a higher-order -function argument, and we then call it with a closure expression as an argument, -followed by a closure expression that moves values from its environment. - -```rust -fn ten_times(f: F) where F: Fn(i32) { - for index in 0..10 { - f(index); - } -} - -ten_times(|j| println!("hello, {}", j)); -// With type annotations -ten_times(|j: i32| -> () { println!("hello, {}", j) }); - -let word = "konnichiwa".to_owned(); -ten_times(move |j| println!("{}, {}", word, j)); -``` - -## Array expressions - -An _[array](types.html#array-and-slice-types) expression_ can be written by -enclosing zero or more comma-separated expressions of uniform type in square -brackets. This produces and array containing each of these values in the -order they are written. - -Alternatively there can be exactly two expressions inside the brackets, -separated by a semi-colon. The expression after the `;` must be a have type -`usize` and be a [constant expression](#constant-expressions), such as a -[literal](tokens.html#literals) or a [constant -item](items.html#constant-items). `[a; b]` creates an array containing `b` -copies of the value of `a`. If the expression after the semi-colon has a value -greater than 1 then this requires that the type of `a` is -[`Copy`](the-copy-trait.html). - -```rust -[1, 2, 3, 4]; -["a", "b", "c", "d"]; -[0; 128]; // array with 128 zeros -[0u8, 0u8, 0u8, 0u8]; -``` - -## Index expressions - -[Array and slice](types.html#array-and-slice-types)-typed expressions can be -indexed by writing a square-bracket-enclosed expression (the index) after them. -When the array is mutable, the resulting -[lvalue](expressions.html#lvalues-and-rvalues) can be assigned to. -For other types an index expression `a[b]` is equivalent to -`*std::ops::Index::index(&a, b)`, or `*std::opsIndexMut::index_mut(&mut a, b)` -in a mutable lvalue context. Just as with methods, Rust will also insert -dereference operations on `a` repeatedly to find an implementation. - -Indices are zero-based, and are of type `usize` for arrays and slices. Array -access is a [constant expression](#constant-expressions), so bounds can be -checked at compile-time for constant arrays with a constant index value. -Otherwise a check will be performed at run-time that will put the thread in a -_panicked state_ if it fails. - -```rust,should_panic -([1, 2, 3, 4])[2]; // Evaluates to 3 - -let x = (["a", "b"])[10]; // warning: const index-expr is out of bounds - -let n = 10; -let y = (["a", "b"])[n]; // panics - -let arr = ["a", "b"]; -arr[10]; // panics -``` - -## Range expressions - -The `..` operator will construct an object of one of the `std::ops::Range` (or -`core::ops::Range`) variants. - -```rust -1..2; // std::ops::Range -3..; // std::ops::RangeFrom -..4; // std::ops::RangeTo -..; // std::ops::RangeFull -``` - -The following expressions are equivalent. - -```rust -let x = std::ops::Range {start: 0, end: 10}; -let y = 0..10; - -assert_eq!(x, y); -``` - -## Operator expressions - -Operators are defined for built in types by the Rust language. Many of the -following operators can also be overloaded using traits in `std::ops` or -`std::cmp`. - -### Overflow - -Integer operators will panic when they overflow when compiled in debug mode. -The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used -to control this more directly. The following things are considered to be -overflow: - -* When `+`, `*` or `-` create a value greater than the maximum value, or less - than the minimum value that can be stored. This includes unary `-` on the - smallest value of any signed integer type. -* Using `/` or `%`, where the left-hand argument is the smallest integer of a - signed integer type and the right-hand argument is `-1`. -* Using `<<` or `>>` where the right-hand argument is greater than or equal to - the number of bits in the type of the left-hand argument, or is negative. - -### Borrow operators - -The `&` (shared borrow) and `&mut` (mutable borrow) operators are unary prefix -operators. When applied to an lvalue produce a reference (pointer) to the -location that the value refers to. The lvalue is also placed into a borrowed -state for the duration of the reference. For a shared borrow (`&`), this -implies that the lvalue may not be mutated, but it may be read or shared again. -For a mutable borrow (`&mut`), the lvalue may not be accessed in any way until -the borrow expires. `&mut` evaluates its operand in a mutable lvalue context. -If the `&` or `&mut` operators are applied to an rvalue, a temporary value is -created; the lifetime of this temporary value is defined by [syntactic -rules](#temporary-lifetimes). These operators cannot be overloaded. - -```rust -{ - // a temporary with value 7 is created that lasts for this scope. - let shared_reference = &7; -} -let mut array = [-2, 3, 9]; -{ - // Mutably borrows `array` for this scope. - // `array` may only be used through `mutable_reference`. - let mutable_reference = &mut array; -} -``` - -### The dereference operator - -The `*` (dereference) operator is also a unary prefix operator. When applied to -a [pointer](types.html#pointer-types) it denotes the pointed-to location. If -the expression is of type `&mut T` and `*mut T`, and is either a local -variable, a (nested) field of a local variance or is a mutable lvalue, then the -resulting [lvalue](expressions.html#lvalues-and-rvalues) can be -assigned to. Dereferencing a raw pointer requires `unsafe`. - -On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an -[immutable lvalue context](#mutability) and `*std::ops::Deref::deref_mut(&mut -x)` in a mutable lvalue context. - -```rust -let x = &7; -assert_eq!(*x, 7); -let y = &mut 9; -*y = 11; -assert_eq!(*y, 11); -``` - -### The `?` operator. - -The `?` ("question mark") operator can be applied to values of the `Result` type to propagate errors. If applied to `Err(e)` it will return -`Err(From::from(e))` from the enclosing function or closure. If applied to -`Ok(x)` it will unwrap the value to return `x`. Unlike other unary operators -`?` is written in postfix notation. `?` cannot be overloaded. - -```rust -# use std::num::ParseIntError; -fn try_to_parse() -> Result { - let x: i32 = "123".parse()?; // x = 123 - let y: i32 = "24a".parse()?; // returns an Err() immediately - Ok(x + y) // Doesn't run. -} - -let res = try_to_parse(); -println!("{:?}", res); -# assert!(res.is_err()) -``` - -### Negation operators - -These are the last two unary operators. This table summarizes the behavior of -them on primitive types and which traits are used to overload these operators -for other types. Remember that signed integers are always represented using -two's complement. The operands of all of these operators are evaluated in -rvalue context so are moved or copied. - -| Symbol | Integer | `bool` | Floating Point | Overloading Trait | -|--------|-------------|-------------|----------------|--------------------| -| `-` | Negation* | | Negation | `std::ops::Neg` | -| `!` | Bitwise NOT | Logical NOT | | `std::ops::Not` | - -\* Only for signed integer types. - -Here are some example of these operators - -```rust -let x = 6; -assert_eq!(-x, -6); -assert_eq!(!x, -7); -assert_eq!(true, !false); -``` - -### Arithmetic and Logical Binary Operators - -Binary operators expressions are all written with infix notation. This table -summarizes the behavior of arithmetic and logical binary operators on -primitive types and which traits are used to overload these operators for other -types. Remember that signed integers are always represented using two's -complement. The operands of all of these operators are evaluated in rvalue -context so are moved or copied. - -| Symbol | Integer | `bool` | Floating Point | Overloading Trait | -|--------|-------------------------|-------------|----------------|--------------------| -| `+` | Addition | | Addition | `std::ops::Add` | -| `-` | Subtraction | | Subtraction | `std::ops::Sub` | -| `*` | Multiplication | | Multiplication | `std::ops::Mul` | -| `/` | Division | | Division | `std::ops::Div` | -| `%` | Remainder | | Remainder | `std::ops::Rem` | -| `&` | Bitwise AND | Logical AND | | `std::ops::BitAnd` | -| | | Bitwise OR | Logical OR | | `std::ops::BitOr` | -| `^` | Bitwise XOR | Logical XOR | | `std::ops::BitXor` | -| `<<` | Left Shift | | | `std::ops::Shl` | -| `>>` | Right Shift* | | | `std::ops::Shr` | - -\* Arithmetic right shift on signed integer types, logical right shift on -unsigned integer types. - -Here are examples of these operators being used. - -```rust -assert_eq!(3 + 6, 9); -assert_eq!(5.5 - 1.25, 4.25); -assert_eq!(-5 * 14, -70); -assert_eq!(14 / 3, 4); -assert_eq!(100 % 7, 2); -assert_eq!(0b1010 & 0b1100, 0b1000); -assert_eq!(0b1010 | 0b1100, 0b1110); -assert_eq!(0b1010 ^ 0b1100, 0b110); -assert_eq!(13 << 3, 104); -assert_eq!(-10 >> 2, -3); -``` - -### Comparison Operators - -Comparison operators are also defined both for primitive types and many type in -the standard library. Parentheses are required when chaining comparison -operators. For example, the expression `a == b == c` is invalid and may be -written as `(a == b) == c`. - -Unlike arithmetic and logical operators, the traits for -overloading the operators the traits for these operators are used more -generally to show how a type may be compared and will likely be assumed to -define actual comparisons by functions that use these traits as bounds. Many -functions and macros in the standard library can then use that assumption -(although not to ensure safety). Unlike the arithmetic and logical operators -above, these operators implicitly take shared borrows of their operands, -evaluating them in lvalue context: - -```rust,ignore -a == b; -// is equivalent to -::std::cmp::PartialEq::eq(&a, &b); -``` - -This means that the operands don't have to be moved out of. - -| Symbol | Meaning | Overloading method | -|--------|--------------------------|----------------------------| -| `==` | Equal | `std::cmp::PartialEq::eq` | -| `!=` | Not equal | `std::cmp::PartialEq::ne` | -| `>` | Greater than | `std::cmp::PartialOrd::gt` | -| `<` | Less than | `std::cmp::PartialOrd::lt` | -| `>=` | Greater than or equal to | `std::cmp::PartialOrd::ge` | -| `<=` | Less than or equal to | `std::cmp::PartialOrd::le` | - -Here are examples of the comparison operators being used. - -```rust -assert!(123 == 123); -assert!(23 != -12); -assert!(12.5 > 12.2); -assert!([1, 2, 3] < [1, 3, 4]); -assert!('A' <= 'B'); -assert!("World" >= "Hello"); -``` - -### Lazy boolean operators - -The operators `||` and `&&` may be applied to operands of boolean type. The -`||` operator denotes logical 'or', and the `&&` operator denotes logical -'and'. They differ from `|` and `&` in that the right-hand operand is only -evaluated when the left-hand operand does not already determine the result of -the expression. That is, `||` only evaluates its right-hand operand when the -left-hand operand evaluates to `false`, and `&&` only when it evaluates to -`true`. - -```rust -let x = false || true; // true -let y = false && panic!(); // false, doesn't evaluate `panic!()` -``` - -### Type cast expressions - -A type cast expression is denoted with the binary operator `as`. - -Executing an `as` expression casts the value on the left-hand side to the type -on the right-hand side. - -An example of an `as` expression: - -```rust -# fn sum(values: &[f64]) -> f64 { 0.0 } -# fn len(values: &[f64]) -> i32 { 0 } -fn average(values: &[f64]) -> f64 { - let sum: f64 = sum(values); - let size: f64 = len(values) as f64; - sum / size -} -``` - -`as` can be used to explicitly perform [coercions](type-coercions.html), as -well as the following additional casts. Here `*T` means either `*const T` or -`*mut T`. - -| Type of `e` | `U` | Cast performed by `e as U` | -|-----------------------|-----------------------|----------------------------------| -| Integer or Float type | Integer or Float type | Numeric cast | -| C-like enum | Integer type | Enum cast | -| `bool` or `char` | Integer type | Primitive to integer cast | -| `u8` | `char` | `u8` to `char` cast | -| `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast | -| `*T` where `T: Sized` | Numeric type | Pointer to address cast | -| Integer type | `*V` where `V: Sized` | Address to pointer cast | -| `&[T; n]` | `*const T` | Array to pointer cast | -| [Function pointer](types.html#function-pointer-types) | `*V` where `V: Sized` | Function pointer to pointer cast | -| Function pointer | Integer | Function pointer to address cast | - -\* or `T` and `V` are compatible unsized types, e.g., both slices, both the -same trait object. - -#### Semantics - -* Numeric cast - * Casting between two integers of the same size (e.g. i32 -> u32) is a no-op - * Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will - truncate - * Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will - * zero-extend if the source is unsigned - * sign-extend if the source is signed - * Casting from a float to an integer will round the float towards zero - * **[NOTE: currently this will cause Undefined Behavior if the rounded - value cannot be represented by the target integer type][float-int]**. - This includes Inf and NaN. This is a bug and will be fixed. - * Casting from an integer to float will produce the floating point - representation of the integer, rounded if necessary (rounding strategy - unspecified) - * Casting from an f32 to an f64 is perfect and lossless - * Casting from an f64 to an f32 will produce the closest possible value - (rounding strategy unspecified) - * **[NOTE: currently this will cause Undefined Behavior if the value - is finite but larger or smaller than the largest or smallest finite - value representable by f32][float-float]**. This is a bug and will - be fixed. -* Enum cast - * Casts an enum to its discriminant, then uses a numeric cast if needed. -* Primitive to integer cast - * `false` casts to `0`, `true` casts to `1` - * `char` casts to the value of the code point, then uses a numeric cast if needed. -* `u8` to `char` cast - * Casts to the `char` with the corresponding code point. - -[float-int]: https://github.com/rust-lang/rust/issues/10184 -[float-float]: https://github.com/rust-lang/rust/issues/15536 - -### Assignment expressions - -An _assignment expression_ consists of an -[lvalue](expressions.html#lvalues-and-rvalues) expression followed -by an equals sign (`=`) and an -[rvalue](expressions.html#lvalues-and-rvalues) expression. - -Evaluating an assignment expression [either copies or -moves](#moved-and-copied-types) its right-hand operand to its left-hand -operand. The left-hand operand must be an lvalue: using an rvalue results in a -compiler error, rather than promoting it to a temporary. - -```rust -# let mut x = 0; -# let y = 0; -x = y; -``` - -### Compound assignment expressions - -The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be -composed with the `=` operator. The expression `lval OP= val` is equivalent to -`lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`. -Any such expression always has the [`unit`](types.html#tuple-types) type. -These operators can all be overloaded using the trait with the same name as for -the normal operation followed by 'Assign', for example, `std::ops::AddAssign` -is used to overload `+=`. As with `=`, `lval` must be an lvalue. - -```rust -let mut x = 10; -x += 4; -assert_eq!(x, 14); -``` - -### Operator precedence - -The precedence of Rust operators is ordered as follows, going from strong to -weak. Binary Operators at the same precedence level are evaluated in the order -given by their associativity. - - -| Operator | Associativity | -|-----------------------------|---------------------| -| `?` | | -| Unary `-` `*` `!` `&` `&mut` | | -| `as` `:` | left to right | -| `*` `/` `%` | left to right | -| `+` `-` | left to right | -| `<<` `>>` | left to right | -| `&` | left to right | -| `^` | left to right | -| | | left to right | -| `==` `!=` `<` `>` `<=` `>=` | Require parentheses | -| `&&` | left to right | -| || | left to right | -| `..` `...` | Require parentheses | -| `<-` | right to left | -| `=` `+=` `-=` `*=` `/=` `%=`
`&=` |= `^=` `<<=` `>>=` | right to left | - -## Grouped expressions - -An expression enclosed in parentheses evaluates to the result of the enclosed -expression. Parentheses can be used to explicitly specify evaluation order -within an expression. - -An example of a parenthesized expression: - -```rust -let x: i32 = 2 + 3 * 4; -let y: i32 = (2 + 3) * 4; -assert_eq!(x, 14); -assert_eq!(y, 20); -``` - -## Loops - -Rust supports three loop expressions: - -* A [`loop` expression](#infinite-loops) denotes an infinite loop. -* A [`while` expression](#predicate-loops) loops until a predicate is false. -* A [`for` expression](#iterator-loops) extracts values from an iterator, - looping until the iterator is empty. - -All three types of loop support [`break` expressions](#break-expressions), -[`continue` expressions](#continue-expressions), and [labels](#loop-labels). -Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values). - -### Infinite loops - -A `loop` expression repeats execution of its body continuously: -`loop { println!("I live."); }`. - -A `loop` expression without an associated `break` expression is -[diverging](items.html#diverging-functions), and doesn't -return anything. A `loop` expression containing associated -[`break` expression(s)](#break-expressions) -may terminate, and must have type compatible with the value of the `break` -expression(s). - -### Predicate loops - -A `while` loop begins by evaluating the boolean loop conditional expression. If -the loop conditional expression evaluates to `true`, the loop body block -executes, then control returns to the loop conditional expression. If the loop -conditional expression evaluates to `false`, the `while` expression completes. - -An example: - -```rust -let mut i = 0; - -while i < 10 { - println!("hello"); - i = i + 1; -} -``` - -### Iterator loops - -A `for` expression is a syntactic construct for looping over elements provided -by an implementation of `std::iter::IntoIterator`. If the iterator yields a -value, that value is given the specified name and the body of the loop is -executed, then control returns to the head of the `for` loop. If the iterator -is empty, the `for` expression completes. - -An example of a `for` loop over the contents of an array: - -```rust -let v = &["apples", "cake", "coffee"]; - -for text in v { - println!("I like {}.", text); -} -``` - -An example of a for loop over a series of integers: - -```rust -let mut sum = 0; -for n in 1..11 { - sum += n; -} -assert_eq!(sum, 55); -``` - -### Loop labels - -A loop expression may optionally have a _label_. The label is written as -a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`, -`'bar: while false {}`, `'humbug: for _ in 0..0 {}`. -If a label is present, then labeled `break` and `continue` expressions nested -within this loop may exit out of this loop or return control to its head. -See [break expressions](#break-expressions) and [continue -expressions](#continue-expressions). - -### `break` expressions - -When `break` is encountered, execution of the associated loop body is -immediately terminated, for example: - -```rust -let mut last = 0; -for x in 1..100 { - if x > 12 { - break; - } - last = x; -} -assert_eq!(last, 12); -``` - -A `break` expression is normally associated with the innermost `loop`, `for` or -`while` loop enclosing the `break` expression, but a [label](#loop-labels) can -be used to specify which enclosing loop is affected. Example: - -```rust -'outer: loop { - while true { - break 'outer; - } -} -``` - -A `break` expression is only permitted in the body of a loop, and has one of -the forms `break`, `break 'label` or ([see below](#break-and-loop-values)) -`break EXPR` or `break 'label EXPR`. - -### `continue` expressions - -When `continue` is encountered, the current iteration of the associated loop -body is immediately terminated, returning control to the loop *head*. In -the case of a `while` loop, the head is the conditional expression controlling -the loop. In the case of a `for` loop, the head is the call-expression -controlling the loop. - -Like `break`, `continue` is normally associated with the innermost enclosing -loop, but `continue 'label` may be used to specify the loop affected. -A `continue` expression is only permitted in the body of a loop. - -### `break` and loop values - -When associated with a `loop`, a break expression may be used to return a value -from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where -`EXPR` is an expression whose result is returned from the `loop`. For example: - -```rust -let (mut a, mut b) = (1, 1); -let result = loop { - if b > 10 { - break b; - } - let c = a + b; - a = b; - b = c; -}; -// first number in Fibonacci sequence over 10: -assert_eq!(result, 13); -``` - -In the case a `loop` has an associated `break`, it is not considered diverging, -and the `loop` must have a type compatible with each `break` expression. -`break` without an expression is considered identical to `break` with -expression `()`. - -## `if` expressions - -An `if` expression is a conditional branch in program control. The form of an -`if` expression is a condition expression, followed by a consequent block, any -number of `else if` conditions and blocks, and an optional trailing `else` -block. The condition expressions must have type `bool`. If a condition -expression evaluates to `true`, the consequent block is executed and any -subsequent `else if` or `else` block is skipped. If a condition expression -evaluates to `false`, the consequent block is skipped and any subsequent `else -if` condition is evaluated. If all `if` and `else if` conditions evaluate to -`false` then any `else` block is executed. An if expression evaluates to the -same value as the executed block, or `()` if no block is evaluated. An `if` -expression must have the same type in all situations. - -```rust -# let x = 3; -if x == 4 { - println!("x is four"); -} else if x == 3 { - println!("x is three"); -} else { - println!("x is something else"); -} - -let y = if 12 * 15 > 150 { - "Bigger" -} else { - "Smaller" -}; -assert_eq!(y, "Bigger"); -``` - -## `match` expressions - -A `match` expression branches on a *pattern*. The exact form of matching that -occurs depends on the pattern. Patterns consist of some combination of -literals, destructured arrays or enum constructors, structs and tuples, -variable binding specifications, wildcards (`..`), and placeholders (`_`). A -`match` expression has a *head expression*, which is the value to compare to -the patterns. The type of the patterns must equal the type of the head -expression. - -A `match` behaves differently depending on whether or not the head expression -is an [lvalue or an rvalue](expressions.html#lvalues-and-rvalues). -If the head expression is an rvalue, it is first evaluated into a temporary -location, and the resulting value is sequentially compared to the patterns in -the arms until a match is found. The first arm with a matching pattern is -chosen as the branch target of the `match`, any variables bound by the pattern -are assigned to local variables in the arm's block, and control enters the -block. - -When the head expression is an lvalue, the match does not allocate a temporary -location (however, a by-value binding may copy or move from the lvalue). When -possible, it is preferable to match on lvalues, as the lifetime of these -matches inherits the lifetime of the lvalue, rather than being restricted to -the inside of the match. - -An example of a `match` expression: - -```rust -let x = 1; - -match x { - 1 => println!("one"), - 2 => println!("two"), - 3 => println!("three"), - 4 => println!("four"), - 5 => println!("five"), - _ => println!("something else"), -} -``` - -Patterns that bind variables default to binding to a copy or move of the -matched value (depending on the matched value's type). This can be changed to -bind to a reference by using the `ref` keyword, or to a mutable reference using -`ref mut`. - -Patterns can be used to *destructure* structs, enums, and tuples. Destructuring -breaks a value up into its component pieces. The syntax used is the same as -when creating such values. When destructing a data structure with named (but -not numbered) fields, it is allowed to write `fieldname` as a shorthand for -`fieldname: fieldname`. In a pattern whose head expression has a `struct`, -`enum` or `tupl` type, a placeholder (`_`) stands for a *single* data field, -whereas a wildcard `..` stands for *all* the fields of a particular variant. - -```rust -# enum Message { -# Quit, -# WriteString(String), -# Move { x: i32, y: i32 }, -# ChangeColor(u8, u8, u8), -# } -# let message = Message::Quit; -match message { - Message::Quit => println!("Quit"), - Message::WriteString(write) => println!("{}", &write), - Message::Move{ x, y: 0 } => println!("move {} horizontally", x), - Message::Move{ .. } => println!("other move"), - Message::ChangeColor { 0: red, 1: green, 2: _ } => { - println!("color change, red: {}, green: {}", red, green); - } -}; -``` - -Patterns can also dereference pointers by using the `&`, `&mut` and `box` -symbols, as appropriate. For example, these two matches on `x: &i32` are -equivalent: - -```rust -# let x = &3; -let y = match *x { 0 => "zero", _ => "some" }; -let z = match x { &0 => "zero", _ => "some" }; - -assert_eq!(y, z); -``` - -Subpatterns can also be bound to variables by the use of the syntax `variable @ -subpattern`. For example: - -```rust -let x = 1; - -match x { - e @ 1 ... 5 => println!("got a range element {}", e), - _ => println!("anything"), -} -``` - -Multiple match patterns may be joined with the `|` operator. A range of values -may be specified with `...`. For example: - -```rust -# let x = 2; -let message = match x { - 0 | 1 => "not many", - 2 ... 9 => "a few", - _ => "lots" -}; -``` - -Range patterns only work on scalar types (like integers and characters; not -like arrays and structs, which have sub-components). A range pattern may not be -a sub-range of another range pattern inside the same `match`. - -Finally, match patterns can accept *pattern guards* to further refine the -criteria for matching a case. Pattern guards appear after the pattern and -consist of a bool-typed expression following the `if` keyword. A pattern guard -may refer to the variables bound within the pattern they follow. - -```rust -# let maybe_digit = Some(0); -# fn process_digit(i: i32) { } -# fn process_other(i: i32) { } -let message = match maybe_digit { - Some(x) if x < 10 => process_digit(x), - Some(x) => process_other(x), - None => panic!(), -}; -``` - -## `if let` expressions - -An `if let` expression is semantically similar to an `if` expression but in -place of a condition expression it expects the keyword `let` followed by a -refutable pattern, an `=` and an expression. If the value of the expression on -the right hand side of the `=` matches the pattern, the corresponding block -will execute, otherwise flow proceeds to the following `else` block if it -exists. Like `if` expressions, `if let` expressions have a value determined by -the block that is evaluated. - -```rust -let dish = ("Ham", "Eggs"); - -// this body will be skipped because the pattern is refuted -if let ("Bacon", b) = dish { - println!("Bacon is served with {}", b); -} else { - // This block is evaluated instead. - println!("No bacon will be served"); -} - -// this body will execute -if let ("Ham", b) = dish { - println!("Ham is served with {}", b); -} -``` - -## `while let` loops - -A `while let` loop is semantically similar to a `while` loop but in place of a -condition expression it expects the keyword `let` followed by a refutable -pattern, an `=` and an expression. If the value of the expression on the right -hand side of the `=` matches the pattern, the loop body block executes then -control returns to the pattern matching statement. Otherwise, the while -expression completes. - -```rust -let mut x = vec![1, 2, 3]; - -while let Some(y) = x.pop() { - println!("y = {}", y); -} -``` - -## `return` expressions - -Return expressions are denoted with the keyword `return`. Evaluating a `return` -expression moves its argument into the designated output location for the -current function call, destroys the current function activation frame, and -transfers control to the caller frame. - -An example of a `return` expression: - -```rust -fn max(a: i32, b: i32) -> i32 { - if a > b { - return a; - } - return b; -} -``` +[block expressions]: expressions/block-expr.html +[call expressions]: expressions/call-expr.html +[closure expressions]: expressions/closure-expr.html +[enum variant]: expressions/enum-variant-expr.html +[field]: expressions/field-expr.html +[literals]: expressions/literal-expr.html +[match]: expressions/match-expr.html +[method-call]: expressions/method-call-expr.html +[paths]: expressions/path-expr.html +[range expressions]: expressions/range-expr.html +[struct]: expressions/struct-expr.html +[tuple expressions]: expressions/tuple-expr.html + +[array expressions]: expressions/array-expr.html +[array indexing]: expressions/array-expr.html#array-and-slice-indexing-expressions + +[arithmetic, logical]: expressions/operator-expr.html#arithmetic-and-logical-binary-operators +[assign]: expressions/operator-expr.html#assignment-expressions +[borrow]: expressions/operator-expr.html#borrow-operators +[cast]: expressions/operator-expr.html#type-cast-expressions +[comparison]: expressions/operator-expr.html#comparison-operators +[compound assignment]: expressions/operator-expr.html#compound-assignment-expressions +[dereferences]: expressions/operator-expr.html#the-dereference-operator +[dereferencing]: expressions/operator-expr.html#the-dereference-operator +[dereference operator]: expressions/operator-expr.html#the-dereference-operator +[grouped]: expressions/operator-expr.html#grouped-expressions +[lazy boolean]: expressions/operator-expr.html#lazy-boolean-operators +[negation]: expressions/operator-expr.html#negation-operators +[overflow]: expressions/operator-expr.html#overflow + +[slice]: types.html#array-and-slice-types diff --git a/src/expressions/array-expr.md b/src/expressions/array-expr.md new file mode 100644 index 0000000000000..00e81356dac30 --- /dev/null +++ b/src/expressions/array-expr.md @@ -0,0 +1,53 @@ +# Array and array index expressions + +## Array expressions + +An _[array](types.html#array-and-slice-types) expression_ can be written by +enclosing zero or more comma-separated expressions of uniform type in square +brackets. This produces and array containing each of these values in the +order they are written. + +Alternatively there can be exactly two expressions inside the brackets, +separated by a semi-colon. The expression after the `;` must be a have type +`usize` and be a [constant expression](expressions.html#constant-expressions), +such as a [literal](tokens.html#literals) or a [constant +item](items/constant-items.html). `[a; b]` creates an array containing `b` +copies of the value of `a`. If the expression after the semi-colon has a value +greater than 1 then this requires that the type of `a` is +[`Copy`](the-copy-trait.html). + +```rust +[1, 2, 3, 4]; +["a", "b", "c", "d"]; +[0; 128]; // array with 128 zeros +[0u8, 0u8, 0u8, 0u8]; +``` + +## Array and slice indexing expressions + +[Array and slice](types.html#array-and-slice-types)-typed expressions can be +indexed by writing a square-bracket-enclosed expression (the index) after them. +When the array is mutable, the resulting +[lvalue](expressions.html#lvalues-and-rvalues) can be assigned to. +For other types an index expression `a[b]` is equivalent to +`*std::ops::Index::index(&a, b)`, or `*std::opsIndexMut::index_mut(&mut a, b)` +in a mutable lvalue context. Just as with methods, Rust will also insert +dereference operations on `a` repeatedly to find an implementation. + +Indices are zero-based, and are of type `usize` for arrays and slices. Array +access is a [constant expression](expressions.html#constant-expressions), so bounds can be +checked at compile-time for constant arrays with a constant index value. +Otherwise a check will be performed at run-time that will put the thread in a +_panicked state_ if it fails. + +```rust,should_panic +([1, 2, 3, 4])[2]; // Evaluates to 3 + +let x = (["a", "b"])[10]; // warning: const index-expr is out of bounds + +let n = 10; +let y = (["a", "b"])[n]; // panics + +let arr = ["a", "b"]; +arr[10]; // panics +``` diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md new file mode 100644 index 0000000000000..ee0d8c14d18a0 --- /dev/null +++ b/src/expressions/block-expr.md @@ -0,0 +1,34 @@ +# Block expressions + +A _block expression_ is similar to a module in terms of the declarations that +are possible, but can also contain [statements](statements.html) and end with +an expression. Each block conceptually introduces a new namespace scope. Use +items can bring new names into scopes and declared items are in scope for only +the block itself. + +A block will execute each statement sequentially, and then execute the +expression (if given). If the block doesn't end in an expression, its value is +`()`: + +```rust +let x: () = { println!("Hello."); }; +``` + +If it ends in an expression, its value and type are that of the expression: + +```rust +let x: i32 = { println!("Hello."); 5 }; + +assert_eq!(5, x); +``` + +Blocks are always [rvalues](expressions.html#lvalues-and-rvalues) and evaluate the last +expression in rvalue context. This can be used to force moving a value +if really needed. + +## `unsafe` blocks + +_See [`unsafe` block](unsafe-blocks.html) for more information on when to use `unsafe`_ + +A block of code can be prefixed with the `unsafe` keyword, to permit calling +`unsafe` functions or dereferencing raw pointers within a safe function. diff --git a/src/expressions/call-expr.md b/src/expressions/call-expr.md new file mode 100644 index 0000000000000..1e2ad8518fd0d --- /dev/null +++ b/src/expressions/call-expr.md @@ -0,0 +1,89 @@ +# Call expressions + +A _call expression_ consists of an expression followed by a parenthesized +expression-list. It invokes a function, providing zero or more input variables. +If the function eventually returns, then the expression completes. For +[non-function types](types.html#function-item-types), the expression f(...) uses the +method on one of the `std::ops::Fn`, `std::ops::FnMut` or `std::ops::FnOnce` +traits, which differ in whether they take the type by reference, mutable +reference, or take ownership respectively. An automatic borrow will be taken if +needed. Rust will also automatically dereference `f` as required. Some examples +of call expressions: + +```rust +# fn add(x: i32, y: i32) -> i32 { 0 } +let three: i32 = add(1i32, 2i32); +let name: &'static str = (|| "Rust")(); +``` + +## Disambiguating Function Calls + +Rust treats all function calls as sugar for a more explicit, fully-qualified +syntax. Upon compilation, Rust will desugar all function calls into the explicit +form. Rust may sometimes require you to qualify function calls with trait, +depending on the ambiguity of a call in light of in-scope items. + +> **Note**: In the past, the Rust community used the terms "Unambiguous +> Function Call Syntax", "Universal Function Call Syntax", or "UFCS", in +> documentation, issues, RFCs, and other community writings. However, the term +> lacks descriptive power and potentially confuses the issue at hand. We mention +> it here for searchability's sake. + +Several situations often occur which result in ambiguities about the receiver or +referent of method or associated function calls. These situations may include: + +* Multiple in-scope traits define methods with the same name for the same types +* Auto-`deref` is undesirable; for example, distinguishing between methods on a + smart pointer itself and the pointer's referent +* Methods which take no arguments, like `default()`, and return properties of a + type, like `size_of()` + +To resolve the ambiguity, the programmer may refer to their desired method or +function using more specific paths, types, or traits. + +For example, + +```rust +trait Pretty { + fn print(&self); +} + +trait Ugly { + fn print(&self); +} + +struct Foo; +impl Pretty for Foo { + fn print(&self) {} +} + +struct Bar; +impl Pretty for Bar { + fn print(&self) {} +} +impl Ugly for Bar{ + fn print(&self) {} +} + +fn main() { + let f = Foo; + let b = Bar; + + // we can do this because we only have one item called `print` for `Foo`s + f.print(); + // more explicit, and, in the case of `Foo`, not necessary + Foo::print(&f); + // if you're not into the whole brevity thing + ::print(&f); + + // b.print(); // Error: multiple 'print' found + // Bar::print(&b); // Still an error: multiple `print` found + + // necessary because of in-scope items defining `print` + ::print(&b); +} +``` + +Refer to [RFC 132] for further details and motivations. + +[RFC 132]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md diff --git a/src/expressions/closure-expr.md b/src/expressions/closure-expr.md new file mode 100644 index 0000000000000..339763ae86904 --- /dev/null +++ b/src/expressions/closure-expr.md @@ -0,0 +1,58 @@ +# Closure expressions + +A _closure expression_ defines a closure and denotes it as a value, in a single +expression. A closure expression is a pipe-symbol-delimited (`|`) list of +patterns followed by an expression. Type annotations may optionally be added +for the type of the parameters or for the return type. If there is a return +type, the expression used for the body of the closure must be a normal +[block]. A closure expression also may begin with the +`move` keyword before the initial `|`. + +A closure expression denotes a function that maps a list of parameters +(`ident_list`) onto the expression that follows the `ident_list`. The patterns +in the `ident_list` are the parameters to the closure. If a parameter's types +is not specified, then the compiler infers it from context. Each closure +expression has a unique anonymous type. + +Closure expressions are most useful when passing functions as arguments to other +functions, as an abbreviation for defining and capturing a separate function. + +Significantly, closure expressions _capture their environment_, which regular +[function definitions] do not. Without the `move` +keyword, the closure expression infers how it captures each variable from its +environment, preferring to capture by shared reference, effectively borrowing +all outer variables mentioned inside the closure's body. If needed the compiler +will infer that instead mutable references should be taken, or that the values +should be moved or copied (depending on their type) from the environment. A +closure can be forced to capture its environment by copying or moving values by +prefixing it with the `move` keyword. This is often used to ensure that the +closure's type is `'static`. + +The compiler will determine which of the [closure +traits](types.html#closure-types) the closure's type will implement by how it +acts on its captured variables. The closure will also implement +[`Send`](the-send-trait.html) and/or [`Sync`](the-sync-trait.html) if all of +its captured types do. These traits allow functions to accept closures using +generics, even though the exact types can't be named. + +In this example, we define a function `ten_times` that takes a higher-order +function argument, and we then call it with a closure expression as an argument, +followed by a closure expression that moves values from its environment. + +```rust +fn ten_times(f: F) where F: Fn(i32) { + for index in 0..10 { + f(index); + } +} + +ten_times(|j| println!("hello, {}", j)); +// With type annotations +ten_times(|j: i32| -> () { println!("hello, {}", j) }); + +let word = "konnichiwa".to_owned(); +ten_times(move |j| println!("{}, {}", word, j)); +``` + +[block]: expressions/block-expr.html +[function definitions]: items/functions.html diff --git a/src/expressions/enum-variant-expr.md b/src/expressions/enum-variant-expr.md new file mode 100644 index 0000000000000..333b909f8210d --- /dev/null +++ b/src/expressions/enum-variant-expr.md @@ -0,0 +1,15 @@ +# Enumeration Variant expressions + +Enumeration variants can be constructed similarly to structs, using a path to +an enum variant instead of to a struct: + +```rust +# enum Message { +# Quit, +# WriteString(String), +# Move { x: i32, y: i32 }, +# } +let q = Message::Quit; +let w = Message::WriteString("Some string".to_string()); +let m = Message::Move { x: 50, y: 200 }; +``` diff --git a/src/expressions/field-expr.md b/src/expressions/field-expr.md new file mode 100644 index 0000000000000..44b89ce0ab6c2 --- /dev/null +++ b/src/expressions/field-expr.md @@ -0,0 +1,43 @@ +# Field access expressions + +A _field expression_ consists of an expression followed by a single dot and an +[identifier](identifiers.html), when not immediately followed by a +parenthesized expression-list (the latter is always a [method call +expression](#method-call-expressions)). A field expression denotes a field of a +[struct](types.html#struct-types) or [union](items/unions.html). To call a +function stored in a struct parentheses are needed around the field expression + +```rust,ignore +mystruct.myfield; +foo().x; +(Struct {a: 10, b: 20}).a; +mystruct.method(); // Method expression +(mystruct.function_field)() // Call expression containing a field expression +``` + +A field access is an [lvalue](expressions.html#lvalues-and-rvalues) referring +to the location of that field. When the subexpression is +[mutable](expressions.html#mutability), the field expression is also mutable. + +Also, if the type of the expression to the left of the dot is a pointer, it is +automatically dereferenced as many times as necessary to make the field access +possible. In cases of ambiguity, we prefer fewer autoderefs to more. + +Finally the fields of a struct, a reference to a struct are treated as separate +entities when borrowing. If the struct does not implement +[`Drop`](the-drop-trait.html) this also applies to moving out of each of its fields +where possible. This also does not apply if automatic dereferencing is done +though user defined types. + +```rust +# struct A { f1: String, f2: String, f3: String } +# let mut x = A { +# f1: "f1".to_string(), +# f2: "f2".to_string(), +# f3: "f3".to_string() +# }; +let a: &mut String = &mut x.f1; // x.f1 borrowed mutably +let b: &String = &x.f2; // x.f2 borrowed immutably +let c: &String = &x.f2; // Can borrow again +let d: String = x.f3; // Move out of x.f3 +``` diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md new file mode 100644 index 0000000000000..585f316c4a5d4 --- /dev/null +++ b/src/expressions/if-expr.md @@ -0,0 +1,59 @@ +# `if` and `if let` expressions + +## `if` expressions + +An `if` expression is a conditional branch in program control. The form of an +`if` expression is a condition expression, followed by a consequent block, any +number of `else if` conditions and blocks, and an optional trailing `else` +block. The condition expressions must have type `bool`. If a condition +expression evaluates to `true`, the consequent block is executed and any +subsequent `else if` or `else` block is skipped. If a condition expression +evaluates to `false`, the consequent block is skipped and any subsequent `else +if` condition is evaluated. If all `if` and `else if` conditions evaluate to +`false` then any `else` block is executed. An if expression evaluates to the +same value as the executed block, or `()` if no block is evaluated. An `if` +expression must have the same type in all situations. + +```rust +# let x = 3; +if x == 4 { + println!("x is four"); +} else if x == 3 { + println!("x is three"); +} else { + println!("x is something else"); +} + +let y = if 12 * 15 > 150 { + "Bigger" +} else { + "Smaller" +}; +assert_eq!(y, "Bigger"); +``` +## `if let` expressions + +An `if let` expression is semantically similar to an `if` expression but in +place of a condition expression it expects the keyword `let` followed by a +refutable pattern, an `=` and an expression. If the value of the expression on +the right hand side of the `=` matches the pattern, the corresponding block +will execute, otherwise flow proceeds to the following `else` block if it +exists. Like `if` expressions, `if let` expressions have a value determined by +the block that is evaluated. + +```rust +let dish = ("Ham", "Eggs"); + +// this body will be skipped because the pattern is refuted +if let ("Bacon", b) = dish { + println!("Bacon is served with {}", b); +} else { + // This block is evaluated instead. + println!("No bacon will be served"); +} + +// this body will execute +if let ("Ham", b) = dish { + println!("Ham is served with {}", b); +} +``` diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md new file mode 100644 index 0000000000000..5b1ef77872295 --- /dev/null +++ b/src/expressions/literal-expr.md @@ -0,0 +1,11 @@ +# Literal expressions + +A _literal expression_ consists of one of the [literal](tokens.html#literals) +forms described earlier. It directly describes a number, character, string, +or boolean value. + +```rust +"hello"; // string type +'5'; // character type +5; // integer type +``` diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md new file mode 100644 index 0000000000000..37ba2f21b820b --- /dev/null +++ b/src/expressions/loop-expr.md @@ -0,0 +1,167 @@ +# Loops + +Rust supports four loop expressions: + +* A [`loop` expression](#infinite-loops) denotes an infinite loop. +* A [`while` expression](#predicate-loops) loops until a predicate is false. +* A [`while let` expression](#while-let-loops) tests a refutable pattern. +* A [`for` expression](#iterator-loops) extracts values from an iterator, + looping until the iterator is empty. + +All four types of loop support [`break` expressions](#break-expressions), +[`continue` expressions](#continue-expressions), and [labels](#loop-labels). +Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values). + +## Infinite loops + +A `loop` expression repeats execution of its body continuously: +`loop { println!("I live."); }`. + +A `loop` expression without an associated `break` expression is +[diverging](items/functions.html#diverging-functions), and doesn't +return anything. A `loop` expression containing associated +[`break` expression(s)](#break-expressions) +may terminate, and must have type compatible with the value of the `break` +expression(s). + +## Predicate loops + +A `while` loop begins by evaluating the boolean loop conditional expression. If +the loop conditional expression evaluates to `true`, the loop body block +executes, then control returns to the loop conditional expression. If the loop +conditional expression evaluates to `false`, the `while` expression completes. + +An example: + +```rust +let mut i = 0; + +while i < 10 { + println!("hello"); + i = i + 1; +} +``` + +## `while let` loops + +A `while let` loop is semantically similar to a `while` loop but in place of a +condition expression it expects the keyword `let` followed by a refutable +pattern, an `=` and an expression. If the value of the expression on the right +hand side of the `=` matches the pattern, the loop body block executes then +control returns to the pattern matching statement. Otherwise, the while +expression completes. + +```rust +let mut x = vec![1, 2, 3]; + +while let Some(y) = x.pop() { + println!("y = {}", y); +} +``` + +## Iterator loops + +A `for` expression is a syntactic construct for looping over elements provided +by an implementation of `std::iter::IntoIterator`. If the iterator yields a +value, that value is given the specified name and the body of the loop is +executed, then control returns to the head of the `for` loop. If the iterator +is empty, the `for` expression completes. + +An example of a `for` loop over the contents of an array: + +```rust +let v = &["apples", "cake", "coffee"]; + +for text in v { + println!("I like {}.", text); +} +``` + +An example of a for loop over a series of integers: + +```rust +let mut sum = 0; +for n in 1..11 { + sum += n; +} +assert_eq!(sum, 55); +``` + +## Loop labels + +A loop expression may optionally have a _label_. The label is written as +a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`, +`'bar: while false {}`, `'humbug: for _ in 0..0 {}`. +If a label is present, then labeled `break` and `continue` expressions nested +within this loop may exit out of this loop or return control to its head. +See [break expressions](#break-expressions) and [continue +expressions](#continue-expressions). + +## `break` expressions + +When `break` is encountered, execution of the associated loop body is +immediately terminated, for example: + +```rust +let mut last = 0; +for x in 1..100 { + if x > 12 { + break; + } + last = x; +} +assert_eq!(last, 12); +``` + +A `break` expression is normally associated with the innermost `loop`, `for` or +`while` loop enclosing the `break` expression, but a [label](#loop-labels) can +be used to specify which enclosing loop is affected. Example: + +```rust +'outer: loop { + while true { + break 'outer; + } +} +``` + +A `break` expression is only permitted in the body of a loop, and has one of +the forms `break`, `break 'label` or ([see below](#break-and-loop-values)) +`break EXPR` or `break 'label EXPR`. + +## `continue` expressions + +When `continue` is encountered, the current iteration of the associated loop +body is immediately terminated, returning control to the loop *head*. In +the case of a `while` loop, the head is the conditional expression controlling +the loop. In the case of a `for` loop, the head is the call-expression +controlling the loop. + +Like `break`, `continue` is normally associated with the innermost enclosing +loop, but `continue 'label` may be used to specify the loop affected. +A `continue` expression is only permitted in the body of a loop. + +## `break` and loop values + +When associated with a `loop`, a break expression may be used to return a value +from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where +`EXPR` is an expression whose result is returned from the `loop`. For example: + +```rust +let (mut a, mut b) = (1, 1); +let result = loop { + if b > 10 { + break b; + } + let c = a + b; + a = b; + b = c; +}; +// first number in Fibonacci sequence over 10: +assert_eq!(result, 13); +``` + +In the case a `loop` has an associated `break`, it is not considered diverging, +and the `loop` must have a type compatible with each `break` expression. +`break` without an expression is considered identical to `break` with +expression `()`. diff --git a/src/expressions/match-expr.md b/src/expressions/match-expr.md new file mode 100644 index 0000000000000..1a4de06a63ff9 --- /dev/null +++ b/src/expressions/match-expr.md @@ -0,0 +1,128 @@ +# `match` expressions + +A `match` expression branches on a *pattern*. The exact form of matching that +occurs depends on the pattern. Patterns consist of some combination of +literals, destructured arrays or enum constructors, structs and tuples, +variable binding specifications, wildcards (`..`), and placeholders (`_`). A +`match` expression has a *head expression*, which is the value to compare to +the patterns. The type of the patterns must equal the type of the head +expression. + +A `match` behaves differently depending on whether or not the head expression +is an [lvalue or an rvalue](expressions.html#lvalues-and-rvalues). +If the head expression is an rvalue, it is first evaluated into a temporary +location, and the resulting value is sequentially compared to the patterns in +the arms until a match is found. The first arm with a matching pattern is +chosen as the branch target of the `match`, any variables bound by the pattern +are assigned to local variables in the arm's block, and control enters the +block. + +When the head expression is an lvalue, the match does not allocate a temporary +location (however, a by-value binding may copy or move from the lvalue). When +possible, it is preferable to match on lvalues, as the lifetime of these +matches inherits the lifetime of the lvalue, rather than being restricted to +the inside of the match. + +An example of a `match` expression: + +```rust +let x = 1; + +match x { + 1 => println!("one"), + 2 => println!("two"), + 3 => println!("three"), + 4 => println!("four"), + 5 => println!("five"), + _ => println!("something else"), +} +``` + +Patterns that bind variables default to binding to a copy or move of the +matched value (depending on the matched value's type). This can be changed to +bind to a reference by using the `ref` keyword, or to a mutable reference using +`ref mut`. + +Patterns can be used to *destructure* structs, enums, and tuples. Destructuring +breaks a value up into its component pieces. The syntax used is the same as +when creating such values. When destructing a data structure with named (but +not numbered) fields, it is allowed to write `fieldname` as a shorthand for +`fieldname: fieldname`. In a pattern whose head expression has a `struct`, +`enum` or `tupl` type, a placeholder (`_`) stands for a *single* data field, +whereas a wildcard `..` stands for *all* the fields of a particular variant. + +```rust +# enum Message { +# Quit, +# WriteString(String), +# Move { x: i32, y: i32 }, +# ChangeColor(u8, u8, u8), +# } +# let message = Message::Quit; +match message { + Message::Quit => println!("Quit"), + Message::WriteString(write) => println!("{}", &write), + Message::Move{ x, y: 0 } => println!("move {} horizontally", x), + Message::Move{ .. } => println!("other move"), + Message::ChangeColor { 0: red, 1: green, 2: _ } => { + println!("color change, red: {}, green: {}", red, green); + } +}; +``` + +Patterns can also dereference pointers by using the `&`, `&mut` and `box` +symbols, as appropriate. For example, these two matches on `x: &i32` are +equivalent: + +```rust +# let x = &3; +let y = match *x { 0 => "zero", _ => "some" }; +let z = match x { &0 => "zero", _ => "some" }; + +assert_eq!(y, z); +``` + +Subpatterns can also be bound to variables by the use of the syntax `variable @ +subpattern`. For example: + +```rust +let x = 1; + +match x { + e @ 1 ... 5 => println!("got a range element {}", e), + _ => println!("anything"), +} +``` + +Multiple match patterns may be joined with the `|` operator. A range of values +may be specified with `...`. For example: + +```rust +# let x = 2; +let message = match x { + 0 | 1 => "not many", + 2 ... 9 => "a few", + _ => "lots" +}; +``` + +Range patterns only work on scalar types (like integers and characters; not +like arrays and structs, which have sub-components). A range pattern may not be +a sub-range of another range pattern inside the same `match`. + +Finally, match patterns can accept *pattern guards* to further refine the +criteria for matching a case. Pattern guards appear after the pattern and +consist of a bool-typed expression following the `if` keyword. A pattern guard +may refer to the variables bound within the pattern they follow. + +```rust +# let maybe_digit = Some(0); +# fn process_digit(i: i32) { } +# fn process_other(i: i32) { } +let message = match maybe_digit { + Some(x) if x < 10 => process_digit(x), + Some(x) => process_other(x), + None => panic!(), +}; +``` + diff --git a/src/expressions/method-call-expr.md b/src/expressions/method-call-expr.md new file mode 100644 index 0000000000000..0db205a31f5ed --- /dev/null +++ b/src/expressions/method-call-expr.md @@ -0,0 +1,51 @@ +# Method-call expressions + +A _method call_ consists of an expression followed by a single dot, an +[identifier](identifiers.html), and a parenthesized expression-list. Method +calls are resolved to methods on specific traits, either statically dispatching +to a method if the exact `self`-type of the left-hand-side is known, or +dynamically dispatching if the left-hand-side expression is an indirect [trait +object](types.html#trait-objects). Method call expressions will automatically +take a shared or mutable borrow of the receiver if needed. + +```rust +let pi: Result = "3.14".parse(); +let log_pi = pi.unwrap_or(1.0).log(2.72); +# assert!(1.14 < log_pi && log_pi < 1.15) +``` + +When resolving method calls on an expression of type `A`, Rust will use the +following order: + +1. Inherent methods, with receiver of type `A`, `&A`, `&mut A`. +1. Trait methods with receiver of type `A`. +1. Trait methods with receiver of type `&A`. +1. Trait methods with receiver of type `&mut A`. +1. If it's possible, Rust will then repeat steps 1-5 with + `
::Target`, and insert a dereference operator. +1. If `A` is now an [array](types.html#array-and-slice-types) type, then + repeat steps 1-4 with the corresponding slice type. + +Note: that in steps 1-4 the receiver is used, not the type of `Self` nor the +type of `A`. For example + +```rust,ignore +// `Self` is `&A`, receiver is `&A`. +impl<'a> Trait for &'a A { + fn method(self) {} +} +// If `A` is `&B`, then `Self` is `B` and the receiver is `A`. +impl B { + fn method(&self) {} +} +``` + +Another note: this process does not use the mutability or lifetime of the +receiver, or whether `unsafe` methods can currently be called to resolve +methods. These constraints instead lead to compiler errors. + +If a step is reached where there is more than one possible method (where +generic methods or traits are considered the same), then it is a compiler +error. These cases require a [more specific +syntax.](expressions/call-expr.html#disambiguating-function-calls) for method +and function invocation. diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md new file mode 100644 index 0000000000000..c85d0438d9e4b --- /dev/null +++ b/src/expressions/operator-expr.md @@ -0,0 +1,359 @@ +# Operator expressions + +Operators are defined for built in types by the Rust language. Many of the +following operators can also be overloaded using traits in `std::ops` or +`std::cmp`. + +## Overflow + +Integer operators will panic when they overflow when compiled in debug mode. +The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used +to control this more directly. The following things are considered to be +overflow: + +* When `+`, `*` or `-` create a value greater than the maximum value, or less + than the minimum value that can be stored. This includes unary `-` on the + smallest value of any signed integer type. +* Using `/` or `%`, where the left-hand argument is the smallest integer of a + signed integer type and the right-hand argument is `-1`. +* Using `<<` or `>>` where the right-hand argument is greater than or equal to + the number of bits in the type of the left-hand argument, or is negative. + +## Grouped expressions + +An expression enclosed in parentheses evaluates to the result of the enclosed +expression. Parentheses can be used to explicitly specify evaluation order +within an expression. + +An example of a parenthesized expression: + +```rust +let x: i32 = 2 + 3 * 4; +let y: i32 = (2 + 3) * 4; +assert_eq!(x, 14); +assert_eq!(y, 20); +``` + +## Borrow operators + +The `&` (shared borrow) and `&mut` (mutable borrow) operators are unary prefix +operators. When applied to an lvalue produce a reference (pointer) to the +location that the value refers to. The lvalue is also placed into a borrowed +state for the duration of the reference. For a shared borrow (`&`), this +implies that the lvalue may not be mutated, but it may be read or shared again. +For a mutable borrow (`&mut`), the lvalue may not be accessed in any way until +the borrow expires. `&mut` evaluates its operand in a mutable lvalue context. +If the `&` or `&mut` operators are applied to an rvalue, a temporary value is +created; the lifetime of this temporary value is defined by [syntactic +rules](expressions.html#temporary-lifetimes). These operators cannot be overloaded. + +```rust +{ + // a temporary with value 7 is created that lasts for this scope. + let shared_reference = &7; +} +let mut array = [-2, 3, 9]; +{ + // Mutably borrows `array` for this scope. + // `array` may only be used through `mutable_reference`. + let mutable_reference = &mut array; +} +``` + +## The dereference operator + +The `*` (dereference) operator is also a unary prefix operator. When applied to +a [pointer](types.html#pointer-types) it denotes the pointed-to location. If +the expression is of type `&mut T` and `*mut T`, and is either a local +variable, a (nested) field of a local variance or is a mutable lvalue, then the +resulting [lvalue](expressions.html#lvalues-and-rvalues) can be +assigned to. Dereferencing a raw pointer requires `unsafe`. + +On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an +[immutable lvalue context](expressions.html#mutability) and +`*std::ops::Deref::deref_mut(&mut x)` in a mutable lvalue context. + +```rust +let x = &7; +assert_eq!(*x, 7); +let y = &mut 9; +*y = 11; +assert_eq!(*y, 11); +``` + +## The `?` operator. + +The `?` ("question mark") operator can be applied to values of the `Result` type to propagate errors. If applied to `Err(e)` it will return +`Err(From::from(e))` from the enclosing function or closure. If applied to +`Ok(x)` it will unwrap the value to return `x`. Unlike other unary operators +`?` is written in postfix notation. `?` cannot be overloaded. + +```rust +# use std::num::ParseIntError; +fn try_to_parse() -> Result { + let x: i32 = "123".parse()?; // x = 123 + let y: i32 = "24a".parse()?; // returns an Err() immediately + Ok(x + y) // Doesn't run. +} + +let res = try_to_parse(); +println!("{:?}", res); +# assert!(res.is_err()) +``` + +## Negation operators + +These are the last two unary operators. This table summarizes the behavior of +them on primitive types and which traits are used to overload these operators +for other types. Remember that signed integers are always represented using +two's complement. The operands of all of these operators are evaluated in +rvalue context so are moved or copied. + +| Symbol | Integer | `bool` | Floating Point | Overloading Trait | +|--------|-------------|-------------|----------------|--------------------| +| `-` | Negation* | | Negation | `std::ops::Neg` | +| `!` | Bitwise NOT | Logical NOT | | `std::ops::Not` | + +\* Only for signed integer types. + +Here are some example of these operators + +```rust +let x = 6; +assert_eq!(-x, -6); +assert_eq!(!x, -7); +assert_eq!(true, !false); +``` + +## Arithmetic and Logical Binary Operators + +Binary operators expressions are all written with infix notation. This table +summarizes the behavior of arithmetic and logical binary operators on +primitive types and which traits are used to overload these operators for other +types. Remember that signed integers are always represented using two's +complement. The operands of all of these operators are evaluated in rvalue +context so are moved or copied. + +| Symbol | Integer | `bool` | Floating Point | Overloading Trait | +|--------|-------------------------|-------------|----------------|--------------------| +| `+` | Addition | | Addition | `std::ops::Add` | +| `-` | Subtraction | | Subtraction | `std::ops::Sub` | +| `*` | Multiplication | | Multiplication | `std::ops::Mul` | +| `/` | Division | | Division | `std::ops::Div` | +| `%` | Remainder | | Remainder | `std::ops::Rem` | +| `&` | Bitwise AND | Logical AND | | `std::ops::BitAnd` | +| | | Bitwise OR | Logical OR | | `std::ops::BitOr` | +| `^` | Bitwise XOR | Logical XOR | | `std::ops::BitXor` | +| `<<` | Left Shift | | | `std::ops::Shl` | +| `>>` | Right Shift* | | | `std::ops::Shr` | + +\* Arithmetic right shift on signed integer types, logical right shift on +unsigned integer types. + +Here are examples of these operators being used. + +```rust +assert_eq!(3 + 6, 9); +assert_eq!(5.5 - 1.25, 4.25); +assert_eq!(-5 * 14, -70); +assert_eq!(14 / 3, 4); +assert_eq!(100 % 7, 2); +assert_eq!(0b1010 & 0b1100, 0b1000); +assert_eq!(0b1010 | 0b1100, 0b1110); +assert_eq!(0b1010 ^ 0b1100, 0b110); +assert_eq!(13 << 3, 104); +assert_eq!(-10 >> 2, -3); +``` + +## Comparison Operators + +Comparison operators are also defined both for primitive types and many type in +the standard library. Parentheses are required when chaining comparison +operators. For example, the expression `a == b == c` is invalid and may be +written as `(a == b) == c`. + +Unlike arithmetic and logical operators, the traits for +overloading the operators the traits for these operators are used more +generally to show how a type may be compared and will likely be assumed to +define actual comparisons by functions that use these traits as bounds. Many +functions and macros in the standard library can then use that assumption +(although not to ensure safety). Unlike the arithmetic and logical operators +above, these operators implicitly take shared borrows of their operands, +evaluating them in lvalue context: + +```rust,ignore +a == b; +// is equivalent to +::std::cmp::PartialEq::eq(&a, &b); +``` + +This means that the operands don't have to be moved out of. + +| Symbol | Meaning | Overloading method | +|--------|--------------------------|----------------------------| +| `==` | Equal | `std::cmp::PartialEq::eq` | +| `!=` | Not equal | `std::cmp::PartialEq::ne` | +| `>` | Greater than | `std::cmp::PartialOrd::gt` | +| `<` | Less than | `std::cmp::PartialOrd::lt` | +| `>=` | Greater than or equal to | `std::cmp::PartialOrd::ge` | +| `<=` | Less than or equal to | `std::cmp::PartialOrd::le` | + +Here are examples of the comparison operators being used. + +```rust +assert!(123 == 123); +assert!(23 != -12); +assert!(12.5 > 12.2); +assert!([1, 2, 3] < [1, 3, 4]); +assert!('A' <= 'B'); +assert!("World" >= "Hello"); +``` + +## Lazy boolean operators + +The operators `||` and `&&` may be applied to operands of boolean type. The +`||` operator denotes logical 'or', and the `&&` operator denotes logical +'and'. They differ from `|` and `&` in that the right-hand operand is only +evaluated when the left-hand operand does not already determine the result of +the expression. That is, `||` only evaluates its right-hand operand when the +left-hand operand evaluates to `false`, and `&&` only when it evaluates to +`true`. + +```rust +let x = false || true; // true +let y = false && panic!(); // false, doesn't evaluate `panic!()` +``` + +## Type cast expressions + +A type cast expression is denoted with the binary operator `as`. + +Executing an `as` expression casts the value on the left-hand side to the type +on the right-hand side. + +An example of an `as` expression: + +```rust +# fn sum(values: &[f64]) -> f64 { 0.0 } +# fn len(values: &[f64]) -> i32 { 0 } +fn average(values: &[f64]) -> f64 { + let sum: f64 = sum(values); + let size: f64 = len(values) as f64; + sum / size +} +``` + +`as` can be used to explicitly perform [coercions](type-coercions.html), as +well as the following additional casts. Here `*T` means either `*const T` or +`*mut T`. + +| Type of `e` | `U` | Cast performed by `e as U` | +|-----------------------|-----------------------|----------------------------------| +| Integer or Float type | Integer or Float type | Numeric cast | +| C-like enum | Integer type | Enum cast | +| `bool` or `char` | Integer type | Primitive to integer cast | +| `u8` | `char` | `u8` to `char` cast | +| `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast | +| `*T` where `T: Sized` | Numeric type | Pointer to address cast | +| Integer type | `*V` where `V: Sized` | Address to pointer cast | +| `&[T; n]` | `*const T` | Array to pointer cast | +| [Function pointer](types.html#function-pointer-types) | `*V` where `V: Sized` | Function pointer to pointer cast | +| Function pointer | Integer | Function pointer to address cast | + +\* or `T` and `V` are compatible unsized types, e.g., both slices, both the +same trait object. + +### Semantics + +* Numeric cast + * Casting between two integers of the same size (e.g. i32 -> u32) is a no-op + * Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will + truncate + * Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will + * zero-extend if the source is unsigned + * sign-extend if the source is signed + * Casting from a float to an integer will round the float towards zero + * **[NOTE: currently this will cause Undefined Behavior if the rounded + value cannot be represented by the target integer type][float-int]**. + This includes Inf and NaN. This is a bug and will be fixed. + * Casting from an integer to float will produce the floating point + representation of the integer, rounded if necessary (rounding strategy + unspecified) + * Casting from an f32 to an f64 is perfect and lossless + * Casting from an f64 to an f32 will produce the closest possible value + (rounding strategy unspecified) + * **[NOTE: currently this will cause Undefined Behavior if the value + is finite but larger or smaller than the largest or smallest finite + value representable by f32][float-float]**. This is a bug and will + be fixed. +* Enum cast + * Casts an enum to its discriminant, then uses a numeric cast if needed. +* Primitive to integer cast + * `false` casts to `0`, `true` casts to `1` + * `char` casts to the value of the code point, then uses a numeric cast if needed. +* `u8` to `char` cast + * Casts to the `char` with the corresponding code point. + +[float-int]: https://github.com/rust-lang/rust/issues/10184 +[float-float]: https://github.com/rust-lang/rust/issues/15536 + +## Assignment expressions + +An _assignment expression_ consists of an +[lvalue](expressions.html#lvalues-and-rvalues) expression followed +by an equals sign (`=`) and an +[rvalue](expressions.html#lvalues-and-rvalues) expression. + +Evaluating an assignment expression [either copies or +moves](expressions.html#moved-and-copied-types) its right-hand operand to its left-hand +operand. The left-hand operand must be an lvalue: using an rvalue results in a +compiler error, rather than promoting it to a temporary. + +```rust +# let mut x = 0; +# let y = 0; +x = y; +``` + +## Compound assignment expressions + +The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be +composed with the `=` operator. The expression `lval OP= val` is equivalent to +`lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`. +Any such expression always has the [`unit`](types.html#tuple-types) type. +These operators can all be overloaded using the trait with the same name as for +the normal operation followed by 'Assign', for example, `std::ops::AddAssign` +is used to overload `+=`. As with `=`, `lval` must be an lvalue. + +```rust +let mut x = 10; +x += 4; +assert_eq!(x, 14); +``` + +## Operator precedence + +The precedence of Rust operators is ordered as follows, going from strong to +weak. Binary Operators at the same precedence level are evaluated in the order +given by their associativity. + + +| Operator | Associativity | +|-----------------------------|---------------------| +| `?` | | +| Unary `-` `*` `!` `&` `&mut` | | +| `as` `:` | left to right | +| `*` `/` `%` | left to right | +| `+` `-` | left to right | +| `<<` `>>` | left to right | +| `&` | left to right | +| `^` | left to right | +| | | left to right | +| `==` `!=` `<` `>` `<=` `>=` | Require parentheses | +| `&&` | left to right | +| || | left to right | +| `..` `...` | Require parentheses | +| `<-` | right to left | +| `=` `+=` `-=` `*=` `/=` `%=`
`&=` |= `^=` `<<=` `>>=` | right to left | + diff --git a/src/expressions/path-expr.md b/src/expressions/path-expr.md new file mode 100644 index 0000000000000..1e33490d4dbba --- /dev/null +++ b/src/expressions/path-expr.md @@ -0,0 +1,21 @@ +# Path expressions + +A [path](paths.html) used as an expression context denotes either a local +variable or an item. Path expressions that resolve to local or static variables +are [lvalues](expressions.html#lvalues-and-rvalues), other paths +are rvalues. Using a `static mut` variable requires an [`unsafe` +block](#unsafe-blocks). + +```rust +# mod globals { +# pub static STATIC_VAR: i32 = 5; +# pub static mut STATIC_MUT_VAR: i32 = 7; +# } +# let local_var = 3; +local_var; +globals::STATIC_VAR; +unsafe { globals::STATIC_MUT_VAR }; +let some_constructor = Some::; +let push_integer = Vec::::push; +let slice_reverse = <[i32]>::reverse; +``` diff --git a/src/expressions/range-expr.md b/src/expressions/range-expr.md new file mode 100644 index 0000000000000..282f3adae753c --- /dev/null +++ b/src/expressions/range-expr.md @@ -0,0 +1,20 @@ +# Range expressions + +The `..` operator will construct an object of one of the `std::ops::Range` (or +`core::ops::Range`) variants. + +```rust +1..2; // std::ops::Range +3..; // std::ops::RangeFrom +..4; // std::ops::RangeTo +..; // std::ops::RangeFull +``` + +The following expressions are equivalent. + +```rust +let x = std::ops::Range {start: 0, end: 10}; +let y = 0..10; + +assert_eq!(x, y); +``` diff --git a/src/expressions/return-expr.md b/src/expressions/return-expr.md new file mode 100644 index 0000000000000..b76a34a989250 --- /dev/null +++ b/src/expressions/return-expr.md @@ -0,0 +1,17 @@ +# `return` expressions + +Return expressions are denoted with the keyword `return`. Evaluating a `return` +expression moves its argument into the designated output location for the +current function call, destroys the current function activation frame, and +transfers control to the caller frame. + +An example of a `return` expression: + +```rust +fn max(a: i32, b: i32) -> i32 { + if a > b { + return a; + } + return b; +} +``` diff --git a/src/expressions/struct-expr.md b/src/expressions/struct-expr.md new file mode 100644 index 0000000000000..b656dc97c4361 --- /dev/null +++ b/src/expressions/struct-expr.md @@ -0,0 +1,80 @@ +# Struct expressions + +There are several forms of struct expressions. A _struct expression_ consists +of the [path](paths.html) of a [struct item](items/structs.html), followed by a +brace-enclosed list of zero or more comma-separated name-value pairs, providing +the field values of a new instance of the struct. A field name can be any +[identifier](identifiers.html), and is separated from its value expression by a +colon. In the case of a tuple struct the field names are numbers corresponding +to the position of the field. The numbers must be written in decimal, +containing no underscores and with no leading zeros or integer suffix. A value +of a [union](items/unions.html) type can also be created using this syntax, +except that it must specify exactly one field. + +Struct expressions can't be used directly in the head of a [loop] +or an [if], [if let] or [match] expression. But struct expressions can still be +in used inside parentheses, for example. + +[loop]: expressions/loop-expr.html +[if]: expressions/if-expr.html#if-expressions +[if let]: expressions/if-expr.html#if-let-expressions +[match]: expressions/match-expr.html + +A _tuple struct expression_ consists of the path of a struct item, followed by +a parenthesized list of one or more comma-separated expressions (in other +words, the path of a struct item followed by a tuple expression). The struct +item must be a tuple struct item. + +A _unit-like struct expression_ consists only of the path of a struct item. + +The following are examples of struct expressions: + +```rust +# struct Point { x: f64, y: f64 } +# struct NothingInMe { } +# struct TuplePoint(f64, f64); +# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } } +# struct Cookie; fn some_fn(t: T) {} +Point {x: 10.0, y: 20.0}; +NothingInMe {}; +TuplePoint(10.0, 20.0); +TuplePoint { 0: 10.0, 1: 20.0 }; // Results in the same value as the above line +let u = game::User {name: "Joe", age: 35, score: 100_000}; +some_fn::(Cookie); +``` + +A struct expression forms a new value of the named struct type. Note that for a +given *unit-like* struct type, this will always be the same value. + +A struct expression can terminate with the syntax `..` followed by an +expression to denote a functional update. The expression following `..` (the +base) must have the same struct type as the new struct type being formed. The +entire expression denotes the result of constructing a new struct (with the +same type as the base expression) with the given values for the fields that +were explicitly specified and the values in the base expression for all other +fields. Just as with all struct expressions, all of the fields of the struct +must be [visible](visibility-and-privacy.html), even those not explicitly +named. + +```rust +# struct Point3d { x: i32, y: i32, z: i32 } +let base = Point3d {x: 1, y: 2, z: 3}; +Point3d {y: 0, z: 10, .. base}; +``` + +## Struct field init shorthand + +When initializing a data structure (struct, enum, union) with named (but not +numbered) fields, it is allowed to write `fieldname` as a shorthand for +`fieldname: fieldname`. This allows a compact syntax with less duplication. + +Example: + +```rust +# struct Point3d { x: i32, y: i32, z: i32 } +# let x = 0; +# let y_value = 0; +# let z = 0; +Point3d { x: x, y: y_value, z: z }; +Point3d { x, y: y_value, z }; +``` diff --git a/src/expressions/tuple-expr.md b/src/expressions/tuple-expr.md new file mode 100644 index 0000000000000..5519861428842 --- /dev/null +++ b/src/expressions/tuple-expr.md @@ -0,0 +1,38 @@ +# Tuple and tuple indexing expressions + +## Tuple expressions + +Tuples are written by enclosing zero or more comma-separated expressions in +parentheses. They are used to create [tuple-typed](types.html#tuple-types) +values. + +```rust +(0.0, 4.5); +("a", 4usize, true); +(); +``` + +You can disambiguate a single-element tuple from a value in parentheses with a +comma: + +```rust +(0,); // single-element tuple +(0); // zero in parentheses +``` + +## Tuple indexing expressions + +[Tuples](types.html#tuple-types) and [struct tuples](items/structs.html) can be +indexed using the number corresponding to the position of the field. The index +must be written as a [decimal literal](tokens.html#integer-literals) with no +underscores or suffix. Tuple indexing expressions also differ from field +expressions in that they can unambiguously be called as a function. In all +other aspects they have the same behavior. + +```rust +# struct Point(f32, f32); +let pair = (1, 2); +assert_eq!(pair.1, 2); +let unit_x = Point(1.0, 0.0); +assert_eq!(unit_x.0, 1.0); +``` diff --git a/src/interior-mutability.md b/src/interior-mutability.md index e7543ac5a273e..84a34475f7116 100644 --- a/src/interior-mutability.md +++ b/src/interior-mutability.md @@ -20,7 +20,7 @@ borrow checks to ensure the usual rules around multiple references. The accessed with atomic operations, allowing the value to be shared and mutated across threads. -[shared reference]: types.hmtl#shared-references +[shared reference]: types.html#shared-references [ub]: behavior-considered-undefined.html [`std::mem::transmute`]: ../std/mem/fn.transmute.html [`std::cell::UnsafeCell`]: ../std/cell/struct.UnsafeCell.html diff --git a/src/items.md b/src/items.md index 4decc358f1928..75da8be93be1b 100644 --- a/src/items.md +++ b/src/items.md @@ -5,27 +5,27 @@ nested set of [modules]. Every crate has a single "outermost" anonymous module; all further items within the crate have [paths] within the module tree of the crate. -[modules]: #modules +[modules]: items/modules.html [paths]: paths.html Items are entirely determined at compile-time, generally remain fixed during execution, and may reside in read-only memory. -There are several kinds of item: - -* [modules](#modules) -* [`extern crate` declarations](#extern-crate-declarations) -* [`use` declarations](#use-declarations) -* [function definitions](#functions) -* [type definitions](#type-aliases) -* [struct definitions](#structs) -* [enumeration definitions](#enumerations) -* [union definitions](#unions) -* [constant items](#constant-items) -* [static items](#static-items) -* [trait definitions](#traits) -* [implementations](#implementations) -* [`extern` blocks](#external-blocks) +There are several kinds of items: + +* [modules](items/modules.html) +* [`extern crate` declarations](items/extern-crates.html) +* [`use` declarations](items/use-declarations.html) +* [function definitions](items/functions.html) +* [type definitions](items/type-aliases.html) +* [struct definitions](items/structs.html) +* [enumeration definitions](items/enumerations.html) +* [union definitions](items/unions.html) +* [constant items](items/constant-items.html) +* [static items](items/static-items.html) +* [trait definitions](items/traits.html) +* [implementations](items/implementations.html) +* [`extern` blocks](items/external-blocks.html) Some items form an implicit scope for the declaration of sub-items. In other words, within a function or module, declarations of items can (in many cases) @@ -55,1291 +55,3 @@ of type abstraction: there are no higher-ranked (or "forall") types abstracted over other types, though higher-ranked types do exist for lifetimes. [path]: paths.html - -## Modules - -A module is a container for zero or more [items]. - -[items]: items.html - -A _module item_ is a module, surrounded in braces, named, and prefixed with the -keyword `mod`. A module item introduces a new, named module into the tree of -modules making up a crate. Modules can nest arbitrarily. - -An example of a module: - -```rust -mod math { - type Complex = (f64, f64); - fn sin(f: f64) -> f64 { - /* ... */ -# panic!(); - } - fn cos(f: f64) -> f64 { - /* ... */ -# panic!(); - } - fn tan(f: f64) -> f64 { - /* ... */ -# panic!(); - } -} -``` - -Modules and types share the same namespace. Declaring a named type with the -same name as a module in scope is forbidden: that is, a type definition, trait, -struct, enumeration, union, type parameter or crate can't shadow the name of a -module in scope, or vice versa. Items brought into scope with `use` also have -this restriction. - -A module without a body is loaded from an external file, by default with the -same name as the module, plus the `.rs` extension. When a nested submodule is -loaded from an external file, it is loaded from a subdirectory path that -mirrors the module hierarchy. - -```rust,ignore -// Load the `vec` module from `vec.rs` -mod vec; - -mod thread { - // Load the `local_data` module from `thread/local_data.rs` - // or `thread/local_data/mod.rs`. - mod local_data; -} -``` - -The directories and files used for loading external file modules can be -influenced with the `path` attribute. - -```rust,ignore -#[path = "thread_files"] -mod thread { - // Load the `local_data` module from `thread_files/tls.rs` - #[path = "tls.rs"] - mod local_data; -} -``` - -### Extern crate declarations - -An _`extern crate` declaration_ specifies a dependency on an external crate. -The external crate is then bound into the declaring scope as the `ident` -provided in the `extern_crate_decl`. - -The external crate is resolved to a specific `soname` at compile time, and a -runtime linkage requirement to that `soname` is passed to the linker for -loading at runtime. The `soname` is resolved at compile time by scanning the -compiler's library path and matching the optional `crateid` provided against -the `crateid` attributes that were declared on the external crate when it was -compiled. If no `crateid` is provided, a default `name` attribute is assumed, -equal to the `ident` given in the `extern_crate_decl`. - -Three examples of `extern crate` declarations: - -```rust,ignore -extern crate pcre; - -extern crate std; // equivalent to: extern crate std as std; - -extern crate std as ruststd; // linking to 'std' under another name -``` - -When naming Rust crates, hyphens are disallowed. However, Cargo packages may -make use of them. In such case, when `Cargo.toml` doesn't specify a crate name, -Cargo will transparently replace `-` with `_` (Refer to [RFC 940] for more -details). - -Here is an example: - -```rust,ignore -// Importing the Cargo package hello-world -extern crate hello_world; // hyphen replaced with an underscore -``` - -[RFC 940]: https://github.com/rust-lang/rfcs/blob/master/text/0940-hyphens-considered-harmful.md - -### Use declarations - -A _use declaration_ creates one or more local name bindings synonymous with -some other [path]. Usually a `use` declaration is used to shorten the path -required to refer to a module item. These declarations may appear in [modules] -and [blocks], usually at the top. - -[path]: paths.html -[modules]: #modules -[blocks]: expressions.html#block-expressions - -> **Note**: Unlike in many languages, `use` declarations in Rust do *not* -> declare linkage dependency with external crates. Rather, [`extern crate` -> declarations](#extern-crate-declarations) declare linkage dependencies. - -Use declarations support a number of convenient shortcuts: - -* Simultaneously binding a list of paths differing only in their final element, - using the glob-like brace syntax `use a::b::{c,d,e,f};` -* Simultaneously binding a list of paths differing only in their final element - and their immediate parent module, using the `self` keyword, such as `use - a::b::{self, c, d};` -* Rebinding the target name as a new local name, using the syntax `use p::q::r - as x;`. This can also be used with the last two features: `use a::b::{self as - ab, c as abc}`. -* Binding all paths matching a given prefix, using the asterisk wildcard syntax - `use a::b::*;` - -An example of `use` declarations: - -```rust -use std::option::Option::{Some, None}; -use std::collections::hash_map::{self, HashMap}; - -fn foo(_: T){} -fn bar(map1: HashMap, map2: hash_map::HashMap){} - -fn main() { - // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64), - // std::option::Option::None]);' - foo(vec![Some(1.0f64), None]); - - // Both `hash_map` and `HashMap` are in scope. - let map1 = HashMap::new(); - let map2 = hash_map::HashMap::new(); - bar(map1, map2); -} -``` - -Like items, `use` declarations are private to the containing module, by -default. Also like items, a `use` declaration can be public, if qualified by -the `pub` keyword. Such a `use` declaration serves to _re-export_ a name. A -public `use` declaration can therefore _redirect_ some public name to a -different target definition: even a definition with a private canonical path, -inside a different module. If a sequence of such redirections form a cycle or -cannot be resolved unambiguously, they represent a compile-time error. - -An example of re-exporting: - -```rust -# fn main() { } -mod quux { - pub use quux::foo::{bar, baz}; - - pub mod foo { - pub fn bar() { } - pub fn baz() { } - } -} -``` - -In this example, the module `quux` re-exports two public names defined in -`foo`. - -Also note that the paths contained in `use` items are relative to the crate -root. So, in the previous example, the `use` refers to `quux::foo::{bar, baz}`, -and not simply to `foo::{bar, baz}`. This also means that top-level module -declarations should be at the crate root if direct usage of the declared -modules within `use` items is desired. It is also possible to use `self` and -`super` at the beginning of a `use` item to refer to the current and direct -parent modules respectively. All rules regarding accessing declared modules in -`use` declarations apply to both module declarations and `extern crate` -declarations. - -An example of what will and will not work for `use` items: - -```rust -# #![allow(unused_imports)] -use foo::baz::foobaz; // good: foo is at the root of the crate - -mod foo { - - mod example { - pub mod iter {} - } - - use foo::example::iter; // good: foo is at crate root -// use example::iter; // bad: example is not at the crate root - use self::baz::foobaz; // good: self refers to module 'foo' - use foo::bar::foobar; // good: foo is at crate root - - pub mod bar { - pub fn foobar() { } - } - - pub mod baz { - use super::bar::foobar; // good: super refers to module 'foo' - pub fn foobaz() { } - } -} - -fn main() {} -``` - -## Functions - -A _function_ consists of a [block], along with a name and a set of parameters. -Other than a name, all these are optional. Functions are declared with the -keyword `fn`. Functions may declare a set of *input* [*variables*][variables] -as parameters, through which the caller passes arguments into the function, and -the *output* [*type*][type] of the value the function will return to its caller -on completion. - -[block]: expressions.html#block-expressions -[variables]: variables.html -[type]: types.html - -When referred to, a _function_ yields a first-class *value* of the -corresponding zero-sized [*function item type*][function item type], which -when called evaluates to a direct call to the function. - -[function item type]: types.html#function-item-types - -For example, this is a simple function: -```rust -fn answer_to_life_the_universe_and_everything() -> i32 { - return 42; -} -``` - -As with `let` bindings, function arguments are irrefutable patterns, so any -pattern that is valid in a let binding is also valid as an argument: - -```rust -fn first((value, _): (i32, i32)) -> i32 { value } -``` - -The block of a function is conceptually wrapped in a block that binds the -argument patterns and then `return`s the value of the function's block. This -means that the tail expression of the block, if evaluated, ends up being -returned to the caller. As usual, an explicit return expression within -the body of the function will short-cut that implicit return, if reached. - -For example, the function above behaves as if it was written as: - -```rust,ignore -// argument_0 is the actual first argument passed from the caller -let (value, _) = argument_0; -return { - value -}; -``` - -### Generic functions - -A _generic function_ allows one or more _parameterized types_ to appear in its -signature. Each type parameter must be explicitly declared in an -angle-bracket-enclosed and comma-separated list, following the function name. - -```rust -// foo is generic over A and B - -fn foo(x: A, y: B) { -# } -``` - -Inside the function signature and body, the name of the type parameter can be -used as a type name. [Trait](#traits) bounds can be specified for type -parameters to allow methods with that trait to be called on values of that -type. This is specified using the `where` syntax: - -```rust -# use std::fmt::Debug; -fn foo(x: T) where T: Debug { -# } -``` - -When a generic function is referenced, its type is instantiated based on the -context of the reference. For example, calling the `foo` function here: - -```rust -use std::fmt::Debug; - -fn foo(x: &[T]) where T: Debug { - // details elided -} - -foo(&[1, 2]); -``` - -will instantiate type parameter `T` with `i32`. - -The type parameters can also be explicitly supplied in a trailing [path] -component after the function name. This might be necessary if there is not -sufficient context to determine the type parameters. For example, -`mem::size_of::() == 4`. - -[path]: paths.html - -### Diverging functions - -A special kind of function can be declared with a `!` character where the -output type would normally be. For example: - -```rust -fn my_err(s: &str) -> ! { - println!("{}", s); - panic!(); -} -``` - -We call such functions "diverging" because they never return a value to the -caller. Every control path in a diverging function must end with a `panic!()`, -a loop expression without an associated break expression, or a call to another -diverging function on every control path. The `!` annotation does *not* denote -a type. - -It might be necessary to declare a diverging function because as mentioned -previously, the typechecker checks that every control path in a function ends -with a [`return`] or diverging expression. So, if `my_err` were declared -without the `!` annotation, the following code would not typecheck: - -[`return`]: expressions.html#return-expressions - -```rust -# fn my_err(s: &str) -> ! { panic!() } - -fn f(i: i32) -> i32 { - if i == 42 { - return 42; - } - else { - my_err("Bad number!"); - } -} -``` - -This will not compile without the `!` annotation on `my_err`, since the `else` -branch of the conditional in `f` does not return an `i32`, as required by the -signature of `f`. Adding the `!` annotation to `my_err` informs the typechecker -that, should control ever enter `my_err`, no further type judgments about `f` -need to hold, since control will never resume in any context that relies on -those judgments. Thus the return type on `f` only needs to reflect the `if` -branch of the conditional. - -### Extern functions - -Extern functions are part of Rust's foreign function interface, providing the -opposite functionality to [external blocks](#external-blocks). Whereas external -blocks allow Rust code to call foreign code, extern functions with bodies -defined in Rust code _can be called by foreign code_. They are defined in the -same way as any other Rust function, except that they have the `extern` -modifier. - -```rust -// Declares an extern fn, the ABI defaults to "C" -extern fn new_i32() -> i32 { 0 } - -// Declares an extern fn with "stdcall" ABI -# #[cfg(target_arch = "x86_64")] -extern "stdcall" fn new_i32_stdcall() -> i32 { 0 } -``` - -Unlike normal functions, extern fns have type `extern "ABI" fn()`. This is the -same type as the functions declared in an extern block. - -```rust -# extern fn new_i32() -> i32 { 0 } -let fptr: extern "C" fn() -> i32 = new_i32; -``` - -## Type aliases - -A _type alias_ defines a new name for an existing [type]. Type aliases are -declared with the keyword `type`. Every value has a single, specific type, but -may implement several different traits, or be compatible with several different -type constraints. - -[type]: types.html - -For example, the following defines the type `Point` as a synonym for the type -`(u8, u8)`, the type of pairs of unsigned 8 bit integers: - -```rust -type Point = (u8, u8); -let p: Point = (41, 68); -``` - -A type alias to an enum type cannot be used to qualify the constructors: - -```rust -enum E { A } -type F = E; -let _: F = E::A; // OK -// let _: F = F::A; // Doesn't work -``` - -## Structs - -A _struct_ is a nominal [struct type] defined with the keyword `struct`. - -An example of a `struct` item and its use: - -```rust -struct Point {x: i32, y: i32} -let p = Point {x: 10, y: 11}; -let px: i32 = p.x; -``` - -A _tuple struct_ is a nominal [tuple type], also defined with the keyword -`struct`. For example: - -[struct type]: types.html#struct-types -[tuple type]: types.html#tuple-types - -```rust -struct Point(i32, i32); -let p = Point(10, 11); -let px: i32 = match p { Point(x, _) => x }; -``` - -A _unit-like struct_ is a struct without any fields, defined by leaving off the -list of fields entirely. Such a struct implicitly defines a constant of its -type with the same name. For example: - -```rust -struct Cookie; -let c = [Cookie, Cookie {}, Cookie, Cookie {}]; -``` - -is equivalent to - -```rust -struct Cookie {} -const Cookie: Cookie = Cookie {}; -let c = [Cookie, Cookie {}, Cookie, Cookie {}]; -``` - -The precise memory layout of a struct is not specified. One can specify a -particular layout using the [`repr` attribute]. - -[`repr` attribute]: attributes.html#ffi-attributes - -## Enumerations - -An _enumeration_ is a simultaneous definition of a nominal [enumerated type] as -well as a set of *constructors*, that can be used to create or pattern-match -values of the corresponding enumerated type. - -[enumerated type]: types.html#enumerated-types - -Enumerations are declared with the keyword `enum`. - -An example of an `enum` item and its use: - -```rust -enum Animal { - Dog, - Cat, -} - -let mut a: Animal = Animal::Dog; -a = Animal::Cat; -``` - -Enumeration constructors can have either named or unnamed fields: - -```rust -enum Animal { - Dog (String, f64), - Cat { name: String, weight: f64 }, -} - -let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2); -a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 }; -``` - -In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is simply -called an enum variant. Each enum instance has a _discriminant_ which is an -integer associated to it that is used to determine which variant it holds. - -### C-like Enumerations - -If there is no data attached to *any* of the variants of an enumeration it is -called a *c-like enumeration*. If a discriminant isn't specified, they start at -zero, and add one for each variant, in order. Each enum value is just its -discriminant which you can specify explicitly: - -```rust -enum Foo { - Bar, // 0 - Baz = 123, - Quux, // 124 -} -``` - -The right hand side of the specification is interpreted as an `isize` value, -but the compiler is allowed to use a smaller type in the actual memory layout. -The [`repr` attribute] can be added in order to change the type of the right -hand side and specify the memory layout. - -[`repr` attribute]: attributes.html#ffi-attributes - -You can also cast a c-like enum to get its discriminant: - -```rust -# enum Foo { Baz = 123 } -let x = Foo::Baz as u32; // x is now 123u32 -``` - -This only works as long as none of the variants have data attached. If it were -`Baz(i32)`, this is disallowed. - -## Unions - -A union declaration uses the same syntax as a struct declaration, except with -`union` in place of `struct`. - -```rust -#[repr(C)] -union MyUnion { - f1: u32, - f2: f32, -} -``` - -The key property of unions is that all fields of a union share common storage. -As a result writes to one field of a union can overwrite its other fields, and -size of a union is determined by the size of its largest field. - -A value of a union type can be created using the same syntax that is used for -struct types, except that it must specify exactly one field: - -```rust -# union MyUnion { f1: u32, f2: f32 } -# -let u = MyUnion { f1: 1 }; -``` - -The expression above creates a value of type `MyUnion` with active field `f1`. -Active field of a union can be accessed using the same syntax as struct fields: - -```rust,ignore -let f = u.f1; -``` - -Inactive fields can be accessed as well (using the same syntax) if they are -sufficiently layout compatible with the current value kept by the union. -Reading incompatible fields results in undefined behavior. However, the active -field is not generally known statically, so all reads of union fields have to -be placed in `unsafe` blocks. - -```rust -# union MyUnion { f1: u32, f2: f32 } -# let u = MyUnion { f1: 1 }; -# -unsafe { - let f = u.f1; -} -``` - -Writes to `Copy` union fields do not require reads for running destructors, so -these writes don't have to be placed in `unsafe` blocks - -```rust -# union MyUnion { f1: u32, f2: f32 } -# let mut u = MyUnion { f1: 1 }; -# -u.f1 = 2; -``` - -Commonly, code using unions will provide safe wrappers around unsafe union -field accesses. - -Another way to access union fields is to use pattern matching. Pattern matching -on union fields uses the same syntax as struct patterns, except that the -pattern must specify exactly one field. Since pattern matching accesses -potentially inactive fields it has to be placed in `unsafe` blocks as well. - -```rust -# union MyUnion { f1: u32, f2: f32 } -# -fn f(u: MyUnion) { - unsafe { - match u { - MyUnion { f1: 10 } => { println!("ten"); } - MyUnion { f2 } => { println!("{}", f2); } - } - } -} -``` - -Pattern matching may match a union as a field of a larger structure. In -particular, when using a Rust union to implement a C tagged union via FFI, this -allows matching on the tag and the corresponding field simultaneously: - -```rust -#[repr(u32)] -enum Tag { I, F } - -#[repr(C)] -union U { - i: i32, - f: f32, -} - -#[repr(C)] -struct Value { - tag: Tag, - u: U, -} - -fn is_zero(v: Value) -> bool { - unsafe { - match v { - Value { tag: I, u: U { i: 0 } } => true, - Value { tag: F, u: U { f: 0.0 } } => true, - _ => false, - } - } -} -``` - -Since union fields share common storage, gaining write access to one field of a -union can give write access to all its remaining fields. Borrow checking rules -have to be adjusted to account for this fact. As a result, if one field of a -union is borrowed, all its remaining fields are borrowed as well for the same -lifetime. - -```rust,ignore -// ERROR: cannot borrow `u` (via `u.f2`) as mutable more than once at a time -fn test() { - let mut u = MyUnion { f1: 1 }; - unsafe { - let b1 = &mut u.f1; - ---- first mutable borrow occurs here (via `u.f1`) - let b2 = &mut u.f2; - ^^^^ second mutable borrow occurs here (via `u.f2`) - *b1 = 5; - } - - first borrow ends here - assert_eq!(unsafe { u.f1 }, 5); -} -``` - -As you could see, in many aspects (except for layouts, safety and ownership) -unions behave exactly like structs, largely as a consequence of inheriting -their syntactic shape from structs. This is also true for many unmentioned -aspects of Rust language (such as privacy, name resolution, type inference, -generics, trait implementations, inherent implementations, coherence, pattern -checking, etc etc etc). - -More detailed specification for unions, including unstable bits, can be found -in [RFC 1897 "Unions v1.2"](https://github.com/rust-lang/rfcs/pull/1897). - -## Constant items - -A *constant item* is a named _[constant value]_ which is not associated with a -specific memory location in the program. Constants are essentially inlined -wherever they are used, meaning that they are copied directly into the relevant -context when used. References to the same constant are not necessarily -guaranteed to refer to the same memory address. - -[constant value]: expressions.html#constant-expressions - -Constant values must not have destructors, and otherwise permit most forms of -data. Constants may refer to the address of other constants, in which case the -address will have elided lifetimes where applicable, otherwise – in most cases -– defaulting to the `static` lifetime. (See below on [static lifetime -elision].) The compiler is, however, still at liberty to translate the constant -many times, so the address referred to may not be stable. - -[static lifetime elision]: #static-lifetime-elision - -Constants must be explicitly typed. The type may be any type that doesn't -implement [`Drop`] and has a `'static` lifetime: any references it contains -must have `'static` lifetimes. - -[`Drop`]: the-drop-trait.html - -```rust -const BIT1: u32 = 1 << 0; -const BIT2: u32 = 1 << 1; - -const BITS: [u32; 2] = [BIT1, BIT2]; -const STRING: &'static str = "bitstring"; - -struct BitsNStrings<'a> { - mybits: [u32; 2], - mystring: &'a str, -} - -const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings { - mybits: BITS, - mystring: STRING, -}; -``` - -## Static items - -A *static item* is similar to a *constant*, except that it represents a precise -memory location in the program. A static is never "inlined" at the usage site, -and all references to it refer to the same memory location. Static items have -the `static` lifetime, which outlives all other lifetimes in a Rust program. -Static items may be placed in read-only memory if they do not contain any -interior mutability. - -Statics may contain interior mutability through the `UnsafeCell` language item. -All access to a static is safe, but there are a number of restrictions on -statics: - -* Statics may not contain any destructors. -* The types of static values must ascribe to `Sync` to allow thread-safe - access. -* Statics may not refer to other statics by value, only by reference. -* Constants cannot refer to statics. - -Constants should in general be preferred over statics, unless large amounts of -data are being stored, or single-address and mutability properties are -required. - -### Mutable statics - -If a static item is declared with the `mut` keyword, then it is allowed to be -modified by the program. One of Rust's goals is to make concurrency bugs hard -to run into, and this is obviously a very large source of race conditions or -other bugs. For this reason, an `unsafe` block is required when either reading -or writing a mutable static variable. Care should be taken to ensure that -modifications to a mutable static are safe with respect to other threads -running in the same process. - -Mutable statics are still very useful, however. They can be used with C -libraries and can also be bound from C libraries (in an `extern` block). - -```rust -# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 } - -static mut LEVELS: u32 = 0; - -// This violates the idea of no shared state, and this doesn't internally -// protect against races, so this function is `unsafe` -unsafe fn bump_levels_unsafe1() -> u32 { - let ret = LEVELS; - LEVELS += 1; - return ret; -} - -// Assuming that we have an atomic_add function which returns the old value, -// this function is "safe" but the meaning of the return value may not be what -// callers expect, so it's still marked as `unsafe` -unsafe fn bump_levels_unsafe2() -> u32 { - return atomic_add(&mut LEVELS, 1); -} -``` - -Mutable statics have the same restrictions as normal statics, except that the -type of the value is not required to ascribe to `Sync`. - -#### `'static` lifetime elision - -Both constant and static declarations of reference types have *implicit* -`'static` lifetimes unless an explicit lifetime is specified. As such, the -constant declarations involving `'static` above may be written without the -lifetimes. Returning to our previous example: - -```rust -const BIT1: u32 = 1 << 0; -const BIT2: u32 = 1 << 1; - -const BITS: [u32; 2] = [BIT1, BIT2]; -const STRING: &str = "bitstring"; - -struct BitsNStrings<'a> { - mybits: [u32; 2], - mystring: &'a str, -} - -const BITS_N_STRINGS: BitsNStrings = BitsNStrings { - mybits: BITS, - mystring: STRING, -}; -``` - -Note that if the `static` or `const` items include function or closure -references, which themselves include references, the compiler will first try -the standard elision rules ([see discussion in the nomicon][elision-nomicon]). -If it is unable to resolve the lifetimes by its usual rules, it will default to -using the `'static` lifetime. By way of example: - -[elision-nomicon]: ../nomicon/lifetime-elision.html - -```rust,ignore -// Resolved as `fn<'a>(&'a str) -> &'a str`. -const RESOLVED_SINGLE: fn(&str) -> &str = .. - -// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`. -const RESOLVED_MULTIPLE: Fn(&Foo, &Bar, &Baz) -> usize = .. - -// There is insufficient information to bound the return reference lifetime -// relative to the argument lifetimes, so the signature is resolved as -// `Fn(&'static Foo, &'static Bar) -> &'static Baz`. -const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = .. -``` - -## Traits - -A _trait_ describes an abstract interface that types can implement. This -interface consists of associated items, which come in three varieties: - -- [functions](#associated-functions-and-methods) -- [types](#associated-types) -- [constants](#associated-constants) - -All traits define an implicit type parameter `Self` that refers to "the type -that is implementing this interface". Traits may also contain additional type -parameters. These type parameters (including `Self`) may be constrained by -other traits and so forth as usual. - -Traits are implemented for specific types through separate [implementations]. - -### Associated functions and methods - -Associated functions whose first parameter is named `self` are called methods -and may be invoked using `.` notation (e.g., `x.foo()`) as well as the usual -function call notation (`foo(x)`). - -Consider the following trait: - -```rust -# type Surface = i32; -# type BoundingBox = i32; -trait Shape { - fn draw(&self, Surface); - fn bounding_box(&self) -> BoundingBox; -} -``` - -This defines a trait with two methods. All values that have [implementations] -of this trait in scope can have their `draw` and `bounding_box` methods called, -using `value.bounding_box()` [syntax]. Note that `&self` is short for `self: -&Self`, and similarly, `self` is short for `self: Self` and `&mut self` is -short for `self: &mut Self`. - -[trait object]: types.html#trait-objects -[implementations]: #implementations -[syntax]: expressions.html#method-call-expressions - -Traits can include default implementations of methods, as in: - -```rust -trait Foo { - fn bar(&self); - fn baz(&self) { println!("We called baz."); } -} -``` - -Here the `baz` method has a default implementation, so types that implement -`Foo` need only implement `bar`. It is also possible for implementing types to -override a method that has a default implementation. - -Type parameters can be specified for a trait to make it generic. These appear -after the trait name, using the same syntax used in [generic -functions](#generic-functions). - -```rust -trait Seq { - fn len(&self) -> u32; - fn elt_at(&self, n: u32) -> T; - fn iter(&self, F) where F: Fn(T); -} -``` - -Associated functions may lack a `self` argument, sometimes called 'static -methods'. This means that they can only be called with function call syntax -(`f(x)`) and not method call syntax (`obj.f()`). The way to refer to the name -of a static method is to qualify it with the trait name or type name, treating -the trait name like a module. For example: - -```rust -trait Num { - fn from_i32(n: i32) -> Self; -} -impl Num for f64 { - fn from_i32(n: i32) -> f64 { n as f64 } -} -let x: f64 = Num::from_i32(42); -let x: f64 = f64::from_i32(42); -``` - - -### Associated Types - -It is also possible to define associated types for a trait. Consider the -following example of a `Container` trait. Notice how the type is available for -use in the method signatures: - -```rust -trait Container { - type E; - fn empty() -> Self; - fn insert(&mut self, Self::E); -} -``` - -In order for a type to implement this trait, it must not only provide -implementations for every method, but it must specify the type `E`. Here's an -implementation of `Container` for the standard library type `Vec`: - -```rust -# trait Container { -# type E; -# fn empty() -> Self; -# fn insert(&mut self, Self::E); -# } -impl Container for Vec { - type E = T; - fn empty() -> Vec { Vec::new() } - fn insert(&mut self, x: T) { self.push(x); } -} -``` - -### Associated Constants - -A trait can define constants like this: - -```rust -trait Foo { - const ID: i32; -} - -impl Foo for i32 { - const ID: i32 = 1; -} - -fn main() { - assert_eq!(1, i32::ID); -} -``` - -Any implementor of `Foo` will have to define `ID`. Without the definition: - -```rust,compile_fail,E0046 -trait Foo { - const ID: i32; -} - -impl Foo for i32 { -} -``` - -gives - -```text -error: not all trait items implemented, missing: `ID` [E0046] - impl Foo for i32 { - } -``` - -A default value can be implemented as well: - -```rust -trait Foo { - const ID: i32 = 1; -} - -impl Foo for i32 { -} - -impl Foo for i64 { - const ID: i32 = 5; -} - -fn main() { - assert_eq!(1, i32::ID); - assert_eq!(5, i64::ID); -} -``` - -As you can see, when implementing `Foo`, you can leave it unimplemented, as -with `i32`. It will then use the default value. But, as in `i64`, we can also -add our own definition. - -Associated constants don’t have to be associated with a trait. An `impl` block -for a `struct` or an `enum` works fine too: - -```rust -struct Foo; - -impl Foo { - const FOO: u32 = 3; -} -``` - -### Trait bounds - -Generic functions may use traits as _bounds_ on their type parameters. This -will have three effects: - -- Only types that have the trait may instantiate the parameter. -- Within the generic function, the methods of the trait can be called on values - that have the parameter's type. Associated types can be used in the - function's signature, and associated constants can be used in expressions - within the function body. -- Generic functions and types with the same or weaker bounds can use the - generic type in the function body or signature. - -For example: - -```rust -# type Surface = i32; -# trait Shape { fn draw(&self, Surface); } -struct Figure(S, S); -fn draw_twice(surface: Surface, sh: T) { - sh.draw(surface); - sh.draw(surface); -} -fn draw_figure(surface: Surface, Figure(sh1, sh2): Figure) { - sh1.draw(surface); - draw_twice(surface, sh2); // Can call this since U: Shape -} -``` - -### Trait objects - -Traits also define a [trait object] with the same name as the trait. Values of -this type are created by coercing from a pointer of some specific type to a -pointer of trait type. For example, `&T` could be coerced to `&Shape` if `T: -Shape` holds (and similarly for `Box`). This coercion can either be implicit -or [explicit]. Here is an example of an explicit coercion: - -[trait object]: types.html#trait-objects -[explicit]: expressions.html#type-cast-expressions - -```rust -trait Shape { } -impl Shape for i32 { } -let mycircle = 0i32; -let myshape: Box = Box::new(mycircle) as Box; -``` - -The resulting value is a box containing the value that was cast, along with -information that identifies the methods of the implementation that was used. -Values with a trait type can have [methods called] on them, for any method in -the trait, and can be used to instantiate type parameters that are bounded by -the trait. - -[methods called]: expressions.html#method-call-expressions - -### Supertraits - - -Trait bounds on `Self` are considered "supertraits". These are required to be -acyclic. Supertraits are somewhat different from other constraints in that -they affect what methods are available in the vtable when the trait is used as -a [trait object]. Consider the following example: - -```rust -trait Shape { fn area(&self) -> f64; } -trait Circle : Shape { fn radius(&self) -> f64; } -``` - -The syntax `Circle : Shape` means that types that implement `Circle` must also -have an implementation for `Shape`. Multiple supertraits are separated by `+`, -`trait Circle : Shape + PartialEq { }`. In an implementation of `Circle` for a -given type `T`, methods can refer to `Shape` methods, since the typechecker -checks that any type with an implementation of `Circle` also has an -implementation of `Shape`: - -```rust -struct Foo; - -trait Shape { fn area(&self) -> f64; } -trait Circle : Shape { fn radius(&self) -> f64; } -impl Shape for Foo { - fn area(&self) -> f64 { - 0.0 - } -} -impl Circle for Foo { - fn radius(&self) -> f64 { - println!("calling area: {}", self.area()); - - 0.0 - } -} - -let c = Foo; -c.radius(); -``` - -In type-parameterized functions, methods of the supertrait may be called on -values of subtrait-bound type parameters. Referring to the previous example of -`trait Circle : Shape`: - -```rust -# trait Shape { fn area(&self) -> f64; } -# trait Circle : Shape { fn radius(&self) -> f64; } -fn radius_times_area(c: T) -> f64 { - // `c` is both a Circle and a Shape - c.radius() * c.area() -} -``` - -Likewise, supertrait methods may also be called on trait objects. - -```rust -# trait Shape { fn area(&self) -> f64; } -# trait Circle : Shape { fn radius(&self) -> f64; } -# impl Shape for i32 { fn area(&self) -> f64 { 0.0 } } -# impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } } -# let mycircle = 0i32; -let mycircle = Box::new(mycircle) as Box; -let nonsense = mycircle.radius() * mycircle.area(); -``` - -## Implementations - -An _implementation_ is an item that can implement a [trait](#traits) for a -specific type. - -Implementations are defined with the keyword `impl`. - -```rust -# #[derive(Copy, Clone)] -# struct Point {x: f64, y: f64}; -# type Surface = i32; -# struct BoundingBox {x: f64, y: f64, width: f64, height: f64}; -# trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; } -# fn do_draw_circle(s: Surface, c: Circle) { } -struct Circle { - radius: f64, - center: Point, -} - -impl Copy for Circle {} - -impl Clone for Circle { - fn clone(&self) -> Circle { *self } -} - -impl Shape for Circle { - fn draw(&self, s: Surface) { do_draw_circle(s, *self); } - fn bounding_box(&self) -> BoundingBox { - let r = self.radius; - BoundingBox { - x: self.center.x - r, - y: self.center.y - r, - width: 2.0 * r, - height: 2.0 * r, - } - } -} -``` - -It is possible to define an implementation without referring to a trait. The -methods in such an implementation can only be used as direct calls on the -values of the type that the implementation targets. In such an implementation, -the trait type and `for` after `impl` are omitted. Such implementations are -limited to nominal types (enums, structs, unions, trait objects), and the -implementation must appear in the same crate as the `Self` type: - -```rust -struct Point {x: i32, y: i32} - -impl Point { - fn log(&self) { - println!("Point is at ({}, {})", self.x, self.y); - } -} - -let my_point = Point {x: 10, y:11}; -my_point.log(); -``` - -When a trait _is_ specified in an `impl`, all methods declared as part of the -trait must be implemented, with matching types and type parameter counts. - -An implementation can take type and lifetime parameters, which can be used in -the rest of the implementation. Type parameters declared for an implementation -must be used at least once in either the trait or the type of an -implementation. Implementation parameters are written after the `impl` keyword. - -```rust -# trait Seq { fn dummy(&self, _: T) { } } -impl Seq for Vec { - /* ... */ -} -impl Seq for u32 { - /* Treat the integer as a sequence of bits */ -} -``` - -## External blocks - -External blocks form the basis for Rust's foreign function interface. -Declarations in an external block describe symbols in external, non-Rust -libraries. - -Functions within external blocks are declared in the same way as other Rust -functions, with the exception that they may not have a body and are instead -terminated by a semicolon. - -Functions within external blocks may be called by Rust code, just like -functions defined in Rust. The Rust compiler automatically translates between -the Rust ABI and the foreign ABI. - -Functions within external blocks may be variadic by specifying `...` after one -or more named arguments in the argument list: - -```rust,ignore -extern { - fn foo(x: i32, ...); -} -``` - -A number of [attributes] control the behavior of external blocks. - -[attributes]: attributes.html#ffi-attributes - -By default external blocks assume that the library they are calling uses the -standard C ABI on the specific platform. Other ABIs may be specified using an -`abi` string, as shown here: - -```rust,ignore -// Interface to the Windows API -extern "stdcall" { } -``` - -There are three ABI strings which are cross-platform, and which all compilers -are guaranteed to support: - -* `extern "Rust"` -- The default ABI when you write a normal `fn foo()` in any - Rust code. -* `extern "C"` -- This is the same as `extern fn foo()`; whatever the default - your C compiler supports. -* `extern "system"` -- Usually the same as `extern "C"`, except on Win32, in - which case it's `"stdcall"`, or what you should use to link to the Windows - API itself - -There are also some platform-specific ABI strings: - -* `extern "cdecl"` -- The default for x86\_32 C code. -* `extern "stdcall"` -- The default for the Win32 API on x86\_32. -* `extern "win64"` -- The default for C code on x86\_64 Windows. -* `extern "sysv64"` -- The default for C code on non-Windows x86\_64. -* `extern "aapcs"` -- The default for ARM. -* `extern "fastcall"` -- The `fastcall` ABI -- corresponds to MSVC's - `__fastcall` and GCC and clang's `__attribute__((fastcall))` -* `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's - `__vectorcall` and clang's `__attribute__((vectorcall))` - -Finally, there are some rustc-specific ABI strings: - -* `extern "rust-intrinsic"` -- The ABI of rustc intrinsics. -* `extern "rust-call"` -- The ABI of the Fn::call trait functions. -* `extern "platform-intrinsic"` -- Specific platform intrinsics -- like, for - example, `sqrt` -- have this ABI. You should never have to deal with it. - -The `link` attribute allows the name of the library to be specified. When -specified the compiler will attempt to link against the native library of the -specified name. - -```rust,ignore -#[link(name = "crypto")] -extern { } -``` - -The type of a function declared in an extern block is `extern "abi" fn(A1, ..., -An) -> R`, where `A1...An` are the declared types of its arguments and `R` is -the declared return type. - -It is valid to add the `link` attribute on an empty extern block. You can use -this to satisfy the linking requirements of extern blocks elsewhere in your -code (including upstream crates) instead of adding the attribute to each extern -block. diff --git a/src/items/constant-items.md b/src/items/constant-items.md new file mode 100644 index 0000000000000..182c7e0fb5dfa --- /dev/null +++ b/src/items/constant-items.md @@ -0,0 +1,42 @@ +# Constant items + +A *constant item* is a named _[constant value]_ which is not associated with a +specific memory location in the program. Constants are essentially inlined +wherever they are used, meaning that they are copied directly into the relevant +context when used. References to the same constant are not necessarily +guaranteed to refer to the same memory address. + +[constant value]: expressions.html#constant-expressions + +Constant values must not have destructors, and otherwise permit most forms of +data. Constants may refer to the address of other constants, in which case the +address will have elided lifetimes where applicable, otherwise – in most cases +– defaulting to the `static` lifetime. (See below on [static lifetime +elision].) The compiler is, however, still at liberty to translate the constant +many times, so the address referred to may not be stable. + +[static lifetime elision]: items/static-items.html#static-lifetime-elision + +Constants must be explicitly typed. The type may be any type that doesn't +implement [`Drop`] and has a `'static` lifetime: any references it contains +must have `'static` lifetimes. + +[`Drop`]: the-drop-trait.html + +```rust +const BIT1: u32 = 1 << 0; +const BIT2: u32 = 1 << 1; + +const BITS: [u32; 2] = [BIT1, BIT2]; +const STRING: &'static str = "bitstring"; + +struct BitsNStrings<'a> { + mybits: [u32; 2], + mystring: &'a str, +} + +const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings { + mybits: BITS, + mystring: STRING, +}; +``` diff --git a/src/items/enumerations.md b/src/items/enumerations.md new file mode 100644 index 0000000000000..81b92ec96c2a7 --- /dev/null +++ b/src/items/enumerations.md @@ -0,0 +1,69 @@ +# Enumerations + +An _enumeration_ is a simultaneous definition of a nominal [enumerated type] as +well as a set of *constructors*, that can be used to create or pattern-match +values of the corresponding enumerated type. + +[enumerated type]: types.html#enumerated-types + +Enumerations are declared with the keyword `enum`. + +An example of an `enum` item and its use: + +```rust +enum Animal { + Dog, + Cat, +} + +let mut a: Animal = Animal::Dog; +a = Animal::Cat; +``` + +Enumeration constructors can have either named or unnamed fields: + +```rust +enum Animal { + Dog (String, f64), + Cat { name: String, weight: f64 }, +} + +let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2); +a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 }; +``` + +In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is simply +called an enum variant. Each enum instance has a _discriminant_ which is an +integer associated to it that is used to determine which variant it holds. + +## C-like Enumerations + +If there is no data attached to *any* of the variants of an enumeration it is +called a *c-like enumeration*. If a discriminant isn't specified, they start at +zero, and add one for each variant, in order. Each enum value is just its +discriminant which you can specify explicitly: + +```rust +enum Foo { + Bar, // 0 + Baz = 123, + Quux, // 124 +} +``` + +The right hand side of the specification is interpreted as an `isize` value, +but the compiler is allowed to use a smaller type in the actual memory layout. +The [`repr` attribute] can be added in order to change the type of the right +hand side and specify the memory layout. + +[`repr` attribute]: attributes.html#ffi-attributes + +You can also cast a c-like enum to get its discriminant: + +```rust +# enum Foo { Baz = 123 } +let x = Foo::Baz as u32; // x is now 123u32 +``` + +This only works as long as none of the variants have data attached. If it were +`Baz(i32)`, this is disallowed. diff --git a/src/items/extern-crates.md b/src/items/extern-crates.md new file mode 100644 index 0000000000000..e12e37495c017 --- /dev/null +++ b/src/items/extern-crates.md @@ -0,0 +1,37 @@ +# Extern crate declarations + +An _`extern crate` declaration_ specifies a dependency on an external crate. +The external crate is then bound into the declaring scope as the `ident` +provided in the `extern_crate_decl`. + +The external crate is resolved to a specific `soname` at compile time, and a +runtime linkage requirement to that `soname` is passed to the linker for +loading at runtime. The `soname` is resolved at compile time by scanning the +compiler's library path and matching the optional `crateid` provided against +the `crateid` attributes that were declared on the external crate when it was +compiled. If no `crateid` is provided, a default `name` attribute is assumed, +equal to the `ident` given in the `extern_crate_decl`. + +Three examples of `extern crate` declarations: + +```rust,ignore +extern crate pcre; + +extern crate std; // equivalent to: extern crate std as std; + +extern crate std as ruststd; // linking to 'std' under another name +``` + +When naming Rust crates, hyphens are disallowed. However, Cargo packages may +make use of them. In such case, when `Cargo.toml` doesn't specify a crate name, +Cargo will transparently replace `-` with `_` (Refer to [RFC 940] for more +details). + +Here is an example: + +```rust,ignore +// Importing the Cargo package hello-world +extern crate hello_world; // hyphen replaced with an underscore +``` + +[RFC 940]: https://github.com/rust-lang/rfcs/blob/master/text/0940-hyphens-considered-harmful.md diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md new file mode 100644 index 0000000000000..edbe3be89f5a0 --- /dev/null +++ b/src/items/external-blocks.md @@ -0,0 +1,83 @@ +# External blocks + +External blocks form the basis for Rust's foreign function interface. +Declarations in an external block describe symbols in external, non-Rust +libraries. + +Functions within external blocks are declared in the same way as other Rust +functions, with the exception that they may not have a body and are instead +terminated by a semicolon. + +Functions within external blocks may be called by Rust code, just like +functions defined in Rust. The Rust compiler automatically translates between +the Rust ABI and the foreign ABI. + +Functions within external blocks may be variadic by specifying `...` after one +or more named arguments in the argument list: + +```rust,ignore +extern { + fn foo(x: i32, ...); +} +``` + +A number of [attributes] control the behavior of external blocks. + +[attributes]: attributes.html#ffi-attributes + +By default external blocks assume that the library they are calling uses the +standard C ABI on the specific platform. Other ABIs may be specified using an +`abi` string, as shown here: + +```rust,ignore +// Interface to the Windows API +extern "stdcall" { } +``` + +There are three ABI strings which are cross-platform, and which all compilers +are guaranteed to support: + +* `extern "Rust"` -- The default ABI when you write a normal `fn foo()` in any + Rust code. +* `extern "C"` -- This is the same as `extern fn foo()`; whatever the default + your C compiler supports. +* `extern "system"` -- Usually the same as `extern "C"`, except on Win32, in + which case it's `"stdcall"`, or what you should use to link to the Windows + API itself + +There are also some platform-specific ABI strings: + +* `extern "cdecl"` -- The default for x86\_32 C code. +* `extern "stdcall"` -- The default for the Win32 API on x86\_32. +* `extern "win64"` -- The default for C code on x86\_64 Windows. +* `extern "sysv64"` -- The default for C code on non-Windows x86\_64. +* `extern "aapcs"` -- The default for ARM. +* `extern "fastcall"` -- The `fastcall` ABI -- corresponds to MSVC's + `__fastcall` and GCC and clang's `__attribute__((fastcall))` +* `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's + `__vectorcall` and clang's `__attribute__((vectorcall))` + +Finally, there are some rustc-specific ABI strings: + +* `extern "rust-intrinsic"` -- The ABI of rustc intrinsics. +* `extern "rust-call"` -- The ABI of the Fn::call trait functions. +* `extern "platform-intrinsic"` -- Specific platform intrinsics -- like, for + example, `sqrt` -- have this ABI. You should never have to deal with it. + +The `link` attribute allows the name of the library to be specified. When +specified the compiler will attempt to link against the native library of the +specified name. + +```rust,ignore +#[link(name = "crypto")] +extern { } +``` + +The type of a function declared in an extern block is `extern "abi" fn(A1, ..., +An) -> R`, where `A1...An` are the declared types of its arguments and `R` is +the declared return type. + +It is valid to add the `link` attribute on an empty extern block. You can use +this to satisfy the linking requirements of extern blocks elsewhere in your +code (including upstream crates) instead of adding the attribute to each extern +block. diff --git a/src/items/functions.md b/src/items/functions.md new file mode 100644 index 0000000000000..7572ba331c7df --- /dev/null +++ b/src/items/functions.md @@ -0,0 +1,167 @@ +# Functions + +A _function_ consists of a [block], along with a name and a set of parameters. +Other than a name, all these are optional. Functions are declared with the +keyword `fn`. Functions may declare a set of *input* [*variables*][variables] +as parameters, through which the caller passes arguments into the function, and +the *output* [*type*][type] of the value the function will return to its caller +on completion. + +[block]: expressions/block-expr.html +[variables]: variables.html +[type]: types.html + +When referred to, a _function_ yields a first-class *value* of the +corresponding zero-sized [*function item type*][function item type], which +when called evaluates to a direct call to the function. + +[function item type]: types.html#function-item-types + +For example, this is a simple function: +```rust +fn answer_to_life_the_universe_and_everything() -> i32 { + return 42; +} +``` + +As with `let` bindings, function arguments are irrefutable patterns, so any +pattern that is valid in a let binding is also valid as an argument: + +```rust +fn first((value, _): (i32, i32)) -> i32 { value } +``` + +The block of a function is conceptually wrapped in a block that binds the +argument patterns and then `return`s the value of the function's block. This +means that the tail expression of the block, if evaluated, ends up being +returned to the caller. As usual, an explicit return expression within +the body of the function will short-cut that implicit return, if reached. + +For example, the function above behaves as if it was written as: + +```rust,ignore +// argument_0 is the actual first argument passed from the caller +let (value, _) = argument_0; +return { + value +}; +``` + +## Generic functions + +A _generic function_ allows one or more _parameterized types_ to appear in its +signature. Each type parameter must be explicitly declared in an +angle-bracket-enclosed and comma-separated list, following the function name. + +```rust +// foo is generic over A and B + +fn foo(x: A, y: B) { +# } +``` + +Inside the function signature and body, the name of the type parameter can be +used as a type name. [Trait](items/traits.html) bounds can be specified for type +parameters to allow methods with that trait to be called on values of that +type. This is specified using the `where` syntax: + +```rust +# use std::fmt::Debug; +fn foo(x: T) where T: Debug { +# } +``` + +When a generic function is referenced, its type is instantiated based on the +context of the reference. For example, calling the `foo` function here: + +```rust +use std::fmt::Debug; + +fn foo(x: &[T]) where T: Debug { + // details elided +} + +foo(&[1, 2]); +``` + +will instantiate type parameter `T` with `i32`. + +The type parameters can also be explicitly supplied in a trailing [path] +component after the function name. This might be necessary if there is not +sufficient context to determine the type parameters. For example, +`mem::size_of::() == 4`. + +[path]: paths.html + +## Diverging functions + +A special kind of function can be declared with a `!` character where the +output type would normally be. For example: + +```rust +fn my_err(s: &str) -> ! { + println!("{}", s); + panic!(); +} +``` + +We call such functions "diverging" because they never return a value to the +caller. Every control path in a diverging function must end with a `panic!()`, +a loop expression without an associated break expression, or a call to another +diverging function on every control path. The `!` annotation does *not* denote +a type. + +It might be necessary to declare a diverging function because as mentioned +previously, the typechecker checks that every control path in a function ends +with a [`return`] or diverging expression. So, if `my_err` were declared +without the `!` annotation, the following code would not typecheck: + +[`return`]: expressions/return-expr.html + +```rust +# fn my_err(s: &str) -> ! { panic!() } + +fn f(i: i32) -> i32 { + if i == 42 { + return 42; + } + else { + my_err("Bad number!"); + } +} +``` + +This will not compile without the `!` annotation on `my_err`, since the `else` +branch of the conditional in `f` does not return an `i32`, as required by the +signature of `f`. Adding the `!` annotation to `my_err` informs the typechecker +that, should control ever enter `my_err`, no further type judgments about `f` +need to hold, since control will never resume in any context that relies on +those judgments. Thus the return type on `f` only needs to reflect the `if` +branch of the conditional. + +## Extern functions + +Extern functions are part of Rust's foreign function interface, providing the +opposite functionality to [external blocks](items/external-blocks.html). Whereas external +blocks allow Rust code to call foreign code, extern functions with bodies +defined in Rust code _can be called by foreign code_. They are defined in the +same way as any other Rust function, except that they have the `extern` +modifier. + +```rust +// Declares an extern fn, the ABI defaults to "C" +extern fn new_i32() -> i32 { 0 } + +// Declares an extern fn with "stdcall" ABI +# #[cfg(target_arch = "x86_64")] +extern "stdcall" fn new_i32_stdcall() -> i32 { 0 } +``` + +Unlike normal functions, extern fns have type `extern "ABI" fn()`. This is the +same type as the functions declared in an extern block. + +```rust +# extern fn new_i32() -> i32 { 0 } +let fptr: extern "C" fn() -> i32 = new_i32; +``` + diff --git a/src/items/implementations.md b/src/items/implementations.md new file mode 100644 index 0000000000000..51330570c0263 --- /dev/null +++ b/src/items/implementations.md @@ -0,0 +1,76 @@ +# Implementations + +An _implementation_ is an item that can implement a [trait](items/traits.html) for a +specific type. + +Implementations are defined with the keyword `impl`. + +```rust +# #[derive(Copy, Clone)] +# struct Point {x: f64, y: f64}; +# type Surface = i32; +# struct BoundingBox {x: f64, y: f64, width: f64, height: f64}; +# trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; } +# fn do_draw_circle(s: Surface, c: Circle) { } +struct Circle { + radius: f64, + center: Point, +} + +impl Copy for Circle {} + +impl Clone for Circle { + fn clone(&self) -> Circle { *self } +} + +impl Shape for Circle { + fn draw(&self, s: Surface) { do_draw_circle(s, *self); } + fn bounding_box(&self) -> BoundingBox { + let r = self.radius; + BoundingBox { + x: self.center.x - r, + y: self.center.y - r, + width: 2.0 * r, + height: 2.0 * r, + } + } +} +``` + +It is possible to define an implementation without referring to a trait. The +methods in such an implementation can only be used as direct calls on the +values of the type that the implementation targets. In such an implementation, +the trait type and `for` after `impl` are omitted. Such implementations are +limited to nominal types (enums, structs, unions, trait objects), and the +implementation must appear in the same crate as the `Self` type: + +```rust +struct Point {x: i32, y: i32} + +impl Point { + fn log(&self) { + println!("Point is at ({}, {})", self.x, self.y); + } +} + +let my_point = Point {x: 10, y:11}; +my_point.log(); +``` + +When a trait _is_ specified in an `impl`, all methods declared as part of the +trait must be implemented, with matching types and type parameter counts. + +An implementation can take type and lifetime parameters, which can be used in +the rest of the implementation. Type parameters declared for an implementation +must be used at least once in either the trait or the type of an +implementation. Implementation parameters are written after the `impl` keyword. + +```rust +# trait Seq { fn dummy(&self, _: T) { } } +impl Seq for Vec { + /* ... */ +} +impl Seq for u32 { + /* Treat the integer as a sequence of bits */ +} +``` diff --git a/src/items/modules.md b/src/items/modules.md new file mode 100644 index 0000000000000..4ab8ea12874a4 --- /dev/null +++ b/src/items/modules.md @@ -0,0 +1,63 @@ +# Modules + +A module is a container for zero or more [items]. + +[items]: items.html + +A _module item_ is a module, surrounded in braces, named, and prefixed with the +keyword `mod`. A module item introduces a new, named module into the tree of +modules making up a crate. Modules can nest arbitrarily. + +An example of a module: + +```rust +mod math { + type Complex = (f64, f64); + fn sin(f: f64) -> f64 { + /* ... */ +# panic!(); + } + fn cos(f: f64) -> f64 { + /* ... */ +# panic!(); + } + fn tan(f: f64) -> f64 { + /* ... */ +# panic!(); + } +} +``` + +Modules and types share the same namespace. Declaring a named type with the +same name as a module in scope is forbidden: that is, a type definition, trait, +struct, enumeration, union, type parameter or crate can't shadow the name of a +module in scope, or vice versa. Items brought into scope with `use` also have +this restriction. + +A module without a body is loaded from an external file, by default with the +same name as the module, plus the `.rs` extension. When a nested submodule is +loaded from an external file, it is loaded from a subdirectory path that +mirrors the module hierarchy. + +```rust,ignore +// Load the `vec` module from `vec.rs` +mod vec; + +mod thread { + // Load the `local_data` module from `thread/local_data.rs` + // or `thread/local_data/mod.rs`. + mod local_data; +} +``` + +The directories and files used for loading external file modules can be +influenced with the `path` attribute. + +```rust,ignore +#[path = "thread_files"] +mod thread { + // Load the `local_data` module from `thread_files/tls.rs` + #[path = "tls.rs"] + mod local_data; +} +``` diff --git a/src/items/static-items.md b/src/items/static-items.md new file mode 100644 index 0000000000000..bac030477f5cf --- /dev/null +++ b/src/items/static-items.md @@ -0,0 +1,105 @@ +# Static items + +A *static item* is similar to a *constant*, except that it represents a precise +memory location in the program. A static is never "inlined" at the usage site, +and all references to it refer to the same memory location. Static items have +the `static` lifetime, which outlives all other lifetimes in a Rust program. +Static items may be placed in read-only memory if they do not contain any +interior mutability. + +Statics may contain interior mutability through the `UnsafeCell` language item. +All access to a static is safe, but there are a number of restrictions on +statics: + +* Statics may not contain any destructors. +* The types of static values must ascribe to `Sync` to allow thread-safe + access. +* Statics may not refer to other statics by value, only by reference. +* Constants cannot refer to statics. + +Constants should in general be preferred over statics, unless large amounts of +data are being stored, or single-address and mutability properties are +required. + +## Mutable statics + +If a static item is declared with the `mut` keyword, then it is allowed to be +modified by the program. One of Rust's goals is to make concurrency bugs hard +to run into, and this is obviously a very large source of race conditions or +other bugs. For this reason, an `unsafe` block is required when either reading +or writing a mutable static variable. Care should be taken to ensure that +modifications to a mutable static are safe with respect to other threads +running in the same process. + +Mutable statics are still very useful, however. They can be used with C +libraries and can also be bound from C libraries (in an `extern` block). + +```rust +# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 } + +static mut LEVELS: u32 = 0; + +// This violates the idea of no shared state, and this doesn't internally +// protect against races, so this function is `unsafe` +unsafe fn bump_levels_unsafe1() -> u32 { + let ret = LEVELS; + LEVELS += 1; + return ret; +} + +// Assuming that we have an atomic_add function which returns the old value, +// this function is "safe" but the meaning of the return value may not be what +// callers expect, so it's still marked as `unsafe` +unsafe fn bump_levels_unsafe2() -> u32 { + return atomic_add(&mut LEVELS, 1); +} +``` + +Mutable statics have the same restrictions as normal statics, except that the +type of the value is not required to ascribe to `Sync`. + +## `'static` lifetime elision + +Both constant and static declarations of reference types have *implicit* +`'static` lifetimes unless an explicit lifetime is specified. As such, the +constant declarations involving `'static` above may be written without the +lifetimes. Returning to our previous example: + +```rust +const BIT1: u32 = 1 << 0; +const BIT2: u32 = 1 << 1; + +const BITS: [u32; 2] = [BIT1, BIT2]; +const STRING: &str = "bitstring"; + +struct BitsNStrings<'a> { + mybits: [u32; 2], + mystring: &'a str, +} + +const BITS_N_STRINGS: BitsNStrings = BitsNStrings { + mybits: BITS, + mystring: STRING, +}; +``` + +Note that if the `static` or `const` items include function or closure +references, which themselves include references, the compiler will first try +the standard elision rules ([see discussion in the nomicon][elision-nomicon]). +If it is unable to resolve the lifetimes by its usual rules, it will default to +using the `'static` lifetime. By way of example: + +[elision-nomicon]: ../nomicon/lifetime-elision.html + +```rust,ignore +// Resolved as `fn<'a>(&'a str) -> &'a str`. +const RESOLVED_SINGLE: fn(&str) -> &str = .. + +// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`. +const RESOLVED_MULTIPLE: Fn(&Foo, &Bar, &Baz) -> usize = .. + +// There is insufficient information to bound the return reference lifetime +// relative to the argument lifetimes, so the signature is resolved as +// `Fn(&'static Foo, &'static Bar) -> &'static Baz`. +const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = .. +``` diff --git a/src/items/structs.md b/src/items/structs.md new file mode 100644 index 0000000000000..1a863411a832e --- /dev/null +++ b/src/items/structs.md @@ -0,0 +1,45 @@ +# Structs + +A _struct_ is a nominal [struct type] defined with the keyword `struct`. + +An example of a `struct` item and its use: + +```rust +struct Point {x: i32, y: i32} +let p = Point {x: 10, y: 11}; +let px: i32 = p.x; +``` + +A _tuple struct_ is a nominal [tuple type], also defined with the keyword +`struct`. For example: + +[struct type]: types.html#struct-types +[tuple type]: types.html#tuple-types + +```rust +struct Point(i32, i32); +let p = Point(10, 11); +let px: i32 = match p { Point(x, _) => x }; +``` + +A _unit-like struct_ is a struct without any fields, defined by leaving off the +list of fields entirely. Such a struct implicitly defines a constant of its +type with the same name. For example: + +```rust +struct Cookie; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; +``` + +is equivalent to + +```rust +struct Cookie {} +const Cookie: Cookie = Cookie {}; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; +``` + +The precise memory layout of a struct is not specified. One can specify a +particular layout using the [`repr` attribute]. + +[`repr` attribute]: attributes.html#ffi-attributes diff --git a/src/items/traits.md b/src/items/traits.md new file mode 100644 index 0000000000000..48194016749f5 --- /dev/null +++ b/src/items/traits.md @@ -0,0 +1,308 @@ +# Traits + +A _trait_ describes an abstract interface that types can implement. This +interface consists of associated items, which come in three varieties: + +- [functions](#associated-functions-and-methods) +- [types](#associated-types) +- [constants](#associated-constants) + +All traits define an implicit type parameter `Self` that refers to "the type +that is implementing this interface". Traits may also contain additional type +parameters. These type parameters (including `Self`) may be constrained by +other traits and so forth as usual. + +Traits are implemented for specific types through separate [implementations]. + +## Associated functions and methods + +Associated functions whose first parameter is named `self` are called methods +and may be invoked using `.` notation (e.g., `x.foo()`) as well as the usual +function call notation (`foo(x)`). + +Consider the following trait: + +```rust +# type Surface = i32; +# type BoundingBox = i32; +trait Shape { + fn draw(&self, Surface); + fn bounding_box(&self) -> BoundingBox; +} +``` + +This defines a trait with two methods. All values that have [implementations] +of this trait in scope can have their `draw` and `bounding_box` methods called, +using `value.bounding_box()` [syntax]. Note that `&self` is short for `self: +&Self`, and similarly, `self` is short for `self: Self` and `&mut self` is +short for `self: &mut Self`. + +[trait object]: types.html#trait-objects +[implementations]: items/implementations.html +[syntax]: expressions/method-call-expr.html + +Traits can include default implementations of methods, as in: + +```rust +trait Foo { + fn bar(&self); + fn baz(&self) { println!("We called baz."); } +} +``` + +Here the `baz` method has a default implementation, so types that implement +`Foo` need only implement `bar`. It is also possible for implementing types to +override a method that has a default implementation. + +Type parameters can be specified for a trait to make it generic. These appear +after the trait name, using the same syntax used in [generic +functions](items/functions.html#generic-functions). + +```rust +trait Seq { + fn len(&self) -> u32; + fn elt_at(&self, n: u32) -> T; + fn iter(&self, F) where F: Fn(T); +} +``` + +Associated functions may lack a `self` argument, sometimes called 'static +methods'. This means that they can only be called with function call syntax +(`f(x)`) and not method call syntax (`obj.f()`). The way to refer to the name +of a static method is to qualify it with the trait name or type name, treating +the trait name like a module. For example: + +```rust +trait Num { + fn from_i32(n: i32) -> Self; +} +impl Num for f64 { + fn from_i32(n: i32) -> f64 { n as f64 } +} +let x: f64 = Num::from_i32(42); +let x: f64 = f64::from_i32(42); +``` + +## Associated Types + +It is also possible to define associated types for a trait. Consider the +following example of a `Container` trait. Notice how the type is available for +use in the method signatures: + +```rust +trait Container { + type E; + fn empty() -> Self; + fn insert(&mut self, Self::E); +} +``` + +In order for a type to implement this trait, it must not only provide +implementations for every method, but it must specify the type `E`. Here's an +implementation of `Container` for the standard library type `Vec`: + +```rust +# trait Container { +# type E; +# fn empty() -> Self; +# fn insert(&mut self, Self::E); +# } +impl Container for Vec { + type E = T; + fn empty() -> Vec { Vec::new() } + fn insert(&mut self, x: T) { self.push(x); } +} +``` + +## Associated Constants + +A trait can define constants like this: + +```rust +trait Foo { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, i32::ID); +} +``` + +Any implementor of `Foo` will have to define `ID`. Without the definition: + +```rust,compile_fail,E0046 +trait Foo { + const ID: i32; +} + +impl Foo for i32 { +} +``` + +gives + +```text +error: not all trait items implemented, missing: `ID` [E0046] + impl Foo for i32 { + } +``` + +A default value can be implemented as well: + +```rust +trait Foo { + const ID: i32 = 1; +} + +impl Foo for i32 { +} + +impl Foo for i64 { + const ID: i32 = 5; +} + +fn main() { + assert_eq!(1, i32::ID); + assert_eq!(5, i64::ID); +} +``` + +As you can see, when implementing `Foo`, you can leave it unimplemented, as +with `i32`. It will then use the default value. But, as in `i64`, we can also +add our own definition. + +Associated constants don’t have to be associated with a trait. An `impl` block +for a `struct` or an `enum` works fine too: + +```rust +struct Foo; + +impl Foo { + const FOO: u32 = 3; +} +``` + +## Trait bounds + +Generic functions may use traits as _bounds_ on their type parameters. This +will have three effects: + +- Only types that have the trait may instantiate the parameter. +- Within the generic function, the methods of the trait can be called on values + that have the parameter's type. Associated types can be used in the + function's signature, and associated constants can be used in expressions + within the function body. +- Generic functions and types with the same or weaker bounds can use the + generic type in the function body or signature. + +For example: + +```rust +# type Surface = i32; +# trait Shape { fn draw(&self, Surface); } +struct Figure(S, S); +fn draw_twice(surface: Surface, sh: T) { + sh.draw(surface); + sh.draw(surface); +} +fn draw_figure(surface: Surface, Figure(sh1, sh2): Figure) { + sh1.draw(surface); + draw_twice(surface, sh2); // Can call this since U: Shape +} +``` + +## Trait objects + +Traits also define a [trait object] with the same name as the trait. Values of +this type are created by coercing from a pointer of some specific type to a +pointer of trait type. For example, `&T` could be coerced to `&Shape` if `T: +Shape` holds (and similarly for `Box`). This coercion can either be implicit +or [explicit]. Here is an example of an explicit coercion: + +[trait object]: types.html#trait-objects +[explicit]: expressions/operator-expr.html#type-cast-expressions + +```rust +trait Shape { } +impl Shape for i32 { } +let mycircle = 0i32; +let myshape: Box = Box::new(mycircle) as Box; +``` + +The resulting value is a box containing the value that was cast, along with +information that identifies the methods of the implementation that was used. +Values with a trait type can have [methods called] on them, for any method in +the trait, and can be used to instantiate type parameters that are bounded by +the trait. + +[methods called]: expressions/method-call-expr.html + +## Supertraits + +Trait bounds on `Self` are considered "supertraits". These are required to be +acyclic. Supertraits are somewhat different from other constraints in that +they affect what methods are available in the vtable when the trait is used as +a [trait object]. Consider the following example: + +```rust +trait Shape { fn area(&self) -> f64; } +trait Circle : Shape { fn radius(&self) -> f64; } +``` + +The syntax `Circle : Shape` means that types that implement `Circle` must also +have an implementation for `Shape`. Multiple supertraits are separated by `+`, +`trait Circle : Shape + PartialEq { }`. In an implementation of `Circle` for a +given type `T`, methods can refer to `Shape` methods, since the typechecker +checks that any type with an implementation of `Circle` also has an +implementation of `Shape`: + +```rust +struct Foo; + +trait Shape { fn area(&self) -> f64; } +trait Circle : Shape { fn radius(&self) -> f64; } +impl Shape for Foo { + fn area(&self) -> f64 { + 0.0 + } +} +impl Circle for Foo { + fn radius(&self) -> f64 { + println!("calling area: {}", self.area()); + + 0.0 + } +} + +let c = Foo; +c.radius(); +``` + +In type-parameterized functions, methods of the supertrait may be called on +values of subtrait-bound type parameters. Referring to the previous example of +`trait Circle : Shape`: + +```rust +# trait Shape { fn area(&self) -> f64; } +# trait Circle : Shape { fn radius(&self) -> f64; } +fn radius_times_area(c: T) -> f64 { + // `c` is both a Circle and a Shape + c.radius() * c.area() +} +``` + +Likewise, supertrait methods may also be called on trait objects. + +```rust +# trait Shape { fn area(&self) -> f64; } +# trait Circle : Shape { fn radius(&self) -> f64; } +# impl Shape for i32 { fn area(&self) -> f64 { 0.0 } } +# impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } } +# let mycircle = 0i32; +let mycircle = Box::new(mycircle) as Box; +let nonsense = mycircle.radius() * mycircle.area(); +``` diff --git a/src/items/type-aliases.md b/src/items/type-aliases.md new file mode 100644 index 0000000000000..532254372c6f6 --- /dev/null +++ b/src/items/type-aliases.md @@ -0,0 +1,25 @@ +# Type aliases + +A _type alias_ defines a new name for an existing [type]. Type aliases are +declared with the keyword `type`. Every value has a single, specific type, but +may implement several different traits, or be compatible with several different +type constraints. + +[type]: types.html + +For example, the following defines the type `Point` as a synonym for the type +`(u8, u8)`, the type of pairs of unsigned 8 bit integers: + +```rust +type Point = (u8, u8); +let p: Point = (41, 68); +``` + +A type alias to an enum type cannot be used to qualify the constructors: + +```rust +enum E { A } +type F = E; +let _: F = E::A; // OK +// let _: F = F::A; // Doesn't work +``` diff --git a/src/items/unions.md b/src/items/unions.md new file mode 100644 index 0000000000000..90bce698424a2 --- /dev/null +++ b/src/items/unions.md @@ -0,0 +1,141 @@ +# Unions + +A union declaration uses the same syntax as a struct declaration, except with +`union` in place of `struct`. + +```rust +#[repr(C)] +union MyUnion { + f1: u32, + f2: f32, +} +``` + +The key property of unions is that all fields of a union share common storage. +As a result writes to one field of a union can overwrite its other fields, and +size of a union is determined by the size of its largest field. + +A value of a union type can be created using the same syntax that is used for +struct types, except that it must specify exactly one field: + +```rust +# union MyUnion { f1: u32, f2: f32 } +# +let u = MyUnion { f1: 1 }; +``` + +The expression above creates a value of type `MyUnion` with active field `f1`. +Active field of a union can be accessed using the same syntax as struct fields: + +```rust,ignore +let f = u.f1; +``` + +Inactive fields can be accessed as well (using the same syntax) if they are +sufficiently layout compatible with the current value kept by the union. +Reading incompatible fields results in undefined behavior. However, the active +field is not generally known statically, so all reads of union fields have to +be placed in `unsafe` blocks. + +```rust +# union MyUnion { f1: u32, f2: f32 } +# let u = MyUnion { f1: 1 }; +# +unsafe { + let f = u.f1; +} +``` + +Writes to `Copy` union fields do not require reads for running destructors, so +these writes don't have to be placed in `unsafe` blocks + +```rust +# union MyUnion { f1: u32, f2: f32 } +# let mut u = MyUnion { f1: 1 }; +# +u.f1 = 2; +``` + +Commonly, code using unions will provide safe wrappers around unsafe union +field accesses. + +Another way to access union fields is to use pattern matching. Pattern matching +on union fields uses the same syntax as struct patterns, except that the +pattern must specify exactly one field. Since pattern matching accesses +potentially inactive fields it has to be placed in `unsafe` blocks as well. + +```rust +# union MyUnion { f1: u32, f2: f32 } +# +fn f(u: MyUnion) { + unsafe { + match u { + MyUnion { f1: 10 } => { println!("ten"); } + MyUnion { f2 } => { println!("{}", f2); } + } + } +} +``` + +Pattern matching may match a union as a field of a larger structure. In +particular, when using a Rust union to implement a C tagged union via FFI, this +allows matching on the tag and the corresponding field simultaneously: + +```rust +#[repr(u32)] +enum Tag { I, F } + +#[repr(C)] +union U { + i: i32, + f: f32, +} + +#[repr(C)] +struct Value { + tag: Tag, + u: U, +} + +fn is_zero(v: Value) -> bool { + unsafe { + match v { + Value { tag: I, u: U { i: 0 } } => true, + Value { tag: F, u: U { f: 0.0 } } => true, + _ => false, + } + } +} +``` + +Since union fields share common storage, gaining write access to one field of a +union can give write access to all its remaining fields. Borrow checking rules +have to be adjusted to account for this fact. As a result, if one field of a +union is borrowed, all its remaining fields are borrowed as well for the same +lifetime. + +```rust,ignore +// ERROR: cannot borrow `u` (via `u.f2`) as mutable more than once at a time +fn test() { + let mut u = MyUnion { f1: 1 }; + unsafe { + let b1 = &mut u.f1; + ---- first mutable borrow occurs here (via `u.f1`) + let b2 = &mut u.f2; + ^^^^ second mutable borrow occurs here (via `u.f2`) + *b1 = 5; + } + - first borrow ends here + assert_eq!(unsafe { u.f1 }, 5); +} +``` + +As you could see, in many aspects (except for layouts, safety and ownership) +unions behave exactly like structs, largely as a consequence of inheriting +their syntactic shape from structs. This is also true for many unmentioned +aspects of Rust language (such as privacy, name resolution, type inference, +generics, trait implementations, inherent implementations, coherence, pattern +checking, etc etc etc). + +More detailed specification for unions, including unstable bits, can be found +in [RFC 1897 "Unions v1.2"](https://github.com/rust-lang/rfcs/pull/1897). diff --git a/src/items/use-declarations.md b/src/items/use-declarations.md new file mode 100644 index 0000000000000..5ff173f89719d --- /dev/null +++ b/src/items/use-declarations.md @@ -0,0 +1,113 @@ +# Use declarations + +A _use declaration_ creates one or more local name bindings synonymous with +some other [path]. Usually a `use` declaration is used to shorten the path +required to refer to a module item. These declarations may appear in [modules] +and [blocks], usually at the top. + +[path]: paths.html +[modules]: items/modules.html +[blocks]: expressions/block-expr.html + +> **Note**: Unlike in many languages, `use` declarations in Rust do *not* +> declare linkage dependency with external crates. Rather, [`extern crate` +> declarations](items/extern-crates.html) declare linkage dependencies. + +Use declarations support a number of convenient shortcuts: + +* Simultaneously binding a list of paths differing only in their final element, + using the glob-like brace syntax `use a::b::{c,d,e,f};` +* Simultaneously binding a list of paths differing only in their final element + and their immediate parent module, using the `self` keyword, such as `use + a::b::{self, c, d};` +* Rebinding the target name as a new local name, using the syntax `use p::q::r + as x;`. This can also be used with the last two features: `use a::b::{self as + ab, c as abc}`. +* Binding all paths matching a given prefix, using the asterisk wildcard syntax + `use a::b::*;` + +An example of `use` declarations: + +```rust +use std::option::Option::{Some, None}; +use std::collections::hash_map::{self, HashMap}; + +fn foo(_: T){} +fn bar(map1: HashMap, map2: hash_map::HashMap){} + +fn main() { + // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64), + // std::option::Option::None]);' + foo(vec![Some(1.0f64), None]); + + // Both `hash_map` and `HashMap` are in scope. + let map1 = HashMap::new(); + let map2 = hash_map::HashMap::new(); + bar(map1, map2); +} +``` + +Like items, `use` declarations are private to the containing module, by +default. Also like items, a `use` declaration can be public, if qualified by +the `pub` keyword. Such a `use` declaration serves to _re-export_ a name. A +public `use` declaration can therefore _redirect_ some public name to a +different target definition: even a definition with a private canonical path, +inside a different module. If a sequence of such redirections form a cycle or +cannot be resolved unambiguously, they represent a compile-time error. + +An example of re-exporting: + +```rust +# fn main() { } +mod quux { + pub use quux::foo::{bar, baz}; + + pub mod foo { + pub fn bar() { } + pub fn baz() { } + } +} +``` + +In this example, the module `quux` re-exports two public names defined in +`foo`. + +Also note that the paths contained in `use` items are relative to the crate +root. So, in the previous example, the `use` refers to `quux::foo::{bar, baz}`, +and not simply to `foo::{bar, baz}`. This also means that top-level module +declarations should be at the crate root if direct usage of the declared +modules within `use` items is desired. It is also possible to use `self` and +`super` at the beginning of a `use` item to refer to the current and direct +parent modules respectively. All rules regarding accessing declared modules in +`use` declarations apply to both module declarations and `extern crate` +declarations. + +An example of what will and will not work for `use` items: + +```rust +# #![allow(unused_imports)] +use foo::baz::foobaz; // good: foo is at the root of the crate + +mod foo { + + mod example { + pub mod iter {} + } + + use foo::example::iter; // good: foo is at crate root +// use example::iter; // bad: example is not at the crate root + use self::baz::foobaz; // good: self refers to module 'foo' + use foo::bar::foobar; // good: foo is at crate root + + pub mod bar { + pub fn foobar() { } + } + + pub mod baz { + use super::bar::foobar; // good: super refers to module 'foo' + pub fn foobaz() { } + } +} + +fn main() {} +``` diff --git a/src/macros-by-example.md b/src/macros-by-example.md index a007b232e4c97..5b224ca5402d7 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -32,9 +32,9 @@ syntax named by _designator_. Valid designators are: * `meta`: the contents of an [attribute] [item]: items.html -[block]: expressions.html#block-expressions +[block]: expressions/block-expr.html [statement]: statements.html -[pattern]: expressions.html#match-expressions +[pattern]: expressions/match-expr.html [expression]: expressions.html [type]: types.html [identifier]: identifiers.html diff --git a/src/statements.md b/src/statements.md index ced9a850a19ee..56c7001e96feb 100644 --- a/src/statements.md +++ b/src/statements.md @@ -1,7 +1,7 @@ # Statements A _statement_ is a component of a block, which is in turn a component of an -outer [expression](expressions.html) or [function](items.html#functions). +outer [expression](expressions.html) or [function](items/functions.html). Rust has two kinds of statement: [declaration statements](#declaration-statements) and [expression @@ -40,7 +40,7 @@ An _expression statement_ is one that evaluates an [expression](expressions.html) and ignores its result. As a rule, an expression statement's purpose is to trigger the effects of evaluating its expression. An expression that consists of only a [block -expression](expressions.html#block-expressions) or control flow expression, +expression](expressions/block-expr.html) or control flow expression, that doesn't end a block and evaluates to `()` can also be used as an expression statement by omitting the trailing semicolon. diff --git a/src/string-table-productions.md b/src/string-table-productions.md index 3621f2d9ff03f..3fceb0847ffbd 100644 --- a/src/string-table-productions.md +++ b/src/string-table-productions.md @@ -12,7 +12,7 @@ When such a string enclosed in double-quotes (`"`) occurs inside the grammar, it is an implicit reference to a single member of such a string table production. See [tokens] for more information. -[binary operators]: expressions.html#arithmetic-and-logical-binary-operators -[keywords]: ../grammar.html#keywords +[binary operators]: expressions/operator-expr.html#arithmetic-and-logical-binary-operators +[keywords]: keywords.html [tokens]: tokens.html -[unary operators]: expressions.html#borrow-operators \ No newline at end of file +[unary operators]: expressions/operator-expr.html#borrow-operators diff --git a/src/tokens.md b/src/tokens.md index 2ad2a9dd8acad..c5746459e6b66 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -404,7 +404,7 @@ Note that the Rust syntax considers `-1i8` as an application of the [unary minus operator] to an integer literal `1i8`, rather than a single integer literal. -[unary minus operator]: expressions.html#negation-operators +[unary minus operator]: expressions/operator-expr.html#negation-operators #### Floating-point literals @@ -485,8 +485,8 @@ otherwise appear as [unary operators], [binary operators], or [keywords]. They are catalogued in [the Symbols section][symbols] of the Grammar document. -[unary operators]: expressions.html#borrow-operators -[binary operators]: expressions.html#arithmetic-and-logical-binary-operators +[unary operators]: expressions/operator-expr.html#borrow-operators +[binary operators]: expressions/operator-expr.html#arithmetic-and-logical-binary-operators [tokens]: #tokens [symbols]: ../grammar.html#symbols [keywords]: keywords.html diff --git a/src/types.md b/src/types.md index 900bf0d2626a7..6913a84df1ce8 100644 --- a/src/types.md +++ b/src/types.md @@ -10,7 +10,7 @@ limited capabilities. ## Primitive types Some types are defined by the language, rather than as part of the standard -library, these are called _primitive types_. Some of these are induvidual +library, these are called _primitive types_. Some of these are individual types: * The boolean type `bool` with values `true` and `false`. @@ -158,7 +158,7 @@ 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](expressions.html#struct-expressions). +expression](expressions/struct-expr.html). 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 @@ -175,7 +175,7 @@ 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](expressions.html#struct-expressions) is the only value that +expression](expressions/struct-expr.html) is the only value that inhabits such a type. [^structtype]: `struct` types are analogous to `struct` types in C, the @@ -184,20 +184,20 @@ inhabits such a type. ## Enumerated types An *enumerated type* is a nominal, heterogeneous disjoint union type, denoted -by the name of an [`enum` item](items.html#enumerations). [^enumtype] +by the name of an [`enum` item](items/enumerations.html). [^enumtype] -An [`enum` item](items.html#enumerations) declares both the type and a number +An [`enum` item](items/enumerations.html) declares both the type and a number of *variants*, each of which is independently named and has the syntax of a struct, tuple struct or unit-like struct. New instances of an `enum` can be constructed in an [enumeration variant -expression](expressions.html#enumeration-variant-expressions). +expression](expressions/enum-variant-expr.html). Any `enum` value consumes as much memory as the largest variant for its corresponding `enum` type, as well as the size needed to store a discriminant. Enum types cannot be denoted *structurally* as types, but must be denoted by -named reference to an [`enum` item](items.html#enumerations). +named reference to an [`enum` item](items/enumerations.html). [^enumtype]: The `enum` type is analogous to a `data` constructor declaration in ML, or a *pick ADT* in Limbo. @@ -205,7 +205,7 @@ named reference to an [`enum` item](items.html#enumerations). ## Union types A *union type* is a nominal, heterogeneous C-like union, denoted by the name of -a [`union` item](items.html#unions). +a [`union` item](items/unions.html). 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 @@ -365,7 +365,7 @@ x = bo(5,7); ## Closure types -A [closure expression](expressions.html#closure-expressions) produces a closure +A [closure expression](expressions/closure-expr.html) produces a closure value with a unique, anonymous type that cannot be written out. Depending on the requirements of the closure, its type implements one or @@ -579,4 +579,4 @@ impl Printable for String { } ``` -The notation `&self` is a shorthand for `self: &Self`. \ No newline at end of file +The notation `&self` is a shorthand for `self: &Self`. diff --git a/src/unsafety.md b/src/unsafety.md index a47aeefc6a395..a68353aedef8f 100644 --- a/src/unsafety.md +++ b/src/unsafety.md @@ -7,8 +7,8 @@ The following language level features cannot be used in the safe subset of Rust: - Dereferencing a [raw pointer](types.html#pointer-types). -- Reading or writing a [mutable static variable](items.html#mutable-statics). -- Reading a field of a [`union`](items.html#unions), or writing to a field of a +- Reading or writing a [mutable static variable](items/static-items.html#mutable-statics). +- Reading a field of a [`union`](items/unions.html), or writing to a field of a union that isn't [`Copy`](the-copy-trait.html). - Calling an unsafe function (including an intrinsic or foreign function). - Implementing an unsafe trait.