Auto merge of #24798 - steveklabnik:rollup, r=steveklabnik
- Successful merges: #24662, #24722, #24725, #24729, #24736, #24749, #24751, #24766, #24769, #24772, #24775, #24790 - Failed merges: #24760
This commit is contained in:
commit
a40261ac91
@ -152,19 +152,19 @@ token : simple_token | ident | literal | symbol | whitespace token ;
|
||||
|
||||
<p id="keyword-table-marker"></p>
|
||||
|
||||
| | | | | |
|
||||
|----------|----------|----------|----------|--------|
|
||||
| abstract | alignof | as | become | box |
|
||||
| break | const | continue | crate | do |
|
||||
| else | enum | extern | false | final |
|
||||
| fn | for | if | impl | in |
|
||||
| let | loop | match | mod | move |
|
||||
| mut | offsetof | once | override | priv |
|
||||
| proc | pub | pure | ref | return |
|
||||
| sizeof | static | self | struct | super |
|
||||
| true | trait | type | typeof | unsafe |
|
||||
| unsized | use | virtual | where | while |
|
||||
| yield | | | | |
|
||||
| | | | | |
|
||||
|----------|----------|----------|----------|---------|
|
||||
| abstract | alignof | as | become | box |
|
||||
| break | const | continue | crate | do |
|
||||
| else | enum | extern | false | final |
|
||||
| fn | for | if | impl | in |
|
||||
| let | loop | macro | match | mod |
|
||||
| move | mut | offsetof | override | priv |
|
||||
| proc | pub | pure | ref | return |
|
||||
| Self | self | sizeof | static | struct |
|
||||
| super | trait | true | type | typeof |
|
||||
| unsafe | unsized | use | virtual | where |
|
||||
| while | yield | | | |
|
||||
|
||||
|
||||
Each of these keywords has special meaning in its grammar, and all of them are
|
||||
@ -524,6 +524,15 @@ array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ;
|
||||
idx_expr : expr '[' expr ']' ;
|
||||
```
|
||||
|
||||
### Range expressions
|
||||
|
||||
```antlr
|
||||
range_expr : expr ".." expr |
|
||||
expr ".." |
|
||||
".." expr |
|
||||
".." ;
|
||||
```
|
||||
|
||||
### Unary operator expressions
|
||||
|
||||
**FIXME:** grammar?
|
||||
@ -610,7 +619,7 @@ lambda_expr : '|' ident_list '|' expr ;
|
||||
### While loops
|
||||
|
||||
```antlr
|
||||
while_expr : "while" no_struct_literal_expr '{' block '}' ;
|
||||
while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ;
|
||||
```
|
||||
|
||||
### Infinite loops
|
||||
@ -634,7 +643,7 @@ continue_expr : "continue" [ lifetime ];
|
||||
### For expressions
|
||||
|
||||
```antlr
|
||||
for_expr : "for" pat "in" no_struct_literal_expr '{' block '}' ;
|
||||
for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ;
|
||||
```
|
||||
|
||||
### If expressions
|
||||
|
@ -29,41 +29,6 @@ You may also be interested in the [grammar].
|
||||
|
||||
# Notation
|
||||
|
||||
Rust's grammar is defined over Unicode code points, each conventionally denoted
|
||||
`U+XXXX`, for 4 or more hexadecimal digits `X`. _Most_ of Rust's grammar is
|
||||
confined to the ASCII range of Unicode, and is described in this document by a
|
||||
dialect of Extended Backus-Naur Form (EBNF), specifically a dialect of EBNF
|
||||
supported by common automated LL(k) parsing tools such as `llgen`, rather than
|
||||
the dialect given in ISO 14977. The dialect can be defined self-referentially
|
||||
as follows:
|
||||
|
||||
```{.ebnf .notation}
|
||||
grammar : rule + ;
|
||||
rule : nonterminal ':' productionrule ';' ;
|
||||
productionrule : production [ '|' production ] * ;
|
||||
production : term * ;
|
||||
term : element repeats ;
|
||||
element : LITERAL | IDENTIFIER | '[' productionrule ']' ;
|
||||
repeats : [ '*' | '+' ] NUMBER ? | NUMBER ? | '?' ;
|
||||
```
|
||||
|
||||
Where:
|
||||
|
||||
- Whitespace in the grammar is ignored.
|
||||
- Square brackets are used to group rules.
|
||||
- `LITERAL` is a single printable ASCII character, or an escaped hexadecimal
|
||||
ASCII code of the form `\xQQ`, in single quotes, denoting the corresponding
|
||||
Unicode code point `U+00QQ`.
|
||||
- `IDENTIFIER` is a nonempty string of ASCII letters and underscores.
|
||||
- The `repeat` forms apply to the adjacent `element`, and are as follows:
|
||||
- `?` means zero or one repetition
|
||||
- `*` means zero or more repetitions
|
||||
- `+` means one or more repetitions
|
||||
- NUMBER trailing a repeat symbol gives a maximum repetition count
|
||||
- NUMBER on its own gives an exact repetition count
|
||||
|
||||
This EBNF dialect should hopefully be familiar to many readers.
|
||||
|
||||
## Unicode productions
|
||||
|
||||
A few productions in Rust's grammar permit Unicode code points outside the ASCII
|
||||
@ -132,13 +97,6 @@ Some productions are defined by exclusion of particular Unicode characters:
|
||||
|
||||
## Comments
|
||||
|
||||
```{.ebnf .gram}
|
||||
comment : block_comment | line_comment ;
|
||||
block_comment : "/*" block_comment_body * "*/" ;
|
||||
block_comment_body : [block_comment | character] * ;
|
||||
line_comment : "//" non_eol * ;
|
||||
```
|
||||
|
||||
Comments in Rust code follow the general C++ style of line and block-comment
|
||||
forms. Nested block comments are supported.
|
||||
|
||||
@ -159,11 +117,6 @@ Non-doc comments are interpreted as a form of whitespace.
|
||||
|
||||
## Whitespace
|
||||
|
||||
```{.ebnf .gram}
|
||||
whitespace_char : '\x20' | '\x09' | '\x0a' | '\x0d' ;
|
||||
whitespace : [ whitespace_char | comment ] + ;
|
||||
```
|
||||
|
||||
The `whitespace_char` production is any nonempty Unicode string consisting of
|
||||
any of the following Unicode characters: `U+0020` (space, `' '`), `U+0009`
|
||||
(tab, `'\t'`), `U+000A` (LF, `'\n'`), `U+000D` (CR, `'\r'`).
|
||||
@ -176,41 +129,11 @@ with any other legal whitespace element, such as a single space character.
|
||||
|
||||
## Tokens
|
||||
|
||||
```{.ebnf .gram}
|
||||
simple_token : keyword | unop | binop ;
|
||||
token : simple_token | ident | literal | symbol | whitespace token ;
|
||||
```
|
||||
|
||||
Tokens are primitive productions in the grammar defined by regular
|
||||
(non-recursive) languages. "Simple" tokens are given in [string table
|
||||
production](#string-table-productions) form, and occur in the rest of the
|
||||
grammar as double-quoted strings. Other tokens have exact rules given.
|
||||
|
||||
### Keywords
|
||||
|
||||
<p id="keyword-table-marker"></p>
|
||||
|
||||
| | | | | |
|
||||
|----------|----------|----------|----------|---------|
|
||||
| abstract | alignof | as | become | box |
|
||||
| break | const | continue | crate | do |
|
||||
| else | enum | extern | false | final |
|
||||
| fn | for | if | impl | in |
|
||||
| let | loop | macro | match | mod |
|
||||
| move | mut | offsetof | override | priv |
|
||||
| proc | pub | pure | ref | return |
|
||||
| Self | self | sizeof | static | struct |
|
||||
| super | trait | true | type | typeof |
|
||||
| unsafe | unsized | use | virtual | where |
|
||||
| while | yield | | | |
|
||||
|
||||
|
||||
Each of these keywords has special meaning in its grammar, and all of them are
|
||||
excluded from the `ident` rule.
|
||||
|
||||
Note that some of these keywords are reserved, and do not currently do
|
||||
anything.
|
||||
|
||||
### Literals
|
||||
|
||||
A literal is an expression consisting of a single token, rather than a sequence
|
||||
@ -218,11 +141,6 @@ of tokens, that immediately and directly denotes the value it evaluates to,
|
||||
rather than referring to it by name or some other evaluation rule. A literal is
|
||||
a form of constant expression, so is evaluated (primarily) at compile time.
|
||||
|
||||
```{.ebnf .gram}
|
||||
lit_suffix : ident;
|
||||
literal : [ string_lit | char_lit | byte_string_lit | byte_lit | num_lit ] lit_suffix ?;
|
||||
```
|
||||
|
||||
The optional suffix is only used for certain numeric literals, but is
|
||||
reserved for future extension, that is, the above gives the lexical
|
||||
grammar, but a Rust parser will reject everything but the 12 special
|
||||
@ -275,32 +193,6 @@ cases mentioned in [Number literals](#number-literals) below.
|
||||
|
||||
#### Character and string literals
|
||||
|
||||
```{.ebnf .gram}
|
||||
char_lit : '\x27' char_body '\x27' ;
|
||||
string_lit : '"' string_body * '"' | 'r' raw_string ;
|
||||
|
||||
char_body : non_single_quote
|
||||
| '\x5c' [ '\x27' | common_escape | unicode_escape ] ;
|
||||
|
||||
string_body : non_double_quote
|
||||
| '\x5c' [ '\x22' | common_escape | unicode_escape ] ;
|
||||
raw_string : '"' raw_string_body '"' | '#' raw_string '#' ;
|
||||
|
||||
common_escape : '\x5c'
|
||||
| 'n' | 'r' | 't' | '0'
|
||||
| 'x' hex_digit 2
|
||||
|
||||
unicode_escape : 'u' '{' hex_digit+ 6 '}';
|
||||
|
||||
hex_digit : 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
|
||||
| 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
|
||||
| dec_digit ;
|
||||
oct_digit : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' ;
|
||||
dec_digit : '0' | nonzero_dec ;
|
||||
nonzero_dec: '1' | '2' | '3' | '4'
|
||||
| '5' | '6' | '7' | '8' | '9' ;
|
||||
```
|
||||
|
||||
##### Character literals
|
||||
|
||||
A _character literal_ is a single Unicode character enclosed within two
|
||||
@ -349,11 +241,10 @@ following forms:
|
||||
|
||||
Raw string literals do not process any escapes. They start with the character
|
||||
`U+0072` (`r`), followed by zero or more of the character `U+0023` (`#`) and a
|
||||
`U+0022` (double-quote) character. The _raw string body_ is not defined in the
|
||||
EBNF grammar above: it can contain any sequence of Unicode characters and is
|
||||
terminated only by another `U+0022` (double-quote) character, followed by the
|
||||
same number of `U+0023` (`#`) characters that preceded the opening `U+0022`
|
||||
(double-quote) character.
|
||||
`U+0022` (double-quote) character. The _raw string body_ can contain any sequence
|
||||
of Unicode characters and is terminated only by another `U+0022` (double-quote)
|
||||
character, followed by the same number of `U+0023` (`#`) characters that preceded
|
||||
the opening `U+0022` (double-quote) character.
|
||||
|
||||
All Unicode characters contained in the raw string body represent themselves,
|
||||
the characters `U+0022` (double-quote) (except when followed by at least as
|
||||
@ -375,19 +266,6 @@ r##"foo #"# bar"##; // foo #"# bar
|
||||
|
||||
#### Byte and byte string literals
|
||||
|
||||
```{.ebnf .gram}
|
||||
byte_lit : "b\x27" byte_body '\x27' ;
|
||||
byte_string_lit : "b\x22" string_body * '\x22' | "br" raw_byte_string ;
|
||||
|
||||
byte_body : ascii_non_single_quote
|
||||
| '\x5c' [ '\x27' | common_escape ] ;
|
||||
|
||||
byte_string_body : ascii_non_double_quote
|
||||
| '\x5c' [ '\x22' | common_escape ] ;
|
||||
raw_byte_string : '"' raw_byte_string_body '"' | '#' raw_byte_string '#' ;
|
||||
|
||||
```
|
||||
|
||||
##### Byte literals
|
||||
|
||||
A _byte literal_ is a single ASCII character (in the `U+0000` to `U+007F`
|
||||
@ -403,7 +281,7 @@ preceded by the characters `U+0062` (`b`) and `U+0022` (double-quote), and
|
||||
followed by the character `U+0022`. If the character `U+0022` is present within
|
||||
the literal, it must be _escaped_ by a preceding `U+005C` (`\`) character.
|
||||
Alternatively, a byte string literal can be a _raw byte string literal_, defined
|
||||
below. A byte string literal is equivalent to a `&'static [u8]` borrowed array
|
||||
below. A byte string literal of length `n` is equivalent to a `&'static [u8; n]` borrowed fixed-sized array
|
||||
of unsigned 8-bit integers.
|
||||
|
||||
Some additional _escapes_ are available in either byte or non-raw byte string
|
||||
@ -424,11 +302,10 @@ following forms:
|
||||
Raw byte string literals do not process any escapes. They start with the
|
||||
character `U+0062` (`b`), followed by `U+0072` (`r`), followed by zero or more
|
||||
of the character `U+0023` (`#`), and a `U+0022` (double-quote) character. The
|
||||
_raw string body_ is not defined in the EBNF grammar above: it can contain any
|
||||
sequence of ASCII characters and is terminated only by another `U+0022`
|
||||
(double-quote) character, followed by the same number of `U+0023` (`#`)
|
||||
characters that preceded the opening `U+0022` (double-quote) character. A raw
|
||||
byte string literal can not contain any non-ASCII byte.
|
||||
_raw string body_ can contain any sequence of ASCII characters and is terminated
|
||||
only by another `U+0022` (double-quote) character, followed by the same number of
|
||||
`U+0023` (`#`) characters that preceded the opening `U+0022` (double-quote)
|
||||
character. A raw byte string literal can not contain any non-ASCII byte.
|
||||
|
||||
All characters contained in the raw string body represent their ASCII encoding,
|
||||
the characters `U+0022` (double-quote) (except when followed by at least as
|
||||
@ -450,19 +327,6 @@ b"\\x52"; br"\x52"; // \x52
|
||||
|
||||
#### Number literals
|
||||
|
||||
```{.ebnf .gram}
|
||||
num_lit : nonzero_dec [ dec_digit | '_' ] * float_suffix ?
|
||||
| '0' [ [ dec_digit | '_' ] * float_suffix ?
|
||||
| 'b' [ '1' | '0' | '_' ] +
|
||||
| 'o' [ oct_digit | '_' ] +
|
||||
| 'x' [ hex_digit | '_' ] + ] ;
|
||||
|
||||
float_suffix : [ exponent | '.' dec_lit exponent ? ] ? ;
|
||||
|
||||
exponent : ['E' | 'e'] ['-' | '+' ] ? dec_lit ;
|
||||
dec_lit : [ dec_digit | '_' ] + ;
|
||||
```
|
||||
|
||||
A _number literal_ is either an _integer literal_ or a _floating-point
|
||||
literal_. The grammar for recognizing the two kinds of literals is mixed.
|
||||
|
||||
@ -540,12 +404,6 @@ The two values of the boolean type are written `true` and `false`.
|
||||
|
||||
### Symbols
|
||||
|
||||
```{.ebnf .gram}
|
||||
symbol : "::" | "->"
|
||||
| '#' | '[' | ']' | '(' | ')' | '{' | '}'
|
||||
| ',' | ';' ;
|
||||
```
|
||||
|
||||
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
|
||||
@ -555,16 +413,6 @@ operators](#binary-operator-expressions), or [keywords](#keywords).
|
||||
|
||||
## Paths
|
||||
|
||||
```{.ebnf .gram}
|
||||
expr_path : [ "::" ] ident [ "::" expr_path_tail ] + ;
|
||||
expr_path_tail : '<' type_expr [ ',' type_expr ] + '>'
|
||||
| expr_path ;
|
||||
|
||||
type_path : ident [ type_path_tail ] + ;
|
||||
type_path_tail : '<' type_expr [ ',' type_expr ] + '>'
|
||||
| "::" type_path ;
|
||||
```
|
||||
|
||||
A _path_ is a sequence of one or more path components _logically_ separated by
|
||||
a namespace qualifier (`::`). If a path consists of only one component, it may
|
||||
refer to either an [item](#items) or a [variable](#variables) in a local control
|
||||
@ -660,19 +508,6 @@ Users of `rustc` can define new syntax extensions in two ways:
|
||||
|
||||
## Macros
|
||||
|
||||
```{.ebnf .gram}
|
||||
expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ;
|
||||
macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';' ;
|
||||
matcher : '(' matcher * ')' | '[' matcher * ']'
|
||||
| '{' matcher * '}' | '$' ident ':' ident
|
||||
| '$' '(' matcher * ')' sep_token? [ '*' | '+' ]
|
||||
| non_special_token ;
|
||||
transcriber : '(' transcriber * ')' | '[' transcriber * ']'
|
||||
| '{' transcriber * '}' | '$' ident
|
||||
| '$' '(' transcriber * ')' sep_token? [ '*' | '+' ]
|
||||
| non_special_token ;
|
||||
```
|
||||
|
||||
`macro_rules` allows users to define syntax extension in a declarative way. We
|
||||
call such extensions "macros by example" or simply "macros" — to be distinguished
|
||||
from the "procedural macros" defined in [compiler plugins][plugin].
|
||||
@ -811,12 +646,6 @@ Crates contain [items](#items), each of which may have some number of
|
||||
|
||||
## Items
|
||||
|
||||
```{.ebnf .gram}
|
||||
item : extern_crate_decl | use_decl | mod_item | fn_item | type_item
|
||||
| struct_item | enum_item | static_item | trait_item | impl_item
|
||||
| extern_block ;
|
||||
```
|
||||
|
||||
An _item_ is a component of a crate. Items are organized within a crate by a
|
||||
nested set of [modules](#modules). Every crate has a single "outermost"
|
||||
anonymous module; all further items within the crate have [paths](#paths)
|
||||
@ -863,11 +692,6 @@ no notion of type abstraction: there are no first-class "forall" types.
|
||||
|
||||
### Modules
|
||||
|
||||
```{.ebnf .gram}
|
||||
mod_item : "mod" ident ( ';' | '{' mod '}' );
|
||||
mod : item * ;
|
||||
```
|
||||
|
||||
A module is a container for zero or more [items](#items).
|
||||
|
||||
A _module item_ is a module, surrounded in braces, named, and prefixed with the
|
||||
@ -928,11 +752,6 @@ mod thread {
|
||||
|
||||
##### Extern crate declarations
|
||||
|
||||
```{.ebnf .gram}
|
||||
extern_crate_decl : "extern" "crate" crate_name
|
||||
crate_name: ident | ( string_lit "as" ident )
|
||||
```
|
||||
|
||||
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`.
|
||||
@ -958,17 +777,6 @@ extern crate std as ruststd; // linking to 'std' under another name
|
||||
|
||||
##### Use declarations
|
||||
|
||||
```{.ebnf .gram}
|
||||
use_decl : "pub" ? "use" [ path "as" ident
|
||||
| path_glob ] ;
|
||||
|
||||
path_glob : ident [ "::" [ path_glob
|
||||
| '*' ] ] ?
|
||||
| '{' path_item [ ',' path_item ] * '}' ;
|
||||
|
||||
path_item : ident | "self" ;
|
||||
```
|
||||
|
||||
A _use declaration_ creates one or more local name bindings synonymous with
|
||||
some other [path](#paths). Usually a `use` declaration is used to shorten the
|
||||
path required to refer to a module item. These declarations may appear at the
|
||||
@ -1413,10 +1221,6 @@ it were `Bar(i32)`, this is disallowed.
|
||||
|
||||
### Constant items
|
||||
|
||||
```{.ebnf .gram}
|
||||
const_item : "const" ident ':' type '=' expr ';' ;
|
||||
```
|
||||
|
||||
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
|
||||
@ -1453,10 +1257,6 @@ const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
|
||||
|
||||
### Static items
|
||||
|
||||
```{.ebnf .gram}
|
||||
static_item : "static" ident ':' type '=' expr ';' ;
|
||||
```
|
||||
|
||||
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
|
||||
@ -1711,11 +1511,6 @@ impl Seq<bool> for u32 {
|
||||
|
||||
### External blocks
|
||||
|
||||
```{.ebnf .gram}
|
||||
extern_block_item : "extern" '{' extern_block '}' ;
|
||||
extern_block : [ foreign_fn ] * ;
|
||||
```
|
||||
|
||||
External blocks form the basis for Rust's foreign function interface.
|
||||
Declarations in an external block describe symbols in external, non-Rust
|
||||
libraries.
|
||||
@ -1915,13 +1710,6 @@ the namespace hierarchy as it normally would.
|
||||
|
||||
## Attributes
|
||||
|
||||
```{.ebnf .gram}
|
||||
attribute : '#' '!' ? '[' meta_item ']' ;
|
||||
meta_item : ident [ '=' literal
|
||||
| '(' meta_seq ')' ] ? ;
|
||||
meta_seq : meta_item [ ',' meta_seq ] ? ;
|
||||
```
|
||||
|
||||
Any item declaration may have an _attribute_ applied to it. Attributes in Rust
|
||||
are modeled on Attributes in ECMA-335, with the syntax coming from ECMA-334
|
||||
(C#). An attribute is a general, free-form metadatum that is interpreted
|
||||
@ -2503,7 +2291,7 @@ The currently implemented features of the reference compiler are:
|
||||
terms of encapsulation).
|
||||
|
||||
If a feature is promoted to a language feature, then all existing programs will
|
||||
start to receive compilation warnings about #[feature] directives which enabled
|
||||
start to receive compilation warnings about `#![feature]` directives which enabled
|
||||
the new feature (because the directive is no longer necessary). However, if a
|
||||
feature is decided to be removed from the language, errors will be issued (if
|
||||
there isn't a parser error first). The directive in this case is no longer
|
||||
@ -2554,11 +2342,6 @@ in meaning to declaring the item outside the statement block.
|
||||
|
||||
#### Variable declarations
|
||||
|
||||
```{.ebnf .gram}
|
||||
let_decl : "let" pat [':' type ] ? [ init ] ? ';' ;
|
||||
init : [ '=' ] expr ;
|
||||
```
|
||||
|
||||
A _variable declaration_ introduces a new set of variable, 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
|
||||
@ -2649,7 +2432,7 @@ parentheses. They are used to create [tuple-typed](#tuple-types) values.
|
||||
```{.tuple}
|
||||
(0,);
|
||||
(0.0, 4.5);
|
||||
("a", 4us, true);
|
||||
("a", 4usize, true);
|
||||
```
|
||||
|
||||
### Unit expressions
|
||||
@ -2659,15 +2442,6 @@ the same name.
|
||||
|
||||
### Structure expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
struct_expr : expr_path '{' ident ':' expr
|
||||
[ ',' ident ':' expr ] *
|
||||
[ ".." expr ] '}' |
|
||||
expr_path '(' expr
|
||||
[ ',' expr ] * ')' |
|
||||
expr_path ;
|
||||
```
|
||||
|
||||
There are several forms of structure expressions. A _structure expression_
|
||||
consists of the [path](#paths) of a [structure item](#structures), followed by
|
||||
a brace-enclosed list of one or more comma-separated name-value pairs,
|
||||
@ -2718,11 +2492,6 @@ Point3d {y: 0, z: 10, .. base};
|
||||
|
||||
### Block expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
block_expr : '{' [ stmt ';' | item ] *
|
||||
[ expr ] '}' ;
|
||||
```
|
||||
|
||||
A _block expression_ is similar to a module in terms of the declarations that
|
||||
are possible. Each block conceptually introduces a new namespace scope. Use
|
||||
items can bring new names into scopes and declared items are in scope for only
|
||||
@ -2745,10 +2514,6 @@ assert_eq!(5, x);
|
||||
|
||||
### Method-call expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
method_call_expr : expr '.' ident paren_expr_list ;
|
||||
```
|
||||
|
||||
A _method call_ consists of an expression followed by a single dot, an
|
||||
identifier, and a parenthesized expression-list. Method calls are resolved to
|
||||
methods on specific traits, either statically dispatching to a method if the
|
||||
@ -2757,10 +2522,6 @@ the left-hand-side expression is an indirect [trait object](#trait-objects).
|
||||
|
||||
### Field expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
field_expr : expr '.' ident ;
|
||||
```
|
||||
|
||||
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
|
||||
@ -2781,12 +2542,6 @@ automatically dereferenced to make the field access possible.
|
||||
|
||||
### Array expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
array_expr : '[' "mut" ? array_elems? ']' ;
|
||||
|
||||
array_elems : [expr [',' expr]*] | [expr ';' expr] ;
|
||||
```
|
||||
|
||||
An [array](#array,-and-slice-types) _expression_ is written by enclosing zero
|
||||
or more comma-separated expressions of uniform type in square brackets.
|
||||
|
||||
@ -2803,10 +2558,6 @@ constant expression that can be evaluated at compile time, such as a
|
||||
|
||||
### Index expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
idx_expr : expr '[' expr ']' ;
|
||||
```
|
||||
|
||||
[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
|
||||
@ -2823,13 +2574,6 @@ _panicked state_.
|
||||
|
||||
### Range expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
range_expr : expr ".." expr |
|
||||
expr ".." |
|
||||
".." expr |
|
||||
".." ;
|
||||
```
|
||||
|
||||
The `..` operator will construct an object of one of the `std::ops::Range` variants.
|
||||
|
||||
```
|
||||
@ -2872,10 +2616,6 @@ before the expression they apply to.
|
||||
|
||||
### Binary operator expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
binop_expr : expr binop expr ;
|
||||
```
|
||||
|
||||
Binary operators expressions are given in terms of [operator
|
||||
precedence](#operator-precedence).
|
||||
|
||||
@ -3036,10 +2776,6 @@ 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.
|
||||
|
||||
```{.ebnf .gram}
|
||||
paren_expr : '(' expr ')' ;
|
||||
```
|
||||
|
||||
An example of a parenthesized expression:
|
||||
|
||||
```
|
||||
@ -3049,12 +2785,6 @@ let x: i32 = (2 + 3) * 4;
|
||||
|
||||
### Call expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
expr_list : [ expr [ ',' expr ]* ] ? ;
|
||||
paren_expr_list : '(' expr_list ')' ;
|
||||
call_expr : expr paren_expr_list ;
|
||||
```
|
||||
|
||||
A _call expression_ invokes a function, providing zero or more input variables
|
||||
and an optional location to move the function's output into. If the function
|
||||
eventually returns, then the expression completes.
|
||||
@ -3070,11 +2800,6 @@ let pi: Result<f32, _> = "3.14".parse();
|
||||
|
||||
### Lambda expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
ident_list : [ ident [ ',' ident ]* ] ? ;
|
||||
lambda_expr : '|' ident_list '|' expr ;
|
||||
```
|
||||
|
||||
A _lambda expression_ (sometimes called an "anonymous function expression")
|
||||
defines a function and denotes it as a value, in a single expression. A lambda
|
||||
expression is a pipe-symbol-delimited (`|`) list of identifiers followed by an
|
||||
@ -3118,10 +2843,6 @@ ten_times(|j| println!("hello, {}", j));
|
||||
|
||||
A `loop` expression denotes an infinite loop.
|
||||
|
||||
```{.ebnf .gram}
|
||||
loop_expr : [ lifetime ':' ] "loop" '{' block '}';
|
||||
```
|
||||
|
||||
A `loop` expression may optionally have a _label_. The label is written as
|
||||
a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a
|
||||
label is present, then labeled `break` and `continue` expressions nested
|
||||
@ -3131,10 +2852,6 @@ expressions](#continue-expressions).
|
||||
|
||||
### Break expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
break_expr : "break" [ lifetime ];
|
||||
```
|
||||
|
||||
A `break` expression has an optional _label_. If the label is absent, then
|
||||
executing a `break` expression immediately terminates the innermost loop
|
||||
enclosing it. It is only permitted in the body of a loop. If the label is
|
||||
@ -3143,10 +2860,6 @@ be the innermost label enclosing the `break` expression, but must enclose it.
|
||||
|
||||
### Continue expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
continue_expr : "continue" [ lifetime ];
|
||||
```
|
||||
|
||||
A `continue` expression has an optional _label_. If the label is absent, then
|
||||
executing a `continue` expression immediately terminates the current iteration
|
||||
of the innermost loop enclosing it, returning control to the loop *head*. In
|
||||
@ -3160,10 +2873,6 @@ A `continue` expression is only permitted in the body of a loop.
|
||||
|
||||
### While loops
|
||||
|
||||
```{.ebnf .gram}
|
||||
while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ;
|
||||
```
|
||||
|
||||
A `while` loop begins by evaluating the boolean loop conditional expression.
|
||||
If the loop conditional expression evaluates to `true`, the loop body block
|
||||
executes and control returns to the loop conditional expression. If the loop
|
||||
@ -3187,26 +2896,22 @@ loops](#infinite-loops), [break expressions](#break-expressions), and
|
||||
|
||||
### For expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ;
|
||||
```
|
||||
|
||||
A `for` expression is a syntactic construct for looping over elements provided
|
||||
by an implementation of `std::iter::Iterator`.
|
||||
by an implementation of `std::iter::IntoIterator`.
|
||||
|
||||
An example of a for loop over the contents of an array:
|
||||
|
||||
```
|
||||
# type Foo = i32;
|
||||
# fn bar(f: Foo) { }
|
||||
# fn bar(f: &Foo) { }
|
||||
# let a = 0;
|
||||
# let b = 0;
|
||||
# let c = 0;
|
||||
|
||||
let v: &[Foo] = &[a, b, c];
|
||||
|
||||
for e in v.iter() {
|
||||
bar(*e);
|
||||
for e in v {
|
||||
bar(e);
|
||||
}
|
||||
```
|
||||
|
||||
@ -3226,14 +2931,6 @@ loops](#infinite-loops), [break expressions](#break-expressions), and
|
||||
|
||||
### If expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
if_expr : "if" no_struct_literal_expr '{' block '}'
|
||||
else_tail ? ;
|
||||
|
||||
else_tail : "else" [ if_expr | if_let_expr
|
||||
| '{' block '}' ] ;
|
||||
```
|
||||
|
||||
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`
|
||||
@ -3246,14 +2943,6 @@ if` condition is evaluated. If all `if` and `else if` conditions evaluate to
|
||||
|
||||
### Match expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
match_expr : "match" no_struct_literal_expr '{' match_arm * '}' ;
|
||||
|
||||
match_arm : attribute * match_pat "=>" [ expr "," | '{' block '}' ] ;
|
||||
|
||||
match_pat : pat [ '|' pat ] * [ "if" expr ] ? ;
|
||||
```
|
||||
|
||||
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,
|
||||
@ -3370,12 +3059,6 @@ let message = match maybe_digit {
|
||||
|
||||
### If let expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
if_let_expr : "if" "let" pat '=' expr '{' block '}'
|
||||
else_tail ? ;
|
||||
else_tail : "else" [ if_expr | if_let_expr | '{' block '}' ] ;
|
||||
```
|
||||
|
||||
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
|
||||
@ -3383,10 +3066,6 @@ block will execute, otherwise flow proceeds to the first `else` block that follo
|
||||
|
||||
### While let loops
|
||||
|
||||
```{.ebnf .gram}
|
||||
while_let_expr : "while" "let" pat '=' expr '{' block '}' ;
|
||||
```
|
||||
|
||||
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
|
||||
@ -3395,10 +3074,6 @@ Otherwise, the while expression completes.
|
||||
|
||||
### Return expressions
|
||||
|
||||
```{.ebnf .gram}
|
||||
return_expr : "return" expr ? ;
|
||||
```
|
||||
|
||||
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
|
||||
|
@ -36,7 +36,6 @@
|
||||
* [Strings](strings.md)
|
||||
* [Generics](generics.md)
|
||||
* [Traits](traits.md)
|
||||
* [Operators and Overloading](operators-and-overloading.md)
|
||||
* [Drop](drop.md)
|
||||
* [if let](if-let.md)
|
||||
* [Trait Objects](trait-objects.md)
|
||||
@ -50,6 +49,7 @@
|
||||
* [Casting between types](casting-between-types.md)
|
||||
* [Associated Types](associated-types.md)
|
||||
* [Unsized Types](unsized-types.md)
|
||||
* [Operators and Overloading](operators-and-overloading.md)
|
||||
* [Deref coercions](deref-coercions.md)
|
||||
* [Macros](macros.md)
|
||||
* [Raw Pointers](raw-pointers.md)
|
||||
|
@ -1,3 +1,119 @@
|
||||
% `Deref` coercions
|
||||
|
||||
Coming soon!
|
||||
The standard library provides a special trait, [`Deref`][deref]. It’s normally
|
||||
used to overload `*`, the dereference operator:
|
||||
|
||||
```rust
|
||||
use std::ops::Deref;
|
||||
|
||||
struct DerefExample<T> {
|
||||
value: T,
|
||||
}
|
||||
|
||||
impl<T> Deref for DerefExample<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = DerefExample { value: 'a' };
|
||||
assert_eq!('a', *x);
|
||||
}
|
||||
```
|
||||
|
||||
[deref]: ../std/ops/trait.Deref.html
|
||||
|
||||
This is useful for writing custom pointer types. However, there’s a language
|
||||
feature related to `Deref`: ‘deref coercions’. Here’s the rule: If you have a
|
||||
type `U`, and it implements `Deref<Target=T>`, values of `&U` will
|
||||
automatically coerce to a `&T`. Here’s an example:
|
||||
|
||||
```rust
|
||||
fn foo(s: &str) {
|
||||
// borrow a string for a second
|
||||
}
|
||||
|
||||
// String implements Deref<Target=str>
|
||||
let owned = "Hello".to_string();
|
||||
|
||||
// therefore, this works:
|
||||
foo(&owned);
|
||||
```
|
||||
|
||||
Using an ampersand in front of a value takes a reference to it. So `owned` is a
|
||||
`String`, `&owned` is an `&String`, and since `impl Deref<Target=str> for
|
||||
String`, `&String` will deref to `&str`, which `foo()` takes.
|
||||
|
||||
That’s it. This rule is one of the only places in which Rust does an automatic
|
||||
conversion for you, but it adds a lot of flexibility. For example, the `Rc<T>`
|
||||
type implements `Deref<Target=T>`, so this works:
|
||||
|
||||
```rust
|
||||
use std::rc::Rc;
|
||||
|
||||
fn foo(s: &str) {
|
||||
// borrow a string for a second
|
||||
}
|
||||
|
||||
// String implements Deref<Target=str>
|
||||
let owned = "Hello".to_string();
|
||||
let counted = Rc::new(owned);
|
||||
|
||||
// therefore, this works:
|
||||
foo(&counted);
|
||||
```
|
||||
|
||||
All we’ve done is wrap our `String` in an `Rc<T>`. But we can now pass the
|
||||
`Rc<String>` around anywhere we’d have a `String`. The signature of `foo`
|
||||
didn’t change, but works just as well with either type. This example has two
|
||||
conversions: `Rc<String>` to `String` and then `String` to `&str`. Rust will do
|
||||
this as many times as possible until the types match.
|
||||
|
||||
Another very common implementation provided by the standard library is:
|
||||
|
||||
```rust
|
||||
fn foo(s: &[i32]) {
|
||||
// borrow a slice for a second
|
||||
}
|
||||
|
||||
// Vec<T> implements Deref<Target=[T]>
|
||||
let owned = vec![1, 2, 3];
|
||||
|
||||
foo(&owned);
|
||||
```
|
||||
|
||||
Vectors can `Deref` to a slice.
|
||||
|
||||
## Deref and method calls
|
||||
|
||||
`Deref` will also kick in when calling a method. In other words, these are
|
||||
the same two things in Rust:
|
||||
|
||||
```rust
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo(&self) { println!("Foo"); }
|
||||
}
|
||||
|
||||
let f = Foo;
|
||||
|
||||
f.foo();
|
||||
```
|
||||
|
||||
Even though `f` isn’t a reference, and `foo` takes `&self`, this works.
|
||||
That’s because these things are the same:
|
||||
|
||||
```rust,ignore
|
||||
f.foo();
|
||||
(&f).foo();
|
||||
(&&f).foo();
|
||||
(&&&&&&&&f).foo();
|
||||
```
|
||||
|
||||
A value of type `&&&&&&&&&&&&&&&&Foo` can still have methods defined on `Foo`
|
||||
called, because the compiler will insert as many * operations as necessary to
|
||||
get it right. And since it’s inserting `*`s, that uses `Deref`.
|
||||
|
@ -18,7 +18,7 @@ foo.bar().baz();
|
||||
Luckily, as you may have guessed with the leading question, you can! Rust provides
|
||||
the ability to use this ‘method call syntax’ via the `impl` keyword.
|
||||
|
||||
## Method calls
|
||||
# Method calls
|
||||
|
||||
Here’s how it works:
|
||||
|
||||
@ -83,7 +83,7 @@ impl Circle {
|
||||
}
|
||||
```
|
||||
|
||||
## Chaining method calls
|
||||
# Chaining method calls
|
||||
|
||||
So, now we know how to call a method, such as `foo.bar()`. But what about our
|
||||
original example, `foo.bar().baz()`? This is called ‘method chaining’, and we
|
||||
@ -127,7 +127,7 @@ fn grow(&self) -> Circle {
|
||||
We just say we’re returning a `Circle`. With this method, we can grow a new
|
||||
circle to any arbitrary size.
|
||||
|
||||
## Static methods
|
||||
# Static methods
|
||||
|
||||
You can also define methods that do not take a `self` parameter. Here’s a
|
||||
pattern that’s very common in Rust code:
|
||||
@ -158,7 +158,7 @@ This ‘static method’ builds a new `Circle` for us. Note that static methods
|
||||
are called with the `Struct::method()` syntax, rather than the `ref.method()`
|
||||
syntax.
|
||||
|
||||
## Builder Pattern
|
||||
# Builder Pattern
|
||||
|
||||
Let’s say that we want our users to be able to create Circles, but we will
|
||||
allow them to only set the properties they care about. Otherwise, the `x`
|
||||
|
@ -1,3 +1,179 @@
|
||||
% Mutability
|
||||
|
||||
Coming Soon
|
||||
Mutability, the ability to change something, works a bit differently in Rust
|
||||
than in other languages. The first aspect of mutability is its non-default
|
||||
status:
|
||||
|
||||
```rust,ignore
|
||||
let x = 5;
|
||||
x = 6; // error!
|
||||
```
|
||||
|
||||
We can introduce mutability with the `mut` keyword:
|
||||
|
||||
```rust
|
||||
let mut x = 5;
|
||||
|
||||
x = 6; // no problem!
|
||||
```
|
||||
|
||||
This is a mutable [variable binding][vb]. When a binding is mutable, it means
|
||||
you’re allowed to change what the binding points to. So in the above example,
|
||||
it’s not so much that the value at `x` is changing, but that the binding
|
||||
changed from one `i32` to another.
|
||||
|
||||
[vb]: variable-bindings.html
|
||||
|
||||
If you want to change what the binding points to, you’ll need a [mutable reference][mr]:
|
||||
|
||||
```rust
|
||||
let mut x = 5;
|
||||
let y = &mut x;
|
||||
```
|
||||
|
||||
[mr]: references-and-borrowing.html
|
||||
|
||||
`y` is an immutable binding to a mutable reference, which means that you can’t
|
||||
bind `y` to something else (`y = &mut z`), but you can mutate the thing that’s
|
||||
bound to `y`. (`*y = 5`) A subtle distinction.
|
||||
|
||||
Of course, if you need both:
|
||||
|
||||
```rust
|
||||
let mut x = 5;
|
||||
let mut y = &mut x;
|
||||
```
|
||||
|
||||
Now `y` can be bound to another value, and the value it’s referencing can be
|
||||
changed.
|
||||
|
||||
It’s important to note that `mut` is part of a [pattern][pattern], so you
|
||||
can do things like this:
|
||||
|
||||
```rust
|
||||
let (mut x, y) = (5, 6);
|
||||
|
||||
fn foo(mut x: i32) {
|
||||
# }
|
||||
```
|
||||
|
||||
[pattern]: patterns.html
|
||||
|
||||
# Interior vs. Exterior Mutability
|
||||
|
||||
However, when we say something is ‘immutable’ in Rust, that doesn’t mean that
|
||||
it’s not able to be changed: We mean something has ‘exterior mutability’. Consider,
|
||||
for example, [`Arc<T>`][arc]:
|
||||
|
||||
```rust
|
||||
use std::sync::Arc;
|
||||
|
||||
let x = Arc::new(5);
|
||||
let y = x.clone();
|
||||
```
|
||||
|
||||
[arc]: ../std/sync/struct.Arc.html
|
||||
|
||||
When we call `clone()`, the `Arc<T>` needs to update the reference count. Yet
|
||||
we’ve not used any `mut`s here, `x` is an immutable binding, and we didn’t take
|
||||
`&mut 5` or anything. So what gives?
|
||||
|
||||
To this, we have to go back to the core of Rust’s guiding philosophy, memory
|
||||
safety, and the mechanism by which Rust guarantees it, the
|
||||
[ownership][ownership] system, and more specifically, [borrowing][borrowing]:
|
||||
|
||||
> You may have one or the other of these two kinds of borrows, but not both at
|
||||
> the same time:
|
||||
>
|
||||
> * 0 to N references (`&T`) to a resource.
|
||||
> * exactly one mutable reference (`&mut T`)
|
||||
|
||||
[ownership]: ownership.html
|
||||
[borrowing]: borrowing.html#The-Rules
|
||||
|
||||
So, that’s the real definition of ‘immutability’: is this safe to have two
|
||||
pointers to? In `Arc<T>`’s case, yes: the mutation is entirely contained inside
|
||||
the structure itself. It’s not user facing. For this reason, it hands out `&T`
|
||||
with `clone()`. If it handed out `&mut T`s, though, that would be a problem.
|
||||
|
||||
Other types, like the ones in the [`std::cell`][stdcell] module, have the
|
||||
opposite: interior mutability. For example:
|
||||
|
||||
```rust
|
||||
use std::cell::RefCell;
|
||||
|
||||
let x = RefCell::new(42);
|
||||
|
||||
let y = x.borrow_mut();
|
||||
```
|
||||
|
||||
[stdcell]: ../std/cell/index.html
|
||||
|
||||
RefCell hands out `&mut` references to what’s inside of it with the
|
||||
`borrow_mut()` method. Isn’t that dangerous? What if we do:
|
||||
|
||||
```rust,ignore
|
||||
use std::cell::RefCell;
|
||||
|
||||
let x = RefCell::new(42);
|
||||
|
||||
let y = x.borrow_mut();
|
||||
let z = x.borrow_mut();
|
||||
# (y, z);
|
||||
```
|
||||
|
||||
This will in fact panic, at runtime. This is what `RefCell` does: it enforces
|
||||
Rust’s borrowing rules at runtime, and `panic!`s if they’re violated. This
|
||||
allows us to get around another aspect of Rust’s mutability rules. Let’s talk
|
||||
about it first.
|
||||
|
||||
## Field-level mutability
|
||||
|
||||
Mutabilty is a property of either a borrow (`&mut`) or a binding (`let mut`).
|
||||
This means that, for example, you cannot have a [`struct`][struct] with
|
||||
some fields mutable and some immutable:
|
||||
|
||||
```rust,ignore
|
||||
struct Point {
|
||||
x: i32,
|
||||
mut y: i32, // nope
|
||||
}
|
||||
```
|
||||
|
||||
The mutability of a struct is in its binding:
|
||||
|
||||
```rust,ignore
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
let mut a = Point { x: 5, y: 6 };
|
||||
|
||||
a.x = 10;
|
||||
|
||||
let b = Point { x: 5, y: 6};
|
||||
|
||||
b.x = 10; // error: cannot assign to immutable field `b.x`
|
||||
```
|
||||
|
||||
[struct]: structs.html
|
||||
|
||||
However, by using `Cell<T>`, you can emulate field-level mutability:
|
||||
|
||||
```
|
||||
use std::cell::Cell;
|
||||
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: Cell<i32>,
|
||||
}
|
||||
|
||||
let mut point = Point { x: 5, y: Cell::new(6) };
|
||||
|
||||
point.y.set(7);
|
||||
|
||||
println!("y: {:?}", point.y);
|
||||
```
|
||||
|
||||
This will print `y: Cell { value: 7 }`. We’ve successfully updated `y`.
|
||||
|
@ -1,3 +1,83 @@
|
||||
% Operators and Overloading
|
||||
|
||||
Coming soon!
|
||||
Rust allows for a limited form of operator overloading. There are certain
|
||||
operators that are able to be overloaded. To support a particular operator
|
||||
between types, there’s a specific trait that you can implement, which then
|
||||
overloads the operator.
|
||||
|
||||
For example, the `+` operator can be overloaded with the `Add` trait:
|
||||
|
||||
```rust
|
||||
use std::ops::Add;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
impl Add for Point {
|
||||
type Output = Point;
|
||||
|
||||
fn add(self, other: Point) -> Point {
|
||||
Point { x: self.x + other.x, y: self.y + other.y }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let p1 = Point { x: 1, y: 0 };
|
||||
let p2 = Point { x: 2, y: 3 };
|
||||
|
||||
let p3 = p1 + p2;
|
||||
|
||||
println!("{:?}", p3);
|
||||
}
|
||||
```
|
||||
|
||||
In `main`, we can use `+` on our two `Point`s, since we’ve implemented
|
||||
`Add<Output=Point>` for `Point`.
|
||||
|
||||
There are a number of operators that can be overloaded this way, and all of
|
||||
their associated traits live in the [`std::ops`][stdops] module. Check out its
|
||||
documentation for the full list.
|
||||
|
||||
[stdops]: ../std/ops/index.html
|
||||
|
||||
Implementing these traits follows a pattern. Let’s look at [`Add`][add] in more
|
||||
detail:
|
||||
|
||||
```rust
|
||||
# mod foo {
|
||||
pub trait Add<RHS = Self> {
|
||||
type Output;
|
||||
|
||||
fn add(self, rhs: RHS) -> Self::Output;
|
||||
}
|
||||
# }
|
||||
```
|
||||
|
||||
[add]: ../std/ops/trait.Add.html
|
||||
|
||||
There’s three types in total involved here: the type you `impl Add` for, `RHS`,
|
||||
which defaults to `Self`, and `Output`. For an expression `let z = x + y`, `x`
|
||||
is the `Self` type, `y` is the RHS, and `z` is the `Self::Output` type.
|
||||
|
||||
```rust
|
||||
# struct Point;
|
||||
# use std::ops::Add;
|
||||
impl Add<i32> for Point {
|
||||
type Output = f64;
|
||||
|
||||
fn add(self, rhs: i32) -> f64 {
|
||||
// add an i32 to a Point and get an f64
|
||||
# 1.0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
will let you do this:
|
||||
|
||||
```rust,ignore
|
||||
let p: Point = // ...
|
||||
let x: f64 = p + 2i32;
|
||||
```
|
||||
|
@ -394,14 +394,71 @@
|
||||
//!
|
||||
//! ## Precision
|
||||
//!
|
||||
//! For non-numeric types, this can be considered a "maximum width". If the
|
||||
//! resulting string is longer than this width, then it is truncated down to
|
||||
//! this many characters and only those are emitted.
|
||||
//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
|
||||
//! longer than this width, then it is truncated down to this many characters and only those are
|
||||
//! emitted.
|
||||
//!
|
||||
//! For integral types, this has no meaning currently.
|
||||
//!
|
||||
//! For floating-point types, this indicates how many digits after the decimal
|
||||
//! point should be printed.
|
||||
//! For floating-point types, this indicates how many digits after the decimal point should be
|
||||
//! printed.
|
||||
//!
|
||||
//! There are three possible ways to specify the desired `precision`:
|
||||
//!
|
||||
//! There are three possible ways to specify the desired `precision`:
|
||||
//! 1. An integer `.N`,
|
||||
//! 2. an integer followed by dollar sign `.N$`, or
|
||||
//! 3. an asterisk `.*`.
|
||||
//!
|
||||
//! The first specification, `.N`, means the integer `N` itself is the precision.
|
||||
//!
|
||||
//! The second, `.N$`, means use format *argument* `N` (which must be a `usize`) as the precision.
|
||||
//!
|
||||
//! Finally, `.*` means that this `{...}` is associated with *two* format inputs rather than one:
|
||||
//! the first input holds the `usize` precision, and the second holds the value to print. Note
|
||||
//! that in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part
|
||||
//! refers to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
|
||||
//!
|
||||
//! For example, these:
|
||||
//!
|
||||
//! ```
|
||||
//! // Hello {arg 0 (x)} is {arg 1 (0.01} with precision specified inline (5)}
|
||||
//! println!("Hello {0} is {1:.5}", "x", 0.01);
|
||||
//!
|
||||
//! // Hello {arg 1 (x)} is {arg 2 (0.01} with precision specified in arg 0 (5)}
|
||||
//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
|
||||
//!
|
||||
//! // Hello {arg 0 (x)} is {arg 2 (0.01} with precision specified in arg 1 (5)}
|
||||
//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
|
||||
//!
|
||||
//! // Hello {next arg (x)} is {second of next two args (0.01} with precision
|
||||
//! // specified in first of next two args (5)}
|
||||
//! println!("Hello {} is {:.*}", "x", 5, 0.01);
|
||||
//!
|
||||
//! // Hello {next arg (x)} is {arg 2 (0.01} with precision
|
||||
//! // specified in its predecessor (5)}
|
||||
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
|
||||
//! ```
|
||||
//!
|
||||
//! All print the same thing:
|
||||
//!
|
||||
//! ```text
|
||||
//! Hello x is 0.01000
|
||||
//! ```
|
||||
//!
|
||||
//! While these:
|
||||
//!
|
||||
//! ```
|
||||
//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
|
||||
//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
|
||||
//! ```
|
||||
//!
|
||||
//! print two significantly different things:
|
||||
//!
|
||||
//! ```text
|
||||
//! Hello, `1234.560` has 3 fractional digits
|
||||
//! Hello, `123` has 3 characters
|
||||
//! ```
|
||||
//!
|
||||
//! # Escaping
|
||||
//!
|
||||
|
@ -11,7 +11,7 @@
|
||||
//! Traits for conversions between types.
|
||||
//!
|
||||
//! The traits in this module provide a general way to talk about conversions from one type to
|
||||
//! another. They follow the standard Rust conventions of `as`/`to`/`into`/`from`.
|
||||
//! another. They follow the standard Rust conventions of `as`/`into`/`from`.
|
||||
//!
|
||||
//! Like many traits, these are often used as bounds for generic functions, to support arguments of
|
||||
//! multiple types.
|
||||
|
@ -394,7 +394,7 @@ impl<'a> Context<'a> {
|
||||
are reserved for internal compiler diagnostics");
|
||||
} else if name.starts_with("derive_") {
|
||||
self.gate_feature("custom_derive", attr.span,
|
||||
"attributes of the form `#[derive_*]` are reserved
|
||||
"attributes of the form `#[derive_*]` are reserved \
|
||||
for the compiler");
|
||||
} else {
|
||||
self.gate_feature("custom_attribute", attr.span,
|
||||
@ -620,7 +620,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
|
||||
pattern.span,
|
||||
"multiple-element slice matches anywhere \
|
||||
but at the end of a slice (e.g. \
|
||||
`[0, ..xs, 0]` are experimental")
|
||||
`[0, ..xs, 0]`) are experimental")
|
||||
}
|
||||
ast::PatVec(..) => {
|
||||
self.gate_feature("slice_patterns",
|
||||
|
@ -52,7 +52,7 @@ document.addEventListener("DOMContentLoaded", function(event) {
|
||||
}
|
||||
|
||||
for (var i = 0; i < toc.length; i++) {
|
||||
if (toc[i].attributes['href'].value === href) {
|
||||
if (toc[i].attributes['href'].value.split('/').pop() === href) {
|
||||
var nav = document.createElement('p');
|
||||
if (i > 0) {
|
||||
var prevNode = toc[i-1].cloneNode(true);
|
||||
|
17
src/test/compile-fail/feature-gate-negate-unsigned.rs
Normal file
17
src/test/compile-fail/feature-gate-negate-unsigned.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that negating unsigned integers is gated by `negate_unsigned` feature
|
||||
// gate
|
||||
|
||||
const MAX: usize = -1;
|
||||
//~^ ERROR unary negation of unsigned integers may be removed in the future
|
||||
|
||||
fn main() {}
|
19
src/test/compile-fail/feature-gate-on-unimplemented.rs
Normal file
19
src/test/compile-fail/feature-gate-on-unimplemented.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that `#[rustc_on_unimplemented]` is gated by `on_unimplemented` feature
|
||||
// gate.
|
||||
|
||||
#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
|
||||
//~^ ERROR the `#[rustc_on_unimplemented]` attribute is an experimental feature
|
||||
trait Foo<Bar>
|
||||
{}
|
||||
|
||||
fn main() {}
|
@ -8,20 +8,19 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that the use of smid types in the ffi is gated by `smid_ffi` feature gate.
|
||||
// Test that default and negative trait implementations are gated by
|
||||
// `optin_builtin_traits` feature gate
|
||||
|
||||
#![feature(simd)]
|
||||
struct DummyStruct;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[simd]
|
||||
pub struct f32x4(f32, f32, f32, f32);
|
||||
|
||||
#[allow(dead_code)]
|
||||
extern {
|
||||
fn foo(x: f32x4);
|
||||
//~^ ERROR use of SIMD type `f32x4` in FFI is highly experimental and may result in invalid code
|
||||
//~| HELP add #![feature(simd_ffi)] to the crate attributes to enable
|
||||
trait DummyTrait {
|
||||
fn dummy(&self) {}
|
||||
}
|
||||
|
||||
impl DummyTrait for .. {}
|
||||
//~^ ERROR default trait implementations are experimental and possibly buggy
|
||||
|
||||
impl !DummyTrait for DummyStruct {}
|
||||
//~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
|
||||
|
||||
fn main() {}
|
16
src/test/compile-fail/feature-gate-plugin.rs
Normal file
16
src/test/compile-fail/feature-gate-plugin.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that `#![plugin(...)]` attribute is gated by `plugin` feature gate
|
||||
|
||||
#![plugin(foo)]
|
||||
//~^ ERROR compiler plugins are experimental and possibly buggy
|
||||
|
||||
fn main() {}
|
21
src/test/compile-fail/feature-gate-rustc-attrs.rs
Normal file
21
src/test/compile-fail/feature-gate-rustc-attrs.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
|
||||
|
||||
#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is an experimental feature
|
||||
#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is an experimental feature
|
||||
#[rustc_move_fragments] //~ ERROR the `#[rustc_move_fragments]` attribute is an experimental feature
|
||||
#[rustc_foo]
|
||||
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,23 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that diagnostic macros are gated by `rustc_diagnostic_macros` feature
|
||||
// gate
|
||||
|
||||
__register_diagnostic!(E0001);
|
||||
//~^ ERROR macro undefined: '__register_diagnostic!'
|
||||
|
||||
fn main() {
|
||||
__diagnostic_used!(E0001);
|
||||
//~^ ERROR macro undefined: '__diagnostic_used!'
|
||||
}
|
||||
|
||||
__build_diagnostic_array!(DIAGNOSTICS);
|
||||
//~^ ERROR macro undefined: '__build_diagnostic_array!'
|
@ -8,14 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that patterns including the box syntax are gated by `box_patterns` feature gate.
|
||||
// Test that slice pattern syntax is gated by `slice_patterns` feature gate
|
||||
|
||||
fn main() {
|
||||
let x = Box::new(1);
|
||||
|
||||
let x = [1, 2, 3, 4, 5];
|
||||
match x {
|
||||
box 1 => (),
|
||||
//~^ box pattern syntax is experimental
|
||||
_ => ()
|
||||
};
|
||||
[1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user