[^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature
gated. This is expected to improve soon.
-- The first character has property `XID_start`
-- The remaining characters have property `XID_continue`
+Either
+
+ * The first character has property `XID_start`
+ * The remaining characters have property `XID_continue`
+
+Or
+
+ * The first character is `_`
+ * The identifier is more than one character, `_` alone is not an identifier
+ * The remaining characters have property `XID_continue`
that does _not_ occur in the set of [keywords][keywords].
block (`/* ... */`) comment forms. Nested block comments are supported.
Line comments beginning with exactly _three_ slashes (`///`), and block
-comments beginning with exactly one repeated asterisk in the block-open
-sequence (`/**`), are interpreted as a special syntax for `doc`
+comments (`/** ... */`), are interpreted as a special syntax for `doc`
[attributes](#attributes). That is, they are equivalent to writing
`#[doc="..."]` around the body of the comment, i.e., `/// Foo` turns into
`#[doc="Foo"]`.
-Line comments beginning with `//!` and block comments beginning with `/*!` are
+Line comments beginning with `//!` and block comments `/*! ... !*/` are
doc comments that apply to the parent of the comment, rather than the item
that follows. That is, they are equivalent to writing `#![doc="..."]` around
the body of the comment. `//!` comments are usually used to document
| | Example | `#` sets | Characters | Escapes |
|----------------------------------------------|-----------------|------------|-------------|---------------------|
-| [Character](#character-literals) | `'H'` | `N/A` | All Unicode | `\'` & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) |
-| [String](#string-literals) | `"hello"` | `N/A` | All Unicode | `\"` & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) |
+| [Character](#character-literals) | `'H'` | `N/A` | All Unicode | [Quote](#quote-escapes) & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) |
+| [String](#string-literals) | `"hello"` | `N/A` | All Unicode | [Quote](#quote-escapes) & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) |
| [Raw](#raw-string-literals) | `r#"hello"#` | `0...` | All Unicode | `N/A` |
-| [Byte](#byte-literals) | `b'H'` | `N/A` | All ASCII | `\'` & [Byte](#byte-escapes) |
-| [Byte string](#byte-string-literals) | `b"hello"` | `N/A` | All ASCII | `\"` & [Byte](#byte-escapes) |
+| [Byte](#byte-literals) | `b'H'` | `N/A` | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) |
+| [Byte string](#byte-string-literals) | `b"hello"` | `N/A` | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) |
| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | `0...` | All ASCII | `N/A` |
##### Byte escapes
| `\r` | Carriage return |
| `\t` | Tab |
| `\\` | Backslash |
+| `\0` | Null |
##### Unicode escapes
| | Name |
|---|------|
| `\u{7FFF}` | 24-bit Unicode character code (up to 6 digits) |
+##### Quote escapes
+| | Name |
+|---|------|
+| `\'` | Single quote |
+| `\"` | Double quote |
+
##### Numbers
| [Number literals](#number-literals)`*` | Example | Exponentiation | Suffixes |
### Symbols
-Symbols are a general class of printable [token](#tokens) that play structural
-roles in a variety of grammar productions. They are catalogued here for
-completeness as the set of remaining miscellaneous printable tokens that do not
+Symbols are a general class of printable [tokens](#tokens) that play structural
+roles in a variety of grammar productions. They are a
+set of remaining miscellaneous printable tokens that do not
otherwise appear as [unary operators](#unary-operator-expressions), [binary
operators](#binary-operator-expressions), or [keywords][keywords].
+They are catalogued in [the Symbols section][symbols] of the Grammar document.
+
+[symbols]: grammar.html#symbols
## Paths
balanced, but they are otherwise not special.
In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust
-syntax named by _designator_. Valid designators are `item`, `block`, `stmt`,
-`pat`, `expr`, `ty` (type), `ident`, `path`, `tt` (either side of the `=>`
-in macro rules), and `meta` (contents of an attribute). In the transcriber, the
+syntax named by _designator_. Valid designators are:
+
+* `item`: an [item](#items)
+* `block`: a [block](#block-expressions)
+* `stmt`: a [statement](#statements)
+* `pat`: a [pattern](#match-expressions)
+* `expr`: an [expression](#expressions)
+* `ty`: a [type](#types)
+* `ident`: an [identifier](#identifiers)
+* `path`: a [path](#paths)
+* `tt`: either side of the `=>` in macro rules
+* `meta`: the contents of an [attribute](#attributes)
+
+In the transcriber, the
designator is already known, and so only the name of a matched nonterminal comes
after the dollar sign.
# Crates and source files
Although Rust, like any other language, can be implemented by an interpreter as
-well as a compiler, the only existing implementation is a compiler —
-from now on referred to as *the* Rust compiler — and the language has
+well as a compiler, the only existing implementation is a compiler,
+and the language has
always been designed to be compiled. For these reasons, this section assumes a
compiler.
* [modules](#modules)
* [functions](#functions)
* [type definitions](grammar.html#type-definitions)
-* [structures](#structures)
+* [structs](#structs)
* [enumerations](#enumerations)
* [constant items](#constant-items)
* [static items](#static-items)
}
use foo::example::iter; // good: foo is at crate root
-// use example::iter; // bad: core is not at the 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
### Functions
-A _function item_ defines a sequence of [statements](#statements) and an
-optional final [expression](#expressions), along with a name and a set of
-parameters. Functions are declared with the keyword `fn`. Functions declare a
+A _function item_ defines a sequence of [statements](#statements) and a
+final [expression](#expressions), 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*](#types)
of the value the function will return to its caller on completion.
```
fn add(x: i32, y: i32) -> i32 {
- return x + y;
+ x + y
}
```
there is not sufficient context to determine the type parameters. For example,
`mem::size_of::<u32>() == 4`.
-#### Unsafety
-
-Unsafe operations are those that potentially violate the memory-safety
-guarantees of Rust's static semantics.
-
-The following language level features cannot be used in the safe subset of
-Rust:
-
-- Dereferencing a [raw pointer](#pointer-types).
-- Reading or writing a [mutable static variable](#mutable-statics).
-- Calling an unsafe function (including an intrinsic or foreign function).
-
-##### Unsafe functions
-
-Unsafe functions are functions that are not safe in all contexts and/or for all
-possible inputs. Such a function must be prefixed with the keyword `unsafe` and
-can only be called from an `unsafe` block or another `unsafe` function.
-
-##### Unsafe blocks
-
-A block of code can be prefixed with the `unsafe` keyword, to permit calling
-`unsafe` functions or dereferencing raw pointers within a safe function.
-
-When a programmer has sufficient conviction that a sequence of potentially
-unsafe operations is actually safe, they can encapsulate that sequence (taken
-as a whole) within an `unsafe` block. The compiler will consider uses of such
-code safe, in the surrounding context.
-
-Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
-or implement features not directly present in the language. For example, Rust
-provides the language features necessary to implement memory-safe concurrency
-in the language but the implementation of threads and message passing is in the
-standard library.
-
-Rust's type system is a conservative approximation of the dynamic safety
-requirements, so in some cases there is a performance cost to using safe code.
-For example, a doubly-linked list is not a tree structure and can only be
-represented with reference-counted pointers in safe code. By using `unsafe`
-blocks to represent the reverse links as raw pointers, it can be implemented
-with only boxes.
-
-##### Behavior considered undefined
-
-The following is a list of behavior which is forbidden in all Rust code,
-including within `unsafe` blocks and `unsafe` functions. Type checking provides
-the guarantee that these issues are never caused by safe code.
-
-* Data races
-* Dereferencing a null/dangling raw pointer
-* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values)
- (uninitialized) memory
-* Breaking the [pointer aliasing
- rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules)
- with raw pointers (a subset of the rules used by C)
-* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T`
- contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
- guarantees.
-* Mutating non-mutable data (that is, data reached through a shared reference or
- data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
-* Invoking undefined behavior via compiler intrinsics:
- * Indexing outside of the bounds of an object with `std::ptr::offset`
- (`offset` intrinsic), with
- the exception of one byte past the end which is permitted.
- * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
- intrinsics) on overlapping buffers
-* Invalid values in primitive types, even in private fields/locals:
- * Dangling/null references or boxes
- * A value other than `false` (0) or `true` (1) in a `bool`
- * A discriminant in an `enum` not included in the type definition
- * A value in a `char` which is a surrogate or above `char::MAX`
- * Non-UTF-8 byte sequences in a `str`
-* Unwinding into Rust from foreign code or unwinding from Rust into foreign
- code. Rust's failure system is not compatible with exception handling in
- other languages. Unwinding must be caught and handled at FFI boundaries.
-
-[noalias]: http://llvm.org/docs/LangRef.html#noalias
-
-##### Behavior not considered unsafe
-
-This is a list of behavior not considered *unsafe* in Rust terms, but that may
-be undesired.
-
-* Deadlocks
-* Leaks of memory and other resources
-* Exiting without calling destructors
-* Integer overflow
- - Overflow is considered "unexpected" behavior and is always user-error,
- unless the `wrapping` primitives are used. In non-optimized builds, the compiler
- will insert debug checks that panic on overflow, but in optimized builds overflow
- instead results in wrapped values. See [RFC 560] for the rationale and more details.
-
-[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
-
#### Diverging functions
A special kind of function can be declared with a `!` character where the
# fn my_err(s: &str) -> ! { panic!() }
fn f(i: i32) -> i32 {
- if i == 42 {
- return 42;
- }
- else {
- my_err("Bad number!");
- }
+ if i == 42 {
+ return 42;
+ }
+ else {
+ my_err("Bad number!");
+ }
}
```
let p: Point = (41, 68);
```
-### Structures
+### Structs
-A _structure_ is a nominal [structure type](#structure-types) defined with the
+A _struct_ is a nominal [struct type](#struct-types) defined with the
keyword `struct`.
An example of a `struct` item and its use:
let px: i32 = p.x;
```
-A _tuple structure_ is a nominal [tuple type](#tuple-types), also defined with
+A _tuple struct_ is a nominal [tuple type](#tuple-types), also defined with
the keyword `struct`. For example:
```
let px: i32 = match p { Point(x, _) => x };
```
-A _unit-like struct_ is a structure without any fields, defined by leaving off
-the list of fields entirely. Such types will have a single value. For example:
+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:
```
+# #![feature(braced_empty_structs)]
struct Cookie;
-let c = [Cookie, Cookie, Cookie, Cookie];
+let c = [Cookie, Cookie {}, Cookie, Cookie {}];
+```
+
+is equivalent to
+
+```
+# #![feature(braced_empty_structs)]
+struct Cookie {}
+const Cookie: Cookie = Cookie {};
+let c = [Cookie, Cookie {}, Cookie, Cookie {}];
```
-The precise memory layout of a structure is not specified. One can specify a
+The precise memory layout of a struct is not specified. One can specify a
particular layout using the [`repr` attribute](#ffi-attributes).
### Enumerations
```
trait Seq<T> {
- fn len(&self) -> u32;
- fn elt_at(&self, n: u32) -> T;
- fn iter<F>(&self, F) where F: Fn(T);
+ fn len(&self) -> u32;
+ fn elt_at(&self, n: u32) -> T;
+ fn iter<F>(&self, F) where F: Fn(T);
}
```
let x: f64 = Num::from_i32(42);
```
-Traits may inherit from other traits. For example, in
+Traits may inherit from other traits. Consider the following example:
```
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
+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
trait Shape { fn area(&self) -> f64; }
trait Circle : Shape { fn radius(&self) -> f64; }
-# impl Shape for Foo {
-# fn area(&self) -> f64 {
-# 0.0
-# }
-# }
+impl Shape for Foo {
+ fn area(&self) -> f64 {
+ 0.0
+ }
+}
impl Circle for Foo {
fn radius(&self) -> f64 {
println!("calling area: {}", self.area());
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}
+ 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), and the implementation must appear
-in the same crate as the `self` type:
+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, trait objects), and the implementation must
+appear in the same crate as the `self` type:
```
struct Point {x: i32, y: i32}
```
# trait Seq<T> { fn dummy(&self, _: T) { } }
impl<T> Seq<T> for Vec<T> {
- /* ... */
+ /* ... */
}
impl Seq<bool> for u32 {
- /* Treat the integer as a sequence of bits */
+ /* Treat the integer as a sequence of bits */
}
```
// A function marked as a unit test
#[test]
fn test_foo() {
- /* ... */
+ /* ... */
}
// A conditionally-compiled module
#[cfg(target_os="linux")]
mod bar {
- /* ... */
+ /* ... */
}
// A lint attribute used to suppress a warning/error
list of names `#[macro_use(foo, bar)]` restricts the import to just those
macros named. The `extern crate` must appear at the crate root, not inside
`mod`, which ensures proper function of the [`$crate` macro
- variable](book/macros.html#the-variable-$crate).
+ variable](book/macros.html#the-variable-crate).
- `macro_reexport` on an `extern crate` — re-export the named macros.
link it into the output.
See the [macros section of the
-book](book/macros.html#scoping-and-macro-import/export) for more information on
+book](book/macros.html#scoping-and-macro-importexport) for more information on
macro scope.
- `simd` - on certain tuple structs, derive the arithmetic operators, which
lower to the target's SIMD instructions, if any; the `simd` feature gate
is necessary to use this attribute.
+- `unsafe_destructor_blind_to_params` - on `Drop::drop` method, asserts that the
+ destructor code (and all potential specializations of that code) will
+ never attempt to read from nor write to any references with lifetimes
+ that come in via generic parameters. This is a constraint we cannot
+ currently express via the type system, and therefore we rely on the
+ programmer to assert that it holds. Adding this to a Drop impl causes
+ the associated destructor to be considered "uninteresting" by the
+ Drop-Check rule, and thus it can help sidestep data ordering
+ constraints that would otherwise be introduced by the Drop-Check
+ rule. Such sidestepping of the constraints, if done incorrectly, can
+ lead to undefined behavior (in the form of reading or writing to data
+ outside of its dynamic extent), and thus this attribute has the word
+ "unsafe" in its name. To use this, the
+ `unsafe_destructor_blind_to_params` feature gate must be enabled.
- `unsafe_no_drop_flag` - on structs, remove the flag that prevents
destructors from being run twice. Destructors might be run multiple times on
the same object with this attribute. To use this, the `unsafe_no_drop_flag` feature
The following configurations must be defined by the implementation:
-* `debug_assertions`. Enabled by default when compiling without optimizations.
+* `debug_assertions` - Enabled by default when compiling without optimizations.
This can be used to enable extra debugging code in development but not in
production. For example, it controls the behavior of the standard library's
`debug_assert!` macro.
-* `target_arch = "..."`. Target CPU architecture, such as `"x86"`, `"x86_64"`
+* `target_arch = "..."` - Target CPU architecture, such as `"x86"`, `"x86_64"`
`"mips"`, `"powerpc"`, `"arm"`, or `"aarch64"`.
-* `target_endian = "..."`. Endianness of the target CPU, either `"little"` or
+* `target_endian = "..."` - Endianness of the target CPU, either `"little"` or
`"big"`.
-* `target_env = ".."` - an option provided by the compiler by default
+* `target_env = ".."` - An option provided by the compiler by default
describing the runtime environment of the target platform. Some examples of
this are `musl` for builds targeting the MUSL libc implementation, `msvc` for
Windows builds targeting MSVC, and `gnu` frequently the rest of the time. This
option may also be blank on some platforms.
-* `target_family = "..."`. Operating system family of the target, e. g.
+* `target_family = "..."` - Operating system family of the target, e. g.
`"unix"` or `"windows"`. The value of this configuration option is defined
as a configuration itself, like `unix` or `windows`.
-* `target_os = "..."`. Operating system of the target, examples include
+* `target_os = "..."` - Operating system of the target, examples include
`"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
`"bitrig"` , `"openbsd"` or `"netbsd"`.
-* `target_pointer_width = "..."`. Target pointer width in bits. This is set
+* `target_pointer_width = "..."` - Target pointer width in bits. This is set
to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
64-bit pointers.
-* `test`. Enabled when compiling the test harness (using the `--test` flag).
-* `unix`. See `target_family`.
-* `windows`. See `target_family`.
+* `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or
+ simply `"unknown"`.
+* `test` - Enabled when compiling the test harness (using the `--test` flag).
+* `unix` - See `target_family`.
+* `windows` - See `target_family`.
You can also set another attribute based on a `cfg` variable with `cfg_attr`:
* `advanced_slice_patterns` - See the [match expressions](#match-expressions)
section for discussion; the exact semantics of
slice patterns are subject to change, so some types
- are still unstable.
+ are still unstable.
* `slice_patterns` - OK, actually, slice patterns are just scary and
completely unstable.
* `box_syntax` - Allows use of `box` expressions, the exact semantics of which
is subject to change.
+* `cfg_target_vendor` - Allows conditional compilation using the `target_vendor`
+ matcher which is subject to change.
+
* `concat_idents` - Allows use of the `concat_idents` macro, which is in many
ways insufficient for concatenating identifiers, and may be
removed entirely for something more wholesome.
* `simd_ffi` - Allows use of SIMD vectors in signatures for foreign functions.
The SIMD interface is subject to change.
-* `staged_api` - Allows usage of stability markers and `#![staged_api]` in a
- crate. Stability markers are also attributes: `#[stable]`,
- `#[unstable]`, and `#[deprecated]` are the three levels.
-
* `start` - Allows use of the `#[start]` attribute, which changes the entry point
into a Rust program. This capability, especially the signature for the
annotated function, is subject to change.
-* `struct_inherit` - Allows using struct inheritance, which is barely
- implemented and will probably be removed. Don't use this.
-
-* `struct_variant` - Structural enum variants (those with named fields). It is
- currently unknown whether this style of enum variant is as
- fully supported as the tuple-forms, and it's not certain
- that this style of variant should remain in the language.
- For now this style of variant is hidden behind a feature
- flag.
-
* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
and should be seen as unstable. This attribute is used to
declare a `static` as being unique per-thread leveraging
terms of encapsulation).
* - `default_type_parameter_fallback` - Allows type parameter defaults to
influence type inference.
+* - `braced_empty_structs` - Allows use of empty structs and enum variants with braces.
+
+* - `stmt_expr_attributes` - Allows attributes on expressions and
+ non-item statements.
If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about `#![feature]` directives which enabled
An _item declaration statement_ has a syntactic form identical to an
[item](#items) declaration within a module. Declaring an item — a
-function, enumeration, structure, type, static, trait, implementation or module
+function, enumeration, struct, type, static, trait, implementation or module
— locally within a statement block is simply a way of restricting its
scope to a narrow region containing all of its uses; it is otherwise identical
in meaning to declaring the item outside the statement block.
> **Note**: there is no implicit capture of the function's dynamic environment when
> declaring a function-local item.
-#### Variable declarations
+#### `let` statements
-A _variable declaration_ introduces a new set of variable, given by a pattern. The
+A _`let` statement_ introduces a new set of variables, given by a pattern. The
pattern may be followed by a type annotation, and/or an initializer expression.
When no type annotation is given, the compiler will infer the type, or signal
an error if insufficient type information is available for definite inference.
#### Moved and copied types
When a [local variable](#variables) is used as an
-[rvalue](#lvalues,-rvalues-and-temporaries), the variable will be copied
+[rvalue](#lvalues-rvalues-and-temporaries), the variable will be copied
if its type implements `Copy`. All others are moved.
### Literal expressions
### Path expressions
A [path](#paths) used as an expression context denotes either a local variable
-or an item. Path expressions are [lvalues](#lvalues,-rvalues-and-temporaries).
+or an item. Path expressions are [lvalues](#lvalues-rvalues-and-temporaries).
### Tuple expressions
(0); // zero in parentheses
```
-### Structure expressions
+### Struct expressions
-There are several forms of structure expressions. A _structure expression_
-consists of the [path](#paths) of a [structure item](#structures), followed by
+There are several forms of struct expressions. A _struct expression_
+consists of the [path](#paths) of a [struct item](#structs), followed by
a brace-enclosed list of one or more comma-separated name-value pairs,
-providing the field values of a new instance of the structure. A field name
+providing the field values of a new instance of the struct. A field name
can be any identifier, and is separated from its value expression by a colon.
-The location denoted by a structure field is mutable if and only if the
-enclosing structure is mutable.
+The location denoted by a struct field is mutable if and only if the
+enclosing struct is mutable.
-A _tuple structure expression_ consists of the [path](#paths) of a [structure
-item](#structures), followed by a parenthesized list of one or more
-comma-separated expressions (in other words, the path of a structure item
-followed by a tuple expression). The structure item must be a tuple structure
+A _tuple struct expression_ consists of the [path](#paths) of a [struct
+item](#structs), 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 structure expression_ consists only of the [path](#paths) of a
-[structure item](#structures).
+A _unit-like struct expression_ consists only of the [path](#paths) of a
+[struct item](#structs).
-The following are examples of structure expressions:
+The following are examples of struct expressions:
```
# struct Point { x: f64, y: f64 }
some_fn::<Cookie>(Cookie);
```
-A structure expression forms a new value of the named structure type. Note
-that for a given *unit-like* structure type, this will always be the same
+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 structure expression can terminate with the syntax `..` followed by an
+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 structure type as the new structure type being formed.
-The entire expression denotes the result of constructing a new structure (with
+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.
A _field expression_ consists of an expression followed by a single dot and an
identifier, when not immediately followed by a parenthesized expression-list
(the latter is a [method call expression](#method-call-expressions)). A field
-expression denotes a field of a [structure](#structure-types).
+expression denotes a field of a [struct](#struct-types).
```{.ignore .field}
mystruct.myfield;
(Struct {a: 10, b: 20}).a;
```
-A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to
+A field access is an [lvalue](#lvalues-rvalues-and-temporaries) referring to
the value of that field. When the type providing the field inherits mutability,
it can be [assigned](#assignment-expressions) to.
### Array expressions
-An [array](#array,-and-slice-types) _expression_ is written by enclosing zero
+An [array](#array-and-slice-types) _expression_ is written by enclosing zero
or more comma-separated expressions of uniform type in square brackets.
In the `[expr ';' expr]` form, the expression after the `';'` must be a
### Index expressions
-[Array](#array,-and-slice-types)-typed expressions can be indexed by
+[Array](#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](#lvalues,-rvalues-and-temporaries) can
+array is mutable, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can
be assigned to.
Indices are zero-based, and may be of any integral type. Vector access is
let x = std::ops::Range {start: 0, end: 10};
let y = 0..10;
-assert_eq!(x,y);
+assert_eq!(x, y);
```
### Unary operator expressions
* `*`
: Dereference. When applied to a [pointer](#pointer-types) it denotes the
pointed-to location. For pointers to mutable locations, the resulting
- [lvalue](#lvalues,-rvalues-and-temporaries) can be assigned to.
+ [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to.
On non-pointer types, it calls the `deref` method of the `std::ops::Deref`
trait, or the `deref_mut` method of the `std::ops::DerefMut` trait (if
implemented by the type and required for an outer expression that will or
# 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
+ let sum: f64 = sum(values);
+ let size: f64 = len(values) as f64;
+ sum / size
}
```
#### Assignment expressions
An _assignment expression_ consists of an
-[lvalue](#lvalues,-rvalues-and-temporaries) expression followed by an equals
-sign (`=`) and an [rvalue](#lvalues,-rvalues-and-temporaries) expression.
+[lvalue](#lvalues-rvalues-and-temporaries) expression followed by an equals
+sign (`=`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression.
Evaluating an assignment expression [either copies or
moves](#moved-and-copied-types) its right-hand operand to its left-hand
a lifetime preceding the loop expression, as in `'foo: loop{ }`. 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
+See [break expressions](#break-expressions) and [continue
expressions](#continue-expressions).
-### Break expressions
+### `break` expressions
A `break` expression has an optional _label_. If the label is absent, then
executing a `break` expression immediately terminates the innermost loop
present, then `break 'foo` terminates the loop with label `'foo`, which need not
be the innermost label enclosing the `break` expression, but must enclose it.
-### Continue expressions
+### `continue` expressions
A `continue` expression has an optional _label_. If the label is absent, then
executing a `continue` expression immediately terminates the current iteration
A `continue` expression is only permitted in the body of a loop.
-### While loops
+### `while` loops
A `while` loop begins by evaluating the boolean loop conditional expression.
If the loop conditional expression evaluates to `true`, the loop body block
loops](#infinite-loops), [break expressions](#break-expressions), and
[continue expressions](#continue-expressions) for more information.
-### For expressions
+### `for` expressions
A `for` expression is a syntactic construct for looping over elements provided
by an implementation of `std::iter::IntoIterator`.
-An example of a for loop over the contents of an array:
+An example of a `for` loop over the contents of an array:
```
# type Foo = i32;
loops](#infinite-loops), [break expressions](#break-expressions), and
[continue expressions](#continue-expressions) for more information.
-### If 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
if` condition is evaluated. If all `if` and `else if` conditions evaluate to
`false` then any `else` block is executed.
-### Match expressions
+### `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, structures and tuples,
+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
fields of a particular variant.
A `match` behaves differently depending on whether or not the head expression
-is an [lvalue or an rvalue](#lvalues,-rvalues-and-temporaries). If the head
+is an [lvalue or an rvalue](#lvalues-rvalues-and-temporaries). 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
# let x = 2;
let message = match x {
- 0 | 1 => "not many",
- 2 ... 9 => "a few",
- _ => "lots"
+ 0 | 1 => "not many",
+ 2 ... 9 => "a few",
+ _ => "lots"
};
```
# 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!()
+ Some(x) if x < 10 => process_digit(x),
+ Some(x) => process_other(x),
+ None => panic!()
};
```
-### If let expressions
+### `if let` expressions
-An `if let` expression is semantically identical to an `if` expression but in place
-of a condition expression it expects a refutable let statement. If the value of the
-expression on the right hand side of the let statement matches the pattern, the corresponding
-block will execute, otherwise flow proceeds to the first `else` block that follows.
+An `if let` expression is semantically identical to an `if` expression but in
+place of a condition expression it expects a `let` statement with a refutable
+pattern. If the value of the expression on the right hand side of the `let`
+statement matches the pattern, the corresponding block will execute, otherwise
+flow proceeds to the first `else` block that follows.
```
let dish = ("Ham", "Eggs");
}
```
-### While let loops
+### `while let` loops
-A `while let` loop is semantically identical to a `while` loop but in place of a
-condition expression it expects a refutable let statement. If the value of the
-expression on the right hand side of the let statement matches the pattern, the
-loop body block executes and control returns to the pattern matching statement.
-Otherwise, the while expression completes.
+A `while let` loop is semantically identical to a `while` loop but in place of
+a condition expression it expects `let` statement with a refutable pattern. If
+the value of the expression on the right hand side of the `let` statement
+matches the pattern, the loop body block executes and control returns to the
+pattern matching statement. Otherwise, the while expression completes.
-### Return expressions
+### `return` expressions
Return expressions are denoted with the keyword `return`. Evaluating a `return`
expression moves its argument into the designated output location for the
```
fn max(a: i32, b: i32) -> i32 {
- if a > b {
- return a;
- }
- return b;
+ if a > b {
+ return a;
+ }
+ return b;
}
```
All in-bounds elements of arrays and slices are always initialized, and access
to an array or slice is always bounds-checked.
-### Structure types
+### Struct types
A `struct` *type* is a heterogeneous product of other types, called the
*fields* of the type.[^structtype]
[^structtype]: `struct` types are analogous to `struct` types in C,
the *record* types of the ML family,
- or the *structure* types of the Lisp family.
+ or the *struct* types of the Lisp family.
New instances of a `struct` can be constructed with a [struct
-expression](#structure-expressions).
+expression](#struct-expressions).
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
The fields of a `struct` may be qualified by [visibility
modifiers](#visibility-and-privacy), to allow access to data in a
-structure outside a module.
+struct outside a module.
-A _tuple struct_ type is just like a structure type, except that the fields are
+A _tuple struct_ type is just like a struct type, except that the fields are
anonymous.
-A _unit-like struct_ type is like a structure type, except that it has no
-fields. The one value constructed by the associated [structure
-expression](#structure-expressions) is the only value that inhabits such a
+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](#struct-expressions) is the only value that inhabits such a
type.
### Enumerated types
### Recursive types
Nominal types — [enumerations](#enumerated-types) and
-[structures](#structure-types) — may be recursive. That is, each `enum`
+[structs](#struct-types) — may be recursive. That is, each `enum`
constructor or `struct` field may refer, directly or indirectly, to the
enclosing `enum` or `struct` type itself. Such recursion has restrictions:
* Recursive types must include a nominal type in the recursion
(not mere [type definitions](grammar.html#type-definitions),
- or other structural types such as [arrays](#array,-and-slice-types) or [tuples](#tuple-types)).
+ or other structural types such as [arrays](#array-and-slice-types) or [tuples](#tuple-types)).
* A recursive `enum` item must have at least one non-recursive constructor
(in order to give the recursion a basis case).
* The size of a recursive type must be finite;
### Pointer types
All pointers in Rust are explicit first-class values. They can be copied,
-stored into data structures, and returned from functions. There are two
+stored into data structs, and returned from functions. There are two
varieties of pointer in Rust:
* References (`&`)
```
fn add(x: i32, y: i32) -> i32 {
- return x + y;
+ return x + y;
}
let mut x = add(5,7);
```
trait Printable {
- fn stringify(&self) -> String;
+ fn stringify(&self) -> String;
}
impl Printable for i32 {
- fn stringify(&self) -> String { self.to_string() }
+ fn stringify(&self) -> String { self.to_string() }
}
fn print(a: Box<Printable>) {
- println!("{}", a.stringify());
+ println!("{}", a.stringify());
}
fn main() {
- print(Box::new(10) as Box<Printable>);
+ print(Box::new(10) as Box<Printable>);
}
```
```ignore
fn to_vec<A: Clone>(xs: &[A]) -> Vec<A> {
if xs.is_empty() {
- return vec![];
+ return vec![];
}
let first: A = xs[0].clone();
let mut rest: Vec<A> = to_vec(&xs[1..]);
```
trait Printable {
- fn make_string(&self) -> String;
+ fn make_string(&self) -> String;
}
impl Printable for String {
fn bar(_: i8) { }
fn main() {
- bar(128);
+ bar(128);
}
```
Each sub-expression is a coercion site to the respective type, e.g. the
zeroth sub-expression is a coercion site to type `U_0`.
-* Parenthesised sub-expressions (`(e)`): if the expression has type `U`, then
+* Parenthesized sub-expressions (`(e)`): if the expression has type `U`, then
the sub-expression is a coercion site to `U`.
* Blocks: if a block has type `U`, then the last expression in the block (if
### Variables
A _variable_ is a component of a stack frame, either a named function parameter,
-an anonymous [temporary](#lvalues,-rvalues-and-temporaries), or a named local
+an anonymous [temporary](#lvalues-rvalues-and-temporaries), or a named local
variable.
A _local variable_ (or *stack-local* allocation) holds a value directly,
The Rust compiler supports various methods to link crates together both
statically and dynamically. This section will explore the various methods to
link Rust crates together, and more information about native libraries can be
-found in the [ffi section of the book][ffi].
+found in the [FFI section of the book][ffi].
In one session of compilation, the compiler can generate multiple artifacts
through the usage of either command line flags or the `crate_type` attribute.
-If one or more command line flag is specified, all `crate_type` attributes will
+If one or more command line flags are specified, all `crate_type` attributes will
be ignored in favor of only building the artifacts specified by command line.
* `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be
specified, then the compiler will produce each form of output at once without
having to recompile. However, this only applies for outputs specified by the
same method. If only `crate_type` attributes are specified, then they will all
-be built, but if one or more `--crate-type` command line flag is specified,
+be built, but if one or more `--crate-type` command line flags are specified,
then only those outputs will be built.
With all these different kinds of outputs, if crate A depends on crate B, then
all compilation needs, and the other options are just available if more
fine-grained control is desired over the output format of a Rust crate.
-# Appendix: Rationales and design trade-offs
+# Unsafety
+
+Unsafe operations are those that potentially violate the memory-safety
+guarantees of Rust's static semantics.
+
+The following language level features cannot be used in the safe subset of
+Rust:
+
+- Dereferencing a [raw pointer](#pointer-types).
+- Reading or writing a [mutable static variable](#mutable-statics).
+- Calling an unsafe function (including an intrinsic or foreign function).
+
+## Unsafe functions
+
+Unsafe functions are functions that are not safe in all contexts and/or for all
+possible inputs. Such a function must be prefixed with the keyword `unsafe` and
+can only be called from an `unsafe` block or another `unsafe` function.
+
+## Unsafe blocks
+
+A block of code can be prefixed with the `unsafe` keyword, to permit calling
+`unsafe` functions or dereferencing raw pointers within a safe function.
+
+When a programmer has sufficient conviction that a sequence of potentially
+unsafe operations is actually safe, they can encapsulate that sequence (taken
+as a whole) within an `unsafe` block. The compiler will consider uses of such
+code safe, in the surrounding context.
+
+Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
+or implement features not directly present in the language. For example, Rust
+provides the language features necessary to implement memory-safe concurrency
+in the language but the implementation of threads and message passing is in the
+standard library.
+
+Rust's type system is a conservative approximation of the dynamic safety
+requirements, so in some cases there is a performance cost to using safe code.
+For example, a doubly-linked list is not a tree structure and can only be
+represented with reference-counted pointers in safe code. By using `unsafe`
+blocks to represent the reverse links as raw pointers, it can be implemented
+with only boxes.
+
+## Behavior considered undefined
+
+The following is a list of behavior which is forbidden in all Rust code,
+including within `unsafe` blocks and `unsafe` functions. Type checking provides
+the guarantee that these issues are never caused by safe code.
+
+* Data races
+* Dereferencing a null/dangling raw pointer
+* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values)
+ (uninitialized) memory
+* Breaking the [pointer aliasing
+ rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules)
+ with raw pointers (a subset of the rules used by C)
+* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T`
+ contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
+ guarantees.
+* Mutating non-mutable data (that is, data reached through a shared reference or
+ data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
+* Invoking undefined behavior via compiler intrinsics:
+ * Indexing outside of the bounds of an object with `std::ptr::offset`
+ (`offset` intrinsic), with
+ the exception of one byte past the end which is permitted.
+ * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
+ intrinsics) on overlapping buffers
+* Invalid values in primitive types, even in private fields/locals:
+ * Dangling/null references or boxes
+ * A value other than `false` (0) or `true` (1) in a `bool`
+ * A discriminant in an `enum` not included in the type definition
+ * A value in a `char` which is a surrogate or above `char::MAX`
+ * Non-UTF-8 byte sequences in a `str`
+* Unwinding into Rust from foreign code or unwinding from Rust into foreign
+ code. Rust's failure system is not compatible with exception handling in
+ other languages. Unwinding must be caught and handled at FFI boundaries.
+
+[noalias]: http://llvm.org/docs/LangRef.html#noalias
+
+## Behavior not considered unsafe
-*TODO*.
+This is a list of behavior not considered *unsafe* in Rust terms, but that may
+be undesired.
+
+* Deadlocks
+* Leaks of memory and other resources
+* Exiting without calling destructors
+* Integer overflow
+ - Overflow is considered "unexpected" behavior and is always user-error,
+ unless the `wrapping` primitives are used. In non-optimized builds, the compiler
+ will insert debug checks that panic on overflow, but in optimized builds overflow
+ instead results in wrapped values. See [RFC 560] for the rationale and more details.
+
+[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
# Appendix: Influences
* SML, OCaml: algebraic data types, pattern matching, type inference,
semicolon statement separation
-* C++: references, RAII, smart pointers, move semantics, monomorphisation,
+* C++: references, RAII, smart pointers, move semantics, monomorphization,
memory model
* ML Kit, Cyclone: region based memory management
* Haskell (GHC): typeclasses, type families