Merge branch 'master' of https://github.com/rust-lang/rust into readdir
This commit is contained in:
commit
b3ee2490c2
196 changed files with 7057 additions and 5348 deletions
221
src/Cargo.lock
generated
221
src/Cargo.lock
generated
|
|
@ -8,10 +8,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.5.3"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -63,13 +63,13 @@ name = "bootstrap"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ dependencies = [
|
|||
name = "build-manifest"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
|
@ -94,22 +94,22 @@ version = "0.1.0"
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.19.3"
|
||||
version = "2.20.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term_size 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term_size 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.18"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -139,20 +139,33 @@ dependencies = [
|
|||
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -164,7 +177,7 @@ name = "filetime"
|
|||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -199,17 +212,23 @@ version = "0.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "handlebars"
|
||||
version = "0.20.5"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
|
|
@ -221,7 +240,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.1.16"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
|
@ -233,7 +252,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.17"
|
||||
version = "0.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
|
@ -251,33 +270,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.0.14"
|
||||
version = "0.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"handlebars 0.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"handlebars 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "0.1.11"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.1.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "panic_abort"
|
||||
version = "0.0.0"
|
||||
|
|
@ -348,27 +381,27 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.1.80"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.3.9"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustbook"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mdbook 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mdbook 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -401,7 +434,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.19"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
|
@ -410,7 +443,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core 0.0.0",
|
||||
]
|
||||
|
||||
|
|
@ -553,7 +586,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core 0.0.0",
|
||||
]
|
||||
|
||||
|
|
@ -597,7 +630,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core 0.0.0",
|
||||
]
|
||||
|
||||
|
|
@ -689,7 +722,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core 0.0.0",
|
||||
]
|
||||
|
||||
|
|
@ -734,6 +767,22 @@ dependencies = [
|
|||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serialize"
|
||||
version = "0.0.0"
|
||||
|
|
@ -779,7 +828,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.5.2"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
|
@ -819,11 +868,11 @@ version = "0.0.0"
|
|||
|
||||
[[package]]
|
||||
name = "term_size"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
|
@ -844,19 +893,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thread-id"
|
||||
version = "2.0.0"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.2.7"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -868,12 +918,20 @@ name = "toml"
|
|||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "0.1.3"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
|
@ -881,9 +939,17 @@ name = "unicode-width"
|
|||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "0.1.3"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
|
@ -891,6 +957,11 @@ name = "vec_map"
|
|||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
|
|
@ -902,38 +973,48 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
|
||||
"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"
|
||||
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
|
||||
"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
|
||||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||
"checksum clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374"
|
||||
"checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283"
|
||||
"checksum clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758"
|
||||
"checksum cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a3a6805df695087e7c1bcd9a82e03ad6fb864c8e67ac41b1348229ce5b7f0407"
|
||||
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
|
||||
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
|
||||
"checksum env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99971fb1b635fe7a0ee3c4d065845bb93cca80a23b5613b5613391ece5de4144"
|
||||
"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
|
||||
"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
|
||||
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
|
||||
"checksum handlebars 0.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "07f9c1d28bcfb97143c95ed0667141677b2b5675c7ba3d5b81459ad43b1073bd"
|
||||
"checksum handlebars 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b930077f1422bf853008047b55896efc1409744bfc9903f1eec1a58fcc7edeff"
|
||||
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
|
||||
"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
|
||||
"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
|
||||
"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
|
||||
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
|
||||
"checksum mdbook 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a629cd0194bbd0340a70db83a94b27cf9881fac8c55e6a2db983addcb7114ee4"
|
||||
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
|
||||
"checksum mdbook 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "14e8a6aca534ac51bad1c1886b10f6d6948a14fa70b1b20a1e41c9e5c0fe3019"
|
||||
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
|
||||
"checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"
|
||||
"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
|
||||
"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
|
||||
"checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
|
||||
"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
|
||||
"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
|
||||
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
|
||||
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
|
||||
"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
|
||||
"checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c"
|
||||
"checksum term_size 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7f5f3f71b0040cecc71af239414c23fd3c73570f5ff54cf50e03cef637f2a0"
|
||||
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
|
||||
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
|
||||
"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
|
||||
"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
|
||||
"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
|
||||
"checksum serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0ed773960f90a78567fcfbe935284adf50c5d7cf119aa2cf43bb0b4afa69bb"
|
||||
"checksum serde_json 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e095e4e94e7382b76f48e93bd845ffddda62df8dfd4c163b1bfa93d40e22e13a"
|
||||
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
|
||||
"checksum term_size 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71662702fe5cd2cf95edd4ad655eea42f24a87a0e44059cbaa4e55260b7bc331"
|
||||
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
|
||||
"checksum thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7793b722f0f77ce716e7f1acf416359ca32ff24d04ffbac4269f44a4a83be05d"
|
||||
"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
|
||||
"checksum unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3bc443ded17b11305ffffe6b37e2076f328a5a8cb6aa877b1b98f77699e98b5"
|
||||
"checksum toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08272367dd2e766db3fa38f068067d17aa6a9dfd7259af24b3927db92f1e0c2f"
|
||||
"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
|
||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
|
||||
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
|
||||
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||
"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
|
|
|||
|
|
@ -205,6 +205,11 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if target.contains("pc-windows-msvc") {
|
||||
cmd.arg("-Z").arg("unstable-options");
|
||||
cmd.arg("-C").arg("target-feature=+crt-static");
|
||||
}
|
||||
}
|
||||
|
||||
if verbose > 1 {
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@ class RustBuild(object):
|
|||
if not os.path.exists(tarball):
|
||||
get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
|
||||
unpack(tarball, self.bin_root(), match="rustc", verbose=self.verbose)
|
||||
self.fix_executable(self.bin_root() + "/bin/rustc")
|
||||
self.fix_executable(self.bin_root() + "/bin/rustdoc")
|
||||
with open(self.rustc_stamp(), 'w') as f:
|
||||
f.write(self.stage0_rustc_date())
|
||||
|
||||
|
|
@ -185,9 +187,63 @@ class RustBuild(object):
|
|||
if not os.path.exists(tarball):
|
||||
get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
|
||||
unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose)
|
||||
self.fix_executable(self.bin_root() + "/bin/cargo")
|
||||
with open(self.cargo_stamp(), 'w') as f:
|
||||
f.write(self.stage0_cargo_rev())
|
||||
|
||||
def fix_executable(self, fname):
|
||||
# If we're on NixOS we need to change the path to the dynamic loader
|
||||
|
||||
default_encoding = sys.getdefaultencoding()
|
||||
try:
|
||||
ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding)
|
||||
except (subprocess.CalledProcessError, WindowsError):
|
||||
return
|
||||
|
||||
if ostype != "Linux":
|
||||
return
|
||||
|
||||
if not os.path.exists("/etc/NIXOS"):
|
||||
return
|
||||
if os.path.exists("/lib"):
|
||||
return
|
||||
|
||||
# At this point we're pretty sure the user is running NixOS
|
||||
print("info: you seem to be running NixOS. Attempting to patch " + fname)
|
||||
|
||||
try:
|
||||
interpreter = subprocess.check_output(["patchelf", "--print-interpreter", fname])
|
||||
interpreter = interpreter.strip().decode(default_encoding)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("warning: failed to call patchelf: %s" % e)
|
||||
return
|
||||
|
||||
loader = interpreter.split("/")[-1]
|
||||
|
||||
try:
|
||||
ldd_output = subprocess.check_output(['ldd', '/run/current-system/sw/bin/sh'])
|
||||
ldd_output = ldd_output.strip().decode(default_encoding)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("warning: unable to call ldd: %s" % e)
|
||||
return
|
||||
|
||||
for line in ldd_output.splitlines():
|
||||
libname = line.split()[0]
|
||||
if libname.endswith(loader):
|
||||
loader_path = libname[:len(libname) - len(loader)]
|
||||
break
|
||||
else:
|
||||
print("warning: unable to find the path to the dynamic linker")
|
||||
return
|
||||
|
||||
correct_interpreter = loader_path + loader
|
||||
|
||||
try:
|
||||
subprocess.check_output(["patchelf", "--set-interpreter", correct_interpreter, fname])
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("warning: failed to call patchelf: %s" % e)
|
||||
return
|
||||
|
||||
def stage0_cargo_rev(self):
|
||||
return self._cargo_rev
|
||||
|
||||
|
|
|
|||
|
|
@ -115,10 +115,6 @@ pub fn standalone(build: &Build, target: &str) {
|
|||
.arg("-o").arg(&out)
|
||||
.arg(&path);
|
||||
|
||||
if filename == "reference.md" {
|
||||
cmd.arg("--html-in-header").arg(&full_toc);
|
||||
}
|
||||
|
||||
if filename == "not_found.md" {
|
||||
cmd.arg("--markdown-no-toc")
|
||||
.arg("--markdown-css")
|
||||
|
|
|
|||
|
|
@ -99,6 +99,12 @@ pub fn llvm(build: &Build, target: &str) {
|
|||
.define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
|
||||
.define("LLVM_DEFAULT_TARGET_TRIPLE", target);
|
||||
|
||||
if target.contains("msvc") {
|
||||
cfg.define("LLVM_USE_CRT_DEBUG", "MT");
|
||||
cfg.define("LLVM_USE_CRT_RELEASE", "MT");
|
||||
cfg.define("LLVM_USE_CRT_RELWITHDEBINFO", "MT");
|
||||
}
|
||||
|
||||
if target.starts_with("i686") {
|
||||
cfg.define("LLVM_BUILD_32_BITS", "ON");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -568,6 +568,15 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
|
|||
})
|
||||
.default(build.config.docs)
|
||||
.run(move |s| doc::rustbook(build, s.target, "nomicon"));
|
||||
rules.doc("doc-reference", "src/doc/reference")
|
||||
.dep(move |s| {
|
||||
s.name("tool-rustbook")
|
||||
.host(&build.config.build)
|
||||
.target(&build.config.build)
|
||||
.stage(0)
|
||||
})
|
||||
.default(build.config.docs)
|
||||
.run(move |s| doc::rustbook(build, s.target, "reference"));
|
||||
rules.doc("doc-standalone", "src/doc")
|
||||
.dep(move |s| {
|
||||
s.name("rustc")
|
||||
|
|
|
|||
|
|
@ -67,4 +67,4 @@ Rust attributes are used for a number of different things. There is a full list
|
|||
of attributes [in the reference][reference]. Currently, you are not allowed to
|
||||
create your own attributes, the Rust compiler defines them.
|
||||
|
||||
[reference]: ../reference.html#attributes
|
||||
[reference]: ../reference/attributes.html
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ most dangerous features of Rust!
|
|||
# Coercion
|
||||
|
||||
Coercion between types is implicit and has no syntax of its own, but can
|
||||
be spelled out with [`as`](#Explicit%20coercions).
|
||||
be spelled out with [`as`](#explicit-coercions).
|
||||
|
||||
Coercion occurs in `let`, `const`, and `static` statements; in
|
||||
function call arguments; in field values in struct initialization; and in a
|
||||
|
|
|
|||
|
|
@ -463,7 +463,7 @@ fn factory() -> &(Fn(i32) -> i32) {
|
|||
|
||||
Right. Because we have a reference, we need to give it a lifetime. But
|
||||
our `factory()` function takes no arguments, so
|
||||
[elision](lifetimes.html#Lifetime%20Elision) doesn’t kick in here. Then what
|
||||
[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what
|
||||
choices do we have? Try `'static`:
|
||||
|
||||
```rust,ignore
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ The advantages over a simple `fn(&str) -> u32` are:
|
|||
a way to define new literal syntax for any data type.
|
||||
|
||||
In addition to procedural macros, you can define new
|
||||
[`derive`](../reference.html#derive)-like attributes and other kinds of
|
||||
[`derive`](../reference/attributes.html#derive)-like attributes and other kinds of
|
||||
extensions. See `Registry::register_syntax_extension` and the `SyntaxExtension`
|
||||
enum. For a more involved macro example, see
|
||||
[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs).
|
||||
|
|
@ -127,7 +127,7 @@ enum. For a more involved macro example, see
|
|||
|
||||
## Tips and tricks
|
||||
|
||||
Some of the [macro debugging tips](macros.html#Debugging%20macro%20code) are applicable.
|
||||
Some of the [macro debugging tips](macros.html#debugging-macro-code) are applicable.
|
||||
|
||||
You can use `syntax::parse` to turn token trees into
|
||||
higher-level syntax elements like expressions:
|
||||
|
|
@ -165,8 +165,8 @@ quasiquote as an ordinary plugin library.
|
|||
# Lint plugins
|
||||
|
||||
Plugins can extend [Rust's lint
|
||||
infrastructure](../reference.html#lint-check-attributes) with additional checks for
|
||||
code style, safety, etc. Now let's write a plugin
|
||||
infrastructure](../reference/attributes.html#lint-check-attributes) with
|
||||
additional checks for code style, safety, etc. Now let's write a plugin
|
||||
[`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs)
|
||||
that warns about any item named `lintme`.
|
||||
|
||||
|
|
@ -244,9 +244,10 @@ mostly use the same infrastructure as lint plugins, and provide examples of how
|
|||
to access type information.
|
||||
|
||||
Lints defined by plugins are controlled by the usual [attributes and compiler
|
||||
flags](../reference.html#lint-check-attributes), e.g. `#[allow(test_lint)]` or
|
||||
`-A test-lint`. These identifiers are derived from the first argument to
|
||||
`declare_lint!`, with appropriate case and punctuation conversion.
|
||||
flags](../reference/attributes.html#lint-check-attributes), e.g.
|
||||
`#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the
|
||||
first argument to `declare_lint!`, with appropriate case and punctuation
|
||||
conversion.
|
||||
|
||||
You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`,
|
||||
including those provided by plugins loaded by `foo.rs`.
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ For sharing references across threads, Rust provides a wrapper type called
|
|||
`Arc<T>`. `Arc<T>` implements `Send` and `Sync` if and only if `T` implements
|
||||
both `Send` and `Sync`. For example, an object of type `Arc<RefCell<U>>` cannot
|
||||
be transferred across threads because
|
||||
[`RefCell`](choosing-your-guarantees.html#RefCell%3CT%3E) does not implement
|
||||
[`RefCell`](choosing-your-guarantees.html#refcellt) does not implement
|
||||
`Sync`, consequently `Arc<RefCell<U>>` would not implement `Send`.
|
||||
|
||||
These two traits allow you to use the type system to make strong guarantees
|
||||
|
|
@ -126,7 +126,7 @@ closure only captures a _reference to `x`_. This is a problem, because the
|
|||
thread may outlive the scope of `x`, leading to a dangling pointer.
|
||||
|
||||
To fix this, we use a `move` closure as mentioned in the error message. `move`
|
||||
closures are explained in depth [here](closures.html#move%20closures); basically
|
||||
closures are explained in depth [here](closures.html#move-closures); basically
|
||||
they move variables from their environment into themselves.
|
||||
|
||||
```rust
|
||||
|
|
|
|||
|
|
@ -21,35 +21,35 @@ sum types and combinators, and try to motivate the way Rust does error handling
|
|||
incrementally. As such, programmers with experience in other expressive type
|
||||
systems may want to jump around.
|
||||
|
||||
* [The Basics](#The%20Basics)
|
||||
* [Unwrapping explained](#Unwrapping%20explained)
|
||||
* [The `Option` type](#The%20Option%20type)
|
||||
* [Composing `Option<T>` values](#Composing%20Option%3CT%3E%20values)
|
||||
* [The `Result` type](#The%20Result%20type)
|
||||
* [Parsing integers](#Parsing%20integers)
|
||||
* [The `Result` type alias idiom](#The%20Result%20type%20alias%20idiom)
|
||||
* [A brief interlude: unwrapping isn't evil](#A%20brief%20interlude:%20unwrapping%20isnt%20evil)
|
||||
* [Working with multiple error types](#Working%20with%20multiple%20error%20types)
|
||||
* [Composing `Option` and `Result`](#Composing%20Option%20and%20Result)
|
||||
* [The limits of combinators](#The%20limits%20of%20combinators)
|
||||
* [Early returns](#Early%20returns)
|
||||
* [The `try!` macro](#The%20try%20macro)
|
||||
* [Defining your own error type](#Defining%20your%20own%20error%20type)
|
||||
* [Standard library traits used for error handling](#Standard%20library%20traits%20used%20for%20error%20handling)
|
||||
* [The `Error` trait](#The%20Error%20trait)
|
||||
* [The `From` trait](#The%20From%20trait)
|
||||
* [The real `try!` macro](#The%20real%20try%20macro)
|
||||
* [Composing custom error types](#Composing%20custom%20error%20types)
|
||||
* [Advice for library writers](#Advice%20for%20library%20writers)
|
||||
* [Case study: A program to read population data](#Case%20study:%20A%20program%20to%20read%20population%20data)
|
||||
* [Initial setup](#Initial%20setup)
|
||||
* [Argument parsing](#Argument%20parsing)
|
||||
* [Writing the logic](#Writing%20the%20logic)
|
||||
* [Error handling with `Box<Error>`](#Error%20handling%20with%20Box%3CError%3E)
|
||||
* [Reading from stdin](#Reading%20from%20stdin)
|
||||
* [Error handling with a custom type](#Error%20handling%20with%20a%20custom%20type)
|
||||
* [Adding functionality](#Adding%20functionality)
|
||||
* [The short story](#The%20short%20story)
|
||||
* [The Basics](#the-basics)
|
||||
* [Unwrapping explained](#unwrapping-explained)
|
||||
* [The `Option` type](#the-option-type)
|
||||
* [Composing `Option<T>` values](#composing-optiont-values)
|
||||
* [The `Result` type](#the-result-type)
|
||||
* [Parsing integers](#parsing-integers)
|
||||
* [The `Result` type alias idiom](#the-result-type-alias-idiom)
|
||||
* [A brief interlude: unwrapping isn't evil](#a-brief-interlude-unwrapping-isnt-evil)
|
||||
* [Working with multiple error types](#working-with-multiple-error-types)
|
||||
* [Composing `Option` and `Result`](#composing-option-and-result)
|
||||
* [The limits of combinators](#the-limits-of-combinators)
|
||||
* [Early returns](#early-returns)
|
||||
* [The `try!` macro](#the-try-macro)
|
||||
* [Defining your own error type](#defining-your-own-error-type)
|
||||
* [Standard library traits used for error handling](#standard-library-traits-used-for-error-handling)
|
||||
* [The `Error` trait](#the-error-trait)
|
||||
* [The `From` trait](#the-from-trait)
|
||||
* [The real `try!` macro](#the-real-try-macro)
|
||||
* [Composing custom error types](#composing-custom-error-types)
|
||||
* [Advice for library writers](#advice-for-library-writers)
|
||||
* [Case study: A program to read population data](#case-study-a-program-to-read-population-data)
|
||||
* [Initial setup](#initial-setup)
|
||||
* [Argument parsing](#argument-parsing)
|
||||
* [Writing the logic](#writing-the-logic)
|
||||
* [Error handling with `Box<Error>`](#error-handling-with-boxerror)
|
||||
* [Reading from stdin](#reading-from-stdin)
|
||||
* [Error handling with a custom type](#error-handling-with-a-custom-type)
|
||||
* [Adding functionality](#adding-functionality)
|
||||
* [The short story](#the-short-story)
|
||||
|
||||
# The Basics
|
||||
|
||||
|
|
@ -796,7 +796,7 @@ because of the return types of
|
|||
[`std::fs::File::open`](../std/fs/struct.File.html#method.open) and
|
||||
[`std::io::Read::read_to_string`](../std/io/trait.Read.html#method.read_to_string).
|
||||
(Note that they both use the [`Result` type alias
|
||||
idiom](#The%20Result%20type%20alias%20idiom) described previously. If you
|
||||
idiom](#the-result-type-alias-idiom) described previously. If you
|
||||
click on the `Result` type, you'll [see the type
|
||||
alias](../std/io/type.Result.html), and consequently, the underlying
|
||||
`io::Error` type.) The third problem is described by the
|
||||
|
|
@ -1120,7 +1120,7 @@ returns an `&Error`, which is itself a trait object. We'll revisit the
|
|||
|
||||
For now, it suffices to show an example implementing the `Error` trait. Let's
|
||||
use the error type we defined in the
|
||||
[previous section](#Defining%20your%20own%20error%20type):
|
||||
[previous section](#defining-your-own-error-type):
|
||||
|
||||
```rust
|
||||
use std::io;
|
||||
|
|
@ -1493,19 +1493,19 @@ representation. But certainly, this will vary depending on use cases.
|
|||
At a minimum, you should probably implement the
|
||||
[`Error`](../std/error/trait.Error.html)
|
||||
trait. This will give users of your library some minimum flexibility for
|
||||
[composing errors](#The%20real%20try%20macro). Implementing the `Error` trait also
|
||||
[composing errors](#the-real-try-macro). Implementing the `Error` trait also
|
||||
means that users are guaranteed the ability to obtain a string representation
|
||||
of an error (because it requires impls for both `fmt::Debug` and
|
||||
`fmt::Display`).
|
||||
|
||||
Beyond that, it can also be useful to provide implementations of `From` on your
|
||||
error types. This allows you (the library author) and your users to
|
||||
[compose more detailed errors](#Composing%20custom%20error%20types). For example,
|
||||
[compose more detailed errors](#composing-custom-error-types). For example,
|
||||
[`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html)
|
||||
provides `From` impls for both `io::Error` and `byteorder::Error`.
|
||||
|
||||
Finally, depending on your tastes, you may also want to define a
|
||||
[`Result` type alias](#The%20Result%20type%20alias%20idiom), particularly if your
|
||||
[`Result` type alias](#the-result-type-alias-idiom), particularly if your
|
||||
library defines a single error type. This is used in the standard library
|
||||
for [`io::Result`](../std/io/type.Result.html)
|
||||
and [`fmt::Result`](../std/fmt/type.Result.html).
|
||||
|
|
@ -1538,7 +1538,7 @@ and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.
|
|||
|
||||
We're not going to spend a lot of time on setting up a project with
|
||||
Cargo because it is already covered well in [the Cargo
|
||||
section](getting-started.html#Hello%20Cargo) and [Cargo's documentation][14].
|
||||
section](getting-started.html#hello-cargo) and [Cargo's documentation][14].
|
||||
|
||||
To get started from scratch, run `cargo new --bin city-pop` and make sure your
|
||||
`Cargo.toml` looks something like this:
|
||||
|
|
@ -1729,7 +1729,7 @@ error types and you don't need any `From` implementations. The downside is that
|
|||
since `Box<Error>` is a trait object, it *erases the type*, which means the
|
||||
compiler can no longer reason about its underlying type.
|
||||
|
||||
[Previously](#The%20limits%20of%20combinators) we started refactoring our code by
|
||||
[Previously](#the-limits-of-combinators) we started refactoring our code by
|
||||
changing the type of our function from `T` to `Result<T, OurErrorType>`. In
|
||||
this case, `OurErrorType` is only `Box<Error>`. But what's `T`? And can we add
|
||||
a return type to `main`?
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@ pub extern fn hello_rust() -> *const u8 {
|
|||
|
||||
The `extern` makes this function adhere to the C calling convention, as
|
||||
discussed above in "[Foreign Calling
|
||||
Conventions](ffi.html#Foreign%20calling%20conventions)". The `no_mangle`
|
||||
Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle`
|
||||
attribute turns off Rust's name mangling, so that it is easier to link to.
|
||||
|
||||
# FFI and panics
|
||||
|
|
|
|||
|
|
@ -140,5 +140,51 @@ container types like [`Vec<T>`][Vec]. On the other hand, often you want to
|
|||
trade that flexibility for increased expressive power. Read about [trait
|
||||
bounds][traits] to see why and how.
|
||||
|
||||
## Resolving ambiguities
|
||||
|
||||
Most of the time when generics are involved, the compiler can infer the
|
||||
generic parameters automatically:
|
||||
|
||||
```rust
|
||||
// v must be a Vec<T> but we don't know what T is yet
|
||||
let mut v = Vec::new();
|
||||
// v just got a bool value, so T must be bool!
|
||||
v.push(true);
|
||||
// Debug-print v
|
||||
println!("{:?}", v);
|
||||
```
|
||||
|
||||
Sometimes though, the compiler needs a little help. For example, had we
|
||||
omitted the last line, we would get a compile error:
|
||||
|
||||
```rust,ignore
|
||||
let v = Vec::new();
|
||||
// ^^^^^^^^ cannot infer type for `T`
|
||||
//
|
||||
// note: type annotations or generic parameter binding required
|
||||
println!("{:?}", v);
|
||||
```
|
||||
|
||||
We can solve this using either a type annotation:
|
||||
|
||||
```rust
|
||||
let v: Vec<bool> = Vec::new();
|
||||
println!("{:?}", v);
|
||||
```
|
||||
|
||||
or by binding the generic parameter `T` via the so-called
|
||||
[‘turbofish’][turbofish] `::<>` syntax:
|
||||
|
||||
```rust
|
||||
let v = Vec::<bool>::new();
|
||||
println!("{:?}", v);
|
||||
```
|
||||
|
||||
The second approach is useful in situations where we don’t want to bind the
|
||||
result to a variable. It can also be used to bind generic parameters in
|
||||
functions or methods. See [Iterators § Consumers](iterators.html#consumers)
|
||||
for an example.
|
||||
|
||||
[traits]: traits.html
|
||||
[Vec]: ../std/vec/struct.Vec.html
|
||||
[turbofish]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ language]*, which means that most things are expressions, rather than
|
|||
statements. The `;` indicates that this expression is over, and the next one is
|
||||
ready to begin. Most lines of Rust code end with a `;`.
|
||||
|
||||
[expression-oriented language]: glossary.html#Expression-Oriented%20Language
|
||||
[expression-oriented language]: glossary.html#expression-oriented-language
|
||||
|
||||
## Compiling and Running Are Separate Steps
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ They can be used to manage control flow in a modular fashion.
|
|||
|
||||
A type without a statically known size or alignment. ([more info][link])
|
||||
|
||||
[link]: ../nomicon/exotic-sizes.html#Dynamically%20Sized%20Types%20(DSTs)
|
||||
[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-dsts
|
||||
|
||||
### Expression
|
||||
|
||||
|
|
@ -76,8 +76,8 @@ In an expression-oriented language, (nearly) every statement is an expression
|
|||
and therefore returns a value. Consequently, these expression statements can
|
||||
themselves form part of larger expressions.
|
||||
|
||||
[expression]: glossary.html#Expression
|
||||
[statement]: glossary.html#Statement
|
||||
[expression]: glossary.html#expression
|
||||
[statement]: glossary.html#statement
|
||||
|
||||
### Statement
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ there are no arguments, and `{` starts the body of the function. Because
|
|||
we didn’t include a return type, it’s assumed to be `()`, an empty
|
||||
[tuple][tuples].
|
||||
|
||||
[tuples]: primitive-types.html#Tuples
|
||||
[tuples]: primitive-types.html#tuples
|
||||
|
||||
```rust,ignore
|
||||
println!("Guess the number!");
|
||||
|
|
@ -727,7 +727,7 @@ thirty-two bit integer. Rust has [a number of built-in number types][number],
|
|||
but we’ve chosen `u32`. It’s a good default choice for a small positive number.
|
||||
|
||||
[parse]: ../std/primitive.str.html#method.parse
|
||||
[number]: primitive-types.html#Numeric%20types
|
||||
[number]: primitive-types.html#numeric-types
|
||||
|
||||
Just like `read_line()`, our call to `parse()` could cause an error. What if
|
||||
our string contained `A👍%`? There’d be no way to convert that to a number. As
|
||||
|
|
|
|||
|
|
@ -135,10 +135,10 @@ Here's the version that does compile:
|
|||
let one_to_one_hundred = (1..101).collect::<Vec<i32>>();
|
||||
```
|
||||
|
||||
If you remember, the `::<>` syntax allows us to give a type hint,
|
||||
and so we tell it that we want a vector of integers. You don't always
|
||||
need to use the whole type, though. Using a `_` will let you provide
|
||||
a partial hint:
|
||||
If you remember, the [`::<>` syntax](generics.html#resolving-ambiguities)
|
||||
allows us to give a type hint that tells the compiler we want a vector of
|
||||
integers. You don't always need to use the whole type, though. Using a `_`
|
||||
will let you provide a partial hint:
|
||||
|
||||
```rust
|
||||
let one_to_one_hundred = (1..101).collect::<Vec<_>>();
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ associated with it, but the compiler lets you elide (i.e. omit, see
|
|||
["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we
|
||||
get to that, though, let’s look at a short example with explicit lifetimes:
|
||||
|
||||
[lifetime-elision]: #Lifetime%20Elision
|
||||
[lifetime-elision]: #lifetime-elision
|
||||
|
||||
```rust,ignore
|
||||
fn bar<'a>(...)
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ trees, at compile time. The semicolon is optional on the last (here, only)
|
|||
case. The "pattern" on the left-hand side of `=>` is known as a ‘matcher’.
|
||||
These have [their own little grammar] within the language.
|
||||
|
||||
[their own little grammar]: ../reference.html#macros
|
||||
[their own little grammar]: ../reference/macros.html
|
||||
|
||||
The matcher `$x:expr` will match any Rust expression, binding that syntax tree
|
||||
to the ‘metavariable’ `$x`. The identifier `expr` is a ‘fragment specifier’;
|
||||
|
|
@ -363,7 +363,7 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
[items]: ../reference.html#items
|
||||
[items]: ../reference/items.html
|
||||
|
||||
# Recursive macros
|
||||
|
||||
|
|
@ -430,7 +430,7 @@ Even when Rust code contains un-expanded macros, it can be parsed as a full
|
|||
tools that process code. It also has a few consequences for the design of
|
||||
Rust’s macro system.
|
||||
|
||||
[ast]: glossary.html#Abstract%20Syntax%20Tree
|
||||
[ast]: glossary.html#abstract-syntax-tree
|
||||
|
||||
One consequence is that Rust must determine, when it parses a macro invocation,
|
||||
whether the macro stands in for
|
||||
|
|
@ -490,7 +490,7 @@ be forced to choose between parsing `$i` and parsing `$e`. Changing the
|
|||
invocation syntax to put a distinctive token in front can solve the problem. In
|
||||
this case, you can write `$(I $i:ident)* E $e:expr`.
|
||||
|
||||
[item]: ../reference.html#items
|
||||
[item]: ../reference/items.html
|
||||
|
||||
# Scoping and macro import/export
|
||||
|
||||
|
|
@ -565,7 +565,7 @@ When this library is loaded with `#[macro_use] extern crate`, only `m2` will
|
|||
be imported.
|
||||
|
||||
The Rust Reference has a [listing of macro-related
|
||||
attributes](../reference.html#macro-related-attributes).
|
||||
attributes](../reference/attributes.html#macro-related-attributes).
|
||||
|
||||
# The variable `$crate`
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ philosophy, memory safety, and the mechanism by which Rust guarantees it, the
|
|||
> * exactly one mutable reference (`&mut T`).
|
||||
|
||||
[ownership]: ownership.html
|
||||
[borrowing]: references-and-borrowing.html#Borrowing
|
||||
[borrowing]: references-and-borrowing.html#borrowing
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -65,10 +65,10 @@ elements onto them.
|
|||
Vectors have a [generic type][generics] `Vec<T>`, so in this example `v` will have type
|
||||
`Vec<i32>`. We'll cover [generics] in detail in a later chapter.
|
||||
|
||||
[arrays]: primitive-types.html#Arrays
|
||||
[arrays]: primitive-types.html#arrays
|
||||
[vectors]: vectors.html
|
||||
[heap]: the-stack-and-the-heap.html#The%20Heap
|
||||
[stack]: the-stack-and-the-heap.html#The%20Stack
|
||||
[heap]: the-stack-and-the-heap.html#the-heap
|
||||
[stack]: the-stack-and-the-heap.html#the-stack
|
||||
[bindings]: variable-bindings.html
|
||||
[generics]: generics.html
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit
|
|||
pattern representing the value of 10 to the allocated memory and binds the
|
||||
variable name x to this memory region for future reference.
|
||||
|
||||
[i32]: primitive-types.html#Numeric%20types
|
||||
[i32]: primitive-types.html#numeric-types
|
||||
|
||||
Now consider the following code fragment:
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ soon.
|
|||
You can assign one tuple into another, if they have the same contained types
|
||||
and [arity]. Tuples have the same arity when they have the same length.
|
||||
|
||||
[arity]: glossary.html#Arity
|
||||
[arity]: glossary.html#arity
|
||||
|
||||
```rust
|
||||
let mut x = (1, 2); // x: (i32, i32)
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ So this is where quotes comes in. The `ast` argument is a struct that gives us
|
|||
a representation of our type (which can be either a `struct` or an `enum`).
|
||||
Check out the [docs](https://docs.rs/syn/0.10.5/syn/struct.MacroInput.html),
|
||||
there is some useful information there. We are able to get the name of the
|
||||
type using `ast.ident`. The `quote!` macro let's us write up the Rust code
|
||||
type using `ast.ident`. The `quote!` macro lets us write up the Rust code
|
||||
that we wish to return and convert it into `Tokens`. `quote!` let's us use some
|
||||
really cool templating mechanics; we simply write `#name` and `quote!` will
|
||||
replace it with the variable named `name`. You can even do some repetition
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ fn main() {
|
|||
let age = 27;
|
||||
let peter = Person { name, age };
|
||||
|
||||
// Print debug struct
|
||||
// Debug-print struct
|
||||
println!("{:?}", peter);
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@
|
|||
<!-- Generics -->
|
||||
|
||||
* `path<…>` (*e.g.* `Vec<u8>`): specifies parameters to generic type *in a type*. See [Generics].
|
||||
* `path::<…>`, `method::<…>` (*e.g.* `"42".parse::<i32>()`): specifies parameters to generic type, function, or method *in an expression*.
|
||||
* `path::<…>`, `method::<…>` (*e.g.* `"42".parse::<i32>()`): specifies parameters to generic type, function, or method *in an expression*. See [Generics § Resolving ambiguities](generics.html#resolving-ambiguities).
|
||||
* `fn ident<…> …`: define generic function. See [Generics].
|
||||
* `struct ident<…> …`: define generic structure. See [Generics].
|
||||
* `enum ident<…> …`: define generic enumeration. See [Generics].
|
||||
|
|
@ -196,18 +196,18 @@
|
|||
[Associated Types]: associated-types.html
|
||||
[Attributes]: attributes.html
|
||||
[Casting Between Types (`as`)]: casting-between-types.html#as
|
||||
[Closures (`move` closures)]: closures.html#move%20closures
|
||||
[Closures (`move` closures)]: closures.html#move-closures
|
||||
[Closures]: closures.html
|
||||
[Comments]: comments.html
|
||||
[Crates and Modules (Defining Modules)]: crates-and-modules.html#Defining%20modules
|
||||
[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#Exporting%20a%20public%20interface
|
||||
[Crates and Modules (Importing External Crates)]: crates-and-modules.html#Importing%20external%20crates
|
||||
[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#Importing%20modules%20with%20use
|
||||
[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#Re-exporting%20with%20pub%20use
|
||||
[Diverging Functions]: functions.html#Diverging%20functions
|
||||
[Crates and Modules (Defining Modules)]: crates-and-modules.html#defining-modules
|
||||
[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#exporting-a-public-interface
|
||||
[Crates and Modules (Importing External Crates)]: crates-and-modules.html#importing-external-crates
|
||||
[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#importing-modules-with-use
|
||||
[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#re-exporting-with-pub-use
|
||||
[Diverging Functions]: functions.html#diverging-functions
|
||||
[Enums]: enums.html
|
||||
[Foreign Function Interface]: ffi.html
|
||||
[Functions (Early Returns)]: functions.html#Early%20returns
|
||||
[Functions (Early Returns)]: functions.html#early-returns
|
||||
[Functions]: functions.html
|
||||
[Generics]: generics.html
|
||||
[Iterators]: iterators.html
|
||||
|
|
@ -216,38 +216,38 @@
|
|||
[Loops (`for`)]: loops.html#for
|
||||
[Loops (`loop`)]: loops.html#loop
|
||||
[Loops (`while`)]: loops.html#while
|
||||
[Loops (Ending Iteration Early)]: loops.html#Ending%20iteration%20early
|
||||
[Loops (Loops Labels)]: loops.html#Loop%20labels
|
||||
[Loops (Ending Iteration Early)]: loops.html#ending-iteration-early
|
||||
[Loops (Loops Labels)]: loops.html#loop-labels
|
||||
[Macros]: macros.html
|
||||
[Match]: match.html
|
||||
[Method Syntax (Method Calls)]: method-syntax.html#Method%20calls
|
||||
[Method Syntax (Method Calls)]: method-syntax.html#method-calls
|
||||
[Method Syntax]: method-syntax.html
|
||||
[Mutability]: mutability.html
|
||||
[Operators and Overloading]: operators-and-overloading.html
|
||||
[Patterns (`ref` and `ref mut`)]: patterns.html#ref%20and%20ref%20mut
|
||||
[Patterns (Bindings)]: patterns.html#Bindings
|
||||
[Patterns (Ignoring bindings)]: patterns.html#Ignoring%20bindings
|
||||
[Patterns (Multiple patterns)]: patterns.html#Multiple%20patterns
|
||||
[Patterns (Ranges)]: patterns.html#Ranges
|
||||
[Patterns (`ref` and `ref mut`)]: patterns.html#ref-and-ref-mut
|
||||
[Patterns (Bindings)]: patterns.html#bindings
|
||||
[Patterns (Ignoring bindings)]: patterns.html#ignoring-bindings
|
||||
[Patterns (Multiple patterns)]: patterns.html#multiple-patterns
|
||||
[Patterns (Ranges)]: patterns.html#ranges
|
||||
[Primitive Types (`char`)]: primitive-types.html#char
|
||||
[Primitive Types (Arrays)]: primitive-types.html#Arrays
|
||||
[Primitive Types (Booleans)]: primitive-types.html#Booleans
|
||||
[Primitive Types (Tuple Indexing)]: primitive-types.html#Tuple%20indexing
|
||||
[Primitive Types (Tuples)]: primitive-types.html#Tuples
|
||||
[Primitive Types (Arrays)]: primitive-types.html#arrays
|
||||
[Primitive Types (Booleans)]: primitive-types.html#booleans
|
||||
[Primitive Types (Tuple Indexing)]: primitive-types.html#tuple-indexing
|
||||
[Primitive Types (Tuples)]: primitive-types.html#tuples
|
||||
[Raw Pointers]: raw-pointers.html
|
||||
[Reference (Byte String Literals)]: ../reference.html#byte-string-literals
|
||||
[Reference (Integer literals)]: ../reference.html#integer-literals
|
||||
[Reference (Raw Byte String Literals)]: ../reference.html#raw-byte-string-literals
|
||||
[Reference (Raw String Literals)]: ../reference.html#raw-string-literals
|
||||
[Reference (Byte String Literals)]: ../reference/tokens.html/#byte-string-literals
|
||||
[Reference (Integer literals)]: ../reference/tokens.html#integer-literals
|
||||
[Reference (Raw Byte String Literals)]: ../reference/tokens.html#raw-byte-string-literals
|
||||
[Reference (Raw String Literals)]: ../reference/tokens.html#raw-string-literals
|
||||
[References and Borrowing]: references-and-borrowing.html
|
||||
[Strings]: strings.html
|
||||
[Structs (Update syntax)]: structs.html#Update%20syntax
|
||||
[Structs (Update syntax)]: structs.html#update-syntax
|
||||
[Structs]: structs.html
|
||||
[Traits (`where` clause)]: traits.html#Where%20clause
|
||||
[Traits (Multiple Trait Bounds)]: traits.html#Multiple%20trait%20bounds
|
||||
[Traits (`where` clause)]: traits.html#where-clause
|
||||
[Traits (Multiple Trait Bounds)]: traits.html#multiple-trait-bounds
|
||||
[Traits]: traits.html
|
||||
[Universal Function Call Syntax]: ufcs.html
|
||||
[Universal Function Call Syntax (Angle-bracket Form)]: ufcs.html#Angle-bracket%20Form
|
||||
[Universal Function Call Syntax (Angle-bracket Form)]: ufcs.html#angle-bracket-form
|
||||
[Unsafe]: unsafe.html
|
||||
[Unsized Types (`?Sized`)]: unsized-types.html#Sized
|
||||
[Unsized Types (`?Sized`)]: unsized-types.html#sized
|
||||
[Variable Bindings]: variable-bindings.html
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ Traits are useful because they allow a type to make certain promises about its
|
|||
behavior. Generic functions can exploit this to constrain, or [bound][bounds], the types they
|
||||
accept. Consider this function, which does not compile:
|
||||
|
||||
[bounds]: glossary.html#Bounds
|
||||
[bounds]: glossary.html#bounds
|
||||
|
||||
```rust,ignore
|
||||
fn print_area<T>(shape: T) {
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ if x == y {
|
|||
This compiles without error. Values of a `Num` type are the same as a value of
|
||||
type `i32`, in every way. You can use [tuple struct] to really get a new type.
|
||||
|
||||
[tuple struct]: structs.html#Tuple%20structs
|
||||
[tuple struct]: structs.html#tuple-structs
|
||||
|
||||
You can also use type aliases with generics:
|
||||
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ print.
|
|||
# Scope and shadowing
|
||||
|
||||
Let’s get back to bindings. Variable bindings have a scope - they are
|
||||
constrained to live in a block they were defined in. A block is a collection
|
||||
constrained to live in the block they were defined in. A block is a collection
|
||||
of statements enclosed by `{` and `}`. Function definitions are also blocks!
|
||||
In the following example we define two variable bindings, `x` and `y`, which
|
||||
live in different blocks. `x` can be accessed from inside the `fn main() {}`
|
||||
|
|
|
|||
|
|
@ -151,6 +151,6 @@ API documentation][vec].
|
|||
[vec]: ../std/vec/index.html
|
||||
[box]: ../std/boxed/index.html
|
||||
[generic]: generics.html
|
||||
[panic]: concurrency.html#Panics
|
||||
[panic]: concurrency.html#panics
|
||||
[get]: ../std/vec/struct.Vec.html#method.get
|
||||
[get_mut]: ../std/vec/struct.Vec.html#method.get_mut
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ literal : [ string_lit | char_lit | byte_string_lit | byte_lit | num_lit | bool_
|
|||
The optional `lit_suffix` production 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 cases
|
||||
mentioned in [Number literals](reference.html#number-literals) in the
|
||||
mentioned in [Number literals](reference/tokens.html#number-literals) in the
|
||||
reference.
|
||||
|
||||
#### Character and string literals
|
||||
|
|
|
|||
|
|
@ -16,14 +16,6 @@ builds documentation for individual Rust packages.
|
|||
Rust provides a standard library with a number of features; [we host its
|
||||
documentation here][api].
|
||||
|
||||
## Reference Documentation
|
||||
|
||||
Rust does not yet have a formal specification, but we have [a reference document
|
||||
][ref]. It is guaranteed to be accurate, but not complete. We now have a
|
||||
policy that all new features must be included in the reference before
|
||||
stabilization; however, we are still back-filling things that landed before
|
||||
then. That work is being tracked [here][38643].
|
||||
|
||||
## Extended Error Documentation
|
||||
|
||||
Many of Rust's errors come with error codes, and you can request extended
|
||||
|
|
@ -37,11 +29,17 @@ nicknamed 'The Rust Bookshelf.'
|
|||
|
||||
* [The Rust Programming Language][book] teaches you how to program in Rust.
|
||||
* [The Rustonomicon][nomicon] is your guidebook to the dark arts of unsafe Rust.
|
||||
* [The Reference][ref] is not a formal spec, but is more detailed and comprehensive than the book.
|
||||
|
||||
Another few words about the reference: it is guaranteed to be accurate, but not
|
||||
complete. We now have a policy that all new features must be included in the
|
||||
reference before stabilization; however, we are still back-filling things that
|
||||
landed before then. That work is being tracked [here][38643].
|
||||
|
||||
[Rust Learning]: https://github.com/ctjhoa/rust-learning
|
||||
[Docs.rs]: https://docs.rs/
|
||||
[api]: std/index.html
|
||||
[ref]: reference.html
|
||||
[ref]: reference/index.html
|
||||
[38643]: https://github.com/rust-lang/rust/issues/38643
|
||||
[err]: error-index.html
|
||||
[book]: book/index.html
|
||||
|
|
|
|||
|
|
@ -79,17 +79,5 @@ if condition {
|
|||
}
|
||||
```
|
||||
|
||||
As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden
|
||||
field of any type that implements Drop. Rust sets the drop flag by overwriting
|
||||
the entire value with a particular bit pattern. This is pretty obviously Not
|
||||
The Fastest and causes a bunch of trouble with optimizing code. It's legacy from
|
||||
a time when you could do much more complex conditional initialization.
|
||||
|
||||
As such work is currently under way to move the flags out onto the stack frame
|
||||
where they more reasonably belong. Unfortunately, this work will take some time
|
||||
as it requires fairly substantial changes to the compiler.
|
||||
|
||||
Regardless, Rust programs don't need to worry about uninitialized values on
|
||||
the stack for correctness. Although they might care for performance. Thankfully,
|
||||
Rust makes it easy to take control here! Uninitialized values are there, and
|
||||
you can work with them in Safe Rust, but you're never in danger.
|
||||
The drop flags are tracked on the stack and no longer stashed in types that
|
||||
implement drop.
|
||||
|
|
|
|||
|
|
@ -78,4 +78,4 @@ TODO: other common problems? SEME regions stuff, mostly?
|
|||
|
||||
|
||||
|
||||
[ex2]: lifetimes.html#Example%3A%20aliasing%20a%20mutable%20reference
|
||||
[ex2]: lifetimes.html#example-aliasing-a-mutable-reference
|
||||
|
|
|
|||
|
|
@ -151,4 +151,4 @@ use fairly elaborate algorithms to cache bits throughout nested types with
|
|||
special constrained representations. As such it is *especially* desirable that
|
||||
we leave enum layout unspecified today.
|
||||
|
||||
[dst]: exotic-sizes.html#Dynamically%20Sized%20Types%20(DSTs)
|
||||
[dst]: exotic-sizes.html#dynamically-sized-types-dsts
|
||||
|
|
|
|||
4413
src/doc/reference.md
4413
src/doc/reference.md
File diff suppressed because it is too large
Load diff
1
src/doc/reference/.gitignore
vendored
Normal file
1
src/doc/reference/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
book
|
||||
58
src/doc/reference/src/SUMMARY.md
Normal file
58
src/doc/reference/src/SUMMARY.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# The Rust Reference
|
||||
|
||||
[Introduction](introduction.md)
|
||||
|
||||
- [Notation](notation.md)
|
||||
- [Unicode productions](unicode-productions.md)
|
||||
- [String table productions](string-table-productions.md)
|
||||
|
||||
- [Lexical structure](lexical-structure.md)
|
||||
- [Input format](input-format.md)
|
||||
- [Identifiers](identifiers.md)
|
||||
- [Comments](comments.md)
|
||||
- [Whitespace](whitespace.md)
|
||||
- [Tokens](tokens.md)
|
||||
- [Paths](paths.md)
|
||||
|
||||
- [Macros](macros.md)
|
||||
- [Macros By Example](macros-by-example.md)
|
||||
- [Procedrual Macros](procedural-macros.md)
|
||||
|
||||
- [Crates and source files](crates-and-source-files.md)
|
||||
|
||||
- [Items and attributes](items-and-attributes.md)
|
||||
- [Items](items.md)
|
||||
- [Visibility and Privacy](visibility-and-privacy.md)
|
||||
- [Attributes](attributes.md)
|
||||
|
||||
- [Statements and expressions](statements-and-expressions.md)
|
||||
- [Statements](statements.md)
|
||||
- [Expressions](expressions.md)
|
||||
|
||||
- [Type system](type-system.md)
|
||||
- [Types](types.md)
|
||||
- [Subtyping](subtyping.md)
|
||||
- [Type coercions](type-coercions.md)
|
||||
|
||||
- [Special traits](special-traits.md)
|
||||
- [The Copy trait](the-copy-trait.md)
|
||||
- [The Sized trait](the-sized-trait.md)
|
||||
- [The Drop trait](the-drop-trait.md)
|
||||
- [The Deref trait](the-deref-trait.md)
|
||||
- [The Send trait](the-send-trait.md)
|
||||
- [The Sync trait](the-sync-trait.md)
|
||||
|
||||
- [Memory model](memory-model.md)
|
||||
- [Memory allocation and lifetime](memory-allocation-and-lifetime.md)
|
||||
- [Memory ownership](memory-ownership.md)
|
||||
- [Variables](variables.md)
|
||||
|
||||
- [Linkage](linkage.md)
|
||||
|
||||
- [Unsafety](unsafety.md)
|
||||
- [Unsafe functions](unsafe-functions.md)
|
||||
- [Unsafe blocks](unsafe-blocks.md)
|
||||
- [Behavior considered undefined](behavior-considered-undefined.md)
|
||||
- [Behavior not considered unsafe](behavior-not-considered-unsafe.md)
|
||||
|
||||
[Appendix: Influences](influences.md)
|
||||
630
src/doc/reference/src/attributes.md
Normal file
630
src/doc/reference/src/attributes.md
Normal file
|
|
@ -0,0 +1,630 @@
|
|||
# Attributes
|
||||
|
||||
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
|
||||
according to name, convention, and language and compiler version. Attributes
|
||||
may appear as any of:
|
||||
|
||||
* A single identifier, the attribute name
|
||||
* An identifier followed by the equals sign '=' and a literal, providing a
|
||||
key/value pair
|
||||
* An identifier followed by a parenthesized list of sub-attribute arguments
|
||||
|
||||
Attributes with a bang ("!") after the hash ("#") apply to the item that the
|
||||
attribute is declared within. Attributes that do not have a bang after the hash
|
||||
apply to the item that follows the attribute.
|
||||
|
||||
An example of attributes:
|
||||
|
||||
```{.rust}
|
||||
// General metadata applied to the enclosing module or crate.
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// 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
|
||||
#[allow(non_camel_case_types)]
|
||||
type int8_t = i8;
|
||||
```
|
||||
|
||||
> **Note:** At some point in the future, the compiler will distinguish between
|
||||
> language-reserved and user-available attributes. Until then, there is
|
||||
> effectively no difference between an attribute handled by a loadable syntax
|
||||
> extension and the compiler.
|
||||
|
||||
## Crate-only attributes
|
||||
|
||||
- `crate_name` - specify the crate's crate name.
|
||||
- `crate_type` - see [linkage](linkage.html).
|
||||
- `feature` - see [compiler features](#compiler-features).
|
||||
- `no_builtins` - disable optimizing certain code patterns to invocations of
|
||||
library functions that are assumed to exist
|
||||
- `no_main` - disable emitting the `main` symbol. Useful when some other
|
||||
object being linked to defines `main`.
|
||||
- `no_start` - disable linking to the `native` crate, which specifies the
|
||||
"start" language item.
|
||||
- `no_std` - disable linking to the `std` crate.
|
||||
- `plugin` - load a list of named crates as compiler plugins, e.g.
|
||||
`#![plugin(foo, bar)]`. Optional arguments for each plugin,
|
||||
i.e. `#![plugin(foo(... args ...))]`, are provided to the plugin's
|
||||
registrar function. The `plugin` feature gate is required to use
|
||||
this attribute.
|
||||
- `recursion_limit` - Sets the maximum depth for potentially
|
||||
infinitely-recursive compile-time operations like
|
||||
auto-dereference or macro expansion. The default is
|
||||
`#![recursion_limit="64"]`.
|
||||
|
||||
### Module-only attributes
|
||||
|
||||
- `no_implicit_prelude` - disable injecting `use std::prelude::*` in this
|
||||
module.
|
||||
- `path` - specifies the file to load the module from. `#[path="foo.rs"] mod
|
||||
bar;` is equivalent to `mod bar { /* contents of foo.rs */ }`. The path is
|
||||
taken relative to the directory that the current module is in.
|
||||
|
||||
## Function-only attributes
|
||||
|
||||
- `main` - indicates that this function should be passed to the entry point,
|
||||
rather than the function in the crate root named `main`.
|
||||
- `plugin_registrar` - mark this function as the registration point for
|
||||
[compiler plugins][plugin], such as loadable syntax extensions.
|
||||
- `start` - indicates that this function should be used as the entry point,
|
||||
overriding the "start" language item. See the "start" [language
|
||||
item](#language-items) for more details.
|
||||
- `test` - indicates that this function is a test function, to only be compiled
|
||||
in case of `--test`.
|
||||
- `should_panic` - indicates that this test function should panic, inverting the success condition.
|
||||
- `cold` - The function is unlikely to be executed, so optimize it (and calls
|
||||
to it) differently.
|
||||
- `naked` - The function utilizes a custom ABI or custom inline ASM that requires
|
||||
epilogue and prologue to be skipped.
|
||||
|
||||
## Static-only attributes
|
||||
|
||||
- `thread_local` - on a `static mut`, this signals that the value of this
|
||||
static may change depending on the current thread. The exact consequences of
|
||||
this are implementation-defined.
|
||||
|
||||
## FFI attributes
|
||||
|
||||
On an `extern` block, the following attributes are interpreted:
|
||||
|
||||
- `link_args` - specify arguments to the linker, rather than just the library
|
||||
name and type. This is feature gated and the exact behavior is
|
||||
implementation-defined (due to variety of linker invocation syntax).
|
||||
- `link` - indicate that a native library should be linked to for the
|
||||
declarations in this block to be linked correctly. `link` supports an optional
|
||||
`kind` key with three possible values: `dylib`, `static`, and `framework`. See
|
||||
[external blocks](items.html#external-blocks) for more about external blocks. Two
|
||||
examples: `#[link(name = "readline")]` and
|
||||
`#[link(name = "CoreFoundation", kind = "framework")]`.
|
||||
- `linked_from` - indicates what native library this block of FFI items is
|
||||
coming from. This attribute is of the form `#[linked_from = "foo"]` where
|
||||
`foo` is the name of a library in either `#[link]` or a `-l` flag. This
|
||||
attribute is currently required to export symbols from a Rust dynamic library
|
||||
on Windows, and it is feature gated behind the `linked_from` feature.
|
||||
|
||||
On declarations inside an `extern` block, the following attributes are
|
||||
interpreted:
|
||||
|
||||
- `link_name` - the name of the symbol that this function or static should be
|
||||
imported as.
|
||||
- `linkage` - on a static, this specifies the [linkage
|
||||
type](http://llvm.org/docs/LangRef.html#linkage-types).
|
||||
|
||||
On `enum`s:
|
||||
|
||||
- `repr` - on C-like enums, this sets the underlying type used for
|
||||
representation. Takes one argument, which is the primitive
|
||||
type this enum should be represented for, or `C`, which specifies that it
|
||||
should be the default `enum` size of the C ABI for that platform. Note that
|
||||
enum representation in C is undefined, and this may be incorrect when the C
|
||||
code is compiled with certain flags.
|
||||
|
||||
On `struct`s:
|
||||
|
||||
- `repr` - specifies the representation to use for this struct. Takes a list
|
||||
of options. The currently accepted ones are `C` and `packed`, which may be
|
||||
combined. `C` will use a C ABI compatible struct layout, and `packed` will
|
||||
remove any padding between fields (note that this is very fragile and may
|
||||
break platforms which require aligned access).
|
||||
|
||||
## Macro-related attributes
|
||||
|
||||
- `macro_use` on a `mod` — macros defined in this module will be visible in the
|
||||
module's parent, after this module has been included.
|
||||
|
||||
- `macro_use` on an `extern crate` — load macros from this crate. An optional
|
||||
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).
|
||||
|
||||
- `macro_reexport` on an `extern crate` — re-export the named macros.
|
||||
|
||||
- `macro_export` - export a macro for cross-crate usage.
|
||||
|
||||
- `no_link` on an `extern crate` — even if we load this crate for macros, don't
|
||||
link it into the output.
|
||||
|
||||
See the [macros section of the
|
||||
book](../book/macros.html#scoping-and-macro-importexport) for more information on
|
||||
macro scope.
|
||||
|
||||
## Miscellaneous attributes
|
||||
|
||||
- `deprecated` - mark the item as deprecated; the full attribute is
|
||||
`#[deprecated(since = "crate version", note = "...")`, where both arguments
|
||||
are optional.
|
||||
- `export_name` - on statics and functions, this determines the name of the
|
||||
exported symbol.
|
||||
- `link_section` - on statics and functions, this specifies the section of the
|
||||
object file that this item's contents will be placed into.
|
||||
- `no_mangle` - on any item, do not apply the standard name mangling. Set the
|
||||
symbol for this item to its identifier.
|
||||
- `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.
|
||||
- `doc` - Doc comments such as `/// foo` are equivalent to `#[doc = "foo"]`.
|
||||
- `rustc_on_unimplemented` - Write a custom note to be shown along with the error
|
||||
when the trait is found to be unimplemented on a type.
|
||||
You may use format arguments like `{T}`, `{A}` to correspond to the
|
||||
types at the point of use corresponding to the type parameters of the
|
||||
trait of the same name. `{Self}` will be replaced with the type that is supposed
|
||||
to implement the trait but doesn't. To use this, the `on_unimplemented` feature gate
|
||||
must be enabled.
|
||||
- `must_use` - on structs and enums, will warn if a value of this type isn't used or
|
||||
assigned to a variable. You may also include an optional message by using
|
||||
`#[must_use = "message"]` which will be given alongside the warning.
|
||||
|
||||
### Conditional compilation
|
||||
|
||||
Sometimes one wants to have different compiler outputs from the same code,
|
||||
depending on build target, such as targeted operating system, or to enable
|
||||
release builds.
|
||||
|
||||
Configuration options are boolean (on or off) and are named either with a
|
||||
single identifier (e.g. `foo`) or an identifier and a string (e.g. `foo = "bar"`;
|
||||
the quotes are required and spaces around the `=` are unimportant). Note that
|
||||
similarly-named options, such as `foo`, `foo="bar"` and `foo="baz"` may each be set
|
||||
or unset independently.
|
||||
|
||||
Configuration options are either provided by the compiler or passed in on the
|
||||
command line using `--cfg` (e.g. `rustc main.rs --cfg foo --cfg 'bar="baz"'`).
|
||||
Rust code then checks for their presence using the `#[cfg(...)]` attribute:
|
||||
|
||||
```
|
||||
// The function is only included in the build when compiling for OSX
|
||||
#[cfg(target_os = "macos")]
|
||||
fn macos_only() {
|
||||
// ...
|
||||
}
|
||||
|
||||
// This function is only included when either foo or bar is defined
|
||||
#[cfg(any(foo, bar))]
|
||||
fn needs_foo_or_bar() {
|
||||
// ...
|
||||
}
|
||||
|
||||
// This function is only included when compiling for a unixish OS with a 32-bit
|
||||
// architecture
|
||||
#[cfg(all(unix, target_pointer_width = "32"))]
|
||||
fn on_32bit_unix() {
|
||||
// ...
|
||||
}
|
||||
|
||||
// This function is only included when foo is not defined
|
||||
#[cfg(not(foo))]
|
||||
fn needs_not_foo() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
This illustrates some conditional compilation can be achieved using the
|
||||
`#[cfg(...)]` attribute. `any`, `all` and `not` can be used to assemble
|
||||
arbitrarily complex configurations through nesting.
|
||||
|
||||
The following configurations must be defined by the implementation:
|
||||
|
||||
* `target_arch = "..."` - Target CPU architecture, such as `"x86"`,
|
||||
`"x86_64"` `"mips"`, `"powerpc"`, `"powerpc64"`, `"arm"`, or
|
||||
`"aarch64"`. This value is closely related to the first element of
|
||||
the platform target triple, though it is not identical.
|
||||
* `target_os = "..."` - Operating system of the target, examples
|
||||
include `"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`,
|
||||
`"freebsd"`, `"dragonfly"`, `"bitrig"` , `"openbsd"` or
|
||||
`"netbsd"`. This value is closely related to the second and third
|
||||
element of the platform target triple, though it is not identical.
|
||||
* `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`.
|
||||
* `unix` - See `target_family`.
|
||||
* `windows` - See `target_family`.
|
||||
* `target_env = ".."` - Further disambiguates the target platform with
|
||||
information about the ABI/libc. Presently this value is either
|
||||
`"gnu"`, `"msvc"`, `"musl"`, or the empty string. For historical
|
||||
reasons this value has only been defined as non-empty when needed
|
||||
for disambiguation. Thus on many GNU platforms this value will be
|
||||
empty. This value is closely related to the fourth element of the
|
||||
platform target triple, though it is not identical. For example,
|
||||
embedded ABIs such as `gnueabihf` will simply define `target_env` as
|
||||
`"gnu"`.
|
||||
* `target_endian = "..."` - Endianness of the target CPU, either `"little"` or
|
||||
`"big"`.
|
||||
* `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.
|
||||
* `target_has_atomic = "..."` - Set of integer sizes on which the target can perform
|
||||
atomic operations. Values are `"8"`, `"16"`, `"32"`, `"64"` and `"ptr"`.
|
||||
* `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or
|
||||
simply `"unknown"`.
|
||||
* `test` - Enabled when compiling the test harness (using the `--test` flag).
|
||||
* `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.
|
||||
|
||||
You can also set another attribute based on a `cfg` variable with `cfg_attr`:
|
||||
|
||||
```rust,ignore
|
||||
#[cfg_attr(a, b)]
|
||||
```
|
||||
|
||||
This is the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise.
|
||||
|
||||
Lastly, configuration options can be used in expressions by invoking the `cfg!`
|
||||
macro: `cfg!(a)` evaluates to `true` if `a` is set, and `false` otherwise.
|
||||
|
||||
### Lint check attributes
|
||||
|
||||
A lint check names a potentially undesirable coding pattern, such as
|
||||
unreachable code or omitted documentation, for the static entity to which the
|
||||
attribute applies.
|
||||
|
||||
For any lint check `C`:
|
||||
|
||||
* `allow(C)` overrides the check for `C` so that violations will go
|
||||
unreported,
|
||||
* `deny(C)` signals an error after encountering a violation of `C`,
|
||||
* `forbid(C)` is the same as `deny(C)`, but also forbids changing the lint
|
||||
level afterwards,
|
||||
* `warn(C)` warns about violations of `C` but continues compilation.
|
||||
|
||||
The lint checks supported by the compiler can be found via `rustc -W help`,
|
||||
along with their default settings. [Compiler
|
||||
plugins](../book/compiler-plugins.html#lint-plugins) can provide additional
|
||||
lint checks.
|
||||
|
||||
```{.ignore}
|
||||
pub mod m1 {
|
||||
// Missing documentation is ignored here
|
||||
#[allow(missing_docs)]
|
||||
pub fn undocumented_one() -> i32 { 1 }
|
||||
|
||||
// Missing documentation signals a warning here
|
||||
#[warn(missing_docs)]
|
||||
pub fn undocumented_too() -> i32 { 2 }
|
||||
|
||||
// Missing documentation signals an error here
|
||||
#[deny(missing_docs)]
|
||||
pub fn undocumented_end() -> i32 { 3 }
|
||||
}
|
||||
```
|
||||
|
||||
This example shows how one can use `allow` and `warn` to toggle a particular
|
||||
check on and off:
|
||||
|
||||
```{.ignore}
|
||||
#[warn(missing_docs)]
|
||||
pub mod m2{
|
||||
#[allow(missing_docs)]
|
||||
pub mod nested {
|
||||
// Missing documentation is ignored here
|
||||
pub fn undocumented_one() -> i32 { 1 }
|
||||
|
||||
// Missing documentation signals a warning here,
|
||||
// despite the allow above.
|
||||
#[warn(missing_docs)]
|
||||
pub fn undocumented_two() -> i32 { 2 }
|
||||
}
|
||||
|
||||
// Missing documentation signals a warning here
|
||||
pub fn undocumented_too() -> i32 { 3 }
|
||||
}
|
||||
```
|
||||
|
||||
This example shows how one can use `forbid` to disallow uses of `allow` for
|
||||
that lint check:
|
||||
|
||||
```{.ignore}
|
||||
#[forbid(missing_docs)]
|
||||
pub mod m3 {
|
||||
// Attempting to toggle warning signals an error here
|
||||
#[allow(missing_docs)]
|
||||
/// Returns 2.
|
||||
pub fn undocumented_too() -> i32 { 2 }
|
||||
}
|
||||
```
|
||||
|
||||
### Language items
|
||||
|
||||
Some primitive Rust operations are defined in Rust code, rather than being
|
||||
implemented directly in C or assembly language. The definitions of these
|
||||
operations have to be easy for the compiler to find. The `lang` attribute
|
||||
makes it possible to declare these operations. For example, the `str` module
|
||||
in the Rust standard library defines the string equality function:
|
||||
|
||||
```{.ignore}
|
||||
#[lang = "str_eq"]
|
||||
pub fn eq_slice(a: &str, b: &str) -> bool {
|
||||
// details elided
|
||||
}
|
||||
```
|
||||
|
||||
The name `str_eq` has a special meaning to the Rust compiler, and the presence
|
||||
of this definition means that it will use this definition when generating calls
|
||||
to the string equality function.
|
||||
|
||||
The set of language items is currently considered unstable. A complete
|
||||
list of the built-in language items will be added in the future.
|
||||
|
||||
### Inline attributes
|
||||
|
||||
The inline attribute suggests that the compiler should place a copy of
|
||||
the function or static in the caller, rather than generating code to
|
||||
call the function or access the static where it is defined.
|
||||
|
||||
The compiler automatically inlines functions based on internal heuristics.
|
||||
Incorrectly inlining functions can actually make the program slower, so it
|
||||
should be used with care.
|
||||
|
||||
`#[inline]` and `#[inline(always)]` always cause the function to be serialized
|
||||
into the crate metadata to allow cross-crate inlining.
|
||||
|
||||
There are three different types of inline attributes:
|
||||
|
||||
* `#[inline]` hints the compiler to perform an inline expansion.
|
||||
* `#[inline(always)]` asks the compiler to always perform an inline expansion.
|
||||
* `#[inline(never)]` asks the compiler to never perform an inline expansion.
|
||||
|
||||
### `derive`
|
||||
|
||||
The `derive` attribute allows certain traits to be automatically implemented
|
||||
for data structures. For example, the following will create an `impl` for the
|
||||
`PartialEq` and `Clone` traits for `Foo`, the type parameter `T` will be given
|
||||
the `PartialEq` or `Clone` constraints for the appropriate `impl`:
|
||||
|
||||
```
|
||||
#[derive(PartialEq, Clone)]
|
||||
struct Foo<T> {
|
||||
a: i32,
|
||||
b: T,
|
||||
}
|
||||
```
|
||||
|
||||
The generated `impl` for `PartialEq` is equivalent to
|
||||
|
||||
```
|
||||
# struct Foo<T> { a: i32, b: T }
|
||||
impl<T: PartialEq> PartialEq for Foo<T> {
|
||||
fn eq(&self, other: &Foo<T>) -> bool {
|
||||
self.a == other.a && self.b == other.b
|
||||
}
|
||||
|
||||
fn ne(&self, other: &Foo<T>) -> bool {
|
||||
self.a != other.a || self.b != other.b
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can implement `derive` for your own type through [procedural
|
||||
macros](procedural-macros.html).
|
||||
|
||||
### Compiler Features
|
||||
|
||||
Certain aspects of Rust may be implemented in the compiler, but they're not
|
||||
necessarily ready for every-day use. These features are often of "prototype
|
||||
quality" or "almost production ready", but may not be stable enough to be
|
||||
considered a full-fledged language feature.
|
||||
|
||||
For this reason, Rust recognizes a special crate-level attribute of the form:
|
||||
|
||||
```{.ignore}
|
||||
#![feature(feature1, feature2, feature3)]
|
||||
```
|
||||
|
||||
This directive informs the compiler that the feature list: `feature1`,
|
||||
`feature2`, and `feature3` should all be enabled. This is only recognized at a
|
||||
crate-level, not at a module-level. Without this directive, all features are
|
||||
considered off, and using the features will result in a compiler error.
|
||||
|
||||
The currently implemented features of the reference compiler are:
|
||||
|
||||
* `advanced_slice_patterns` - See the [match
|
||||
expressions](expressions.html#match-expressions)
|
||||
section for discussion; the exact semantics of
|
||||
slice patterns are subject to change, so some types are still unstable.
|
||||
|
||||
* `slice_patterns` - OK, actually, slice patterns are just scary and
|
||||
completely unstable.
|
||||
|
||||
* `asm` - The `asm!` macro provides a means for inline assembly. This is often
|
||||
useful, but the exact syntax for this feature along with its
|
||||
semantics are likely to change, so this macro usage must be opted
|
||||
into.
|
||||
|
||||
* `associated_consts` - Allows constants to be defined in `impl` and `trait`
|
||||
blocks, so that they can be associated with a type or
|
||||
trait in a similar manner to methods and associated
|
||||
types.
|
||||
|
||||
* `box_patterns` - Allows `box` patterns, the exact semantics of which
|
||||
is subject to change.
|
||||
|
||||
* `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.
|
||||
|
||||
* `cfg_target_has_atomic` - Allows conditional compilation using the `target_has_atomic`
|
||||
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.
|
||||
|
||||
* `custom_attribute` - Allows the usage of attributes unknown to the compiler
|
||||
so that new attributes can be added in a backwards compatible
|
||||
manner (RFC 572).
|
||||
|
||||
* `custom_derive` - Allows the use of `#[derive(Foo,Bar)]` as sugar for
|
||||
`#[derive_Foo] #[derive_Bar]`, which can be user-defined syntax
|
||||
extensions.
|
||||
|
||||
* `inclusive_range_syntax` - Allows use of the `a...b` and `...b` syntax for inclusive ranges.
|
||||
|
||||
* `inclusive_range` - Allows use of the types that represent desugared inclusive ranges.
|
||||
|
||||
* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
|
||||
are inherently unstable and no promise about them is made.
|
||||
|
||||
* `lang_items` - Allows use of the `#[lang]` attribute. Like `intrinsics`,
|
||||
lang items are inherently unstable and no promise about them
|
||||
is made.
|
||||
|
||||
* `link_args` - This attribute is used to specify custom flags to the linker,
|
||||
but usage is strongly discouraged. The compiler's usage of the
|
||||
system linker is not guaranteed to continue in the future, and
|
||||
if the system linker is not used then specifying custom flags
|
||||
doesn't have much meaning.
|
||||
|
||||
* `link_llvm_intrinsics` - Allows linking to LLVM intrinsics via
|
||||
`#[link_name="llvm.*"]`.
|
||||
|
||||
* `linkage` - Allows use of the `linkage` attribute, which is not portable.
|
||||
|
||||
* `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a
|
||||
nasty hack that will certainly be removed.
|
||||
|
||||
* `main` - Allows use of the `#[main]` attribute, which changes the entry point
|
||||
into a Rust program. This capability is subject to change.
|
||||
|
||||
* `macro_reexport` - Allows macros to be re-exported from one crate after being imported
|
||||
from another. This feature was originally designed with the sole
|
||||
use case of the Rust standard library in mind, and is subject to
|
||||
change.
|
||||
|
||||
* `non_ascii_idents` - The compiler supports the use of non-ascii identifiers,
|
||||
but the implementation is a little rough around the
|
||||
edges, so this can be seen as an experimental feature
|
||||
for now until the specification of identifiers is fully
|
||||
fleshed out.
|
||||
|
||||
* `no_std` - Allows the `#![no_std]` crate attribute, which disables the implicit
|
||||
`extern crate std`. This typically requires use of the unstable APIs
|
||||
behind the libstd "facade", such as libcore and libcollections. It
|
||||
may also cause problems when using syntax extensions, including
|
||||
`#[derive]`.
|
||||
|
||||
* `on_unimplemented` - Allows the `#[rustc_on_unimplemented]` attribute, which allows
|
||||
trait definitions to add specialized notes to error messages
|
||||
when an implementation was expected but not found.
|
||||
|
||||
* `optin_builtin_traits` - Allows the definition of default and negative trait
|
||||
implementations. Experimental.
|
||||
|
||||
* `plugin` - Usage of [compiler plugins][plugin] for custom lints or syntax extensions.
|
||||
These depend on compiler internals and are subject to change.
|
||||
|
||||
* `plugin_registrar` - Indicates that a crate provides [compiler plugins][plugin].
|
||||
|
||||
* `quote` - Allows use of the `quote_*!` family of macros, which are
|
||||
implemented very poorly and will likely change significantly
|
||||
with a proper implementation.
|
||||
|
||||
* `rustc_attrs` - Gates internal `#[rustc_*]` attributes which may be
|
||||
for internal use only or have meaning added to them in the future.
|
||||
|
||||
* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation
|
||||
of rustc, not meant for mortals.
|
||||
|
||||
* `simd` - Allows use of the `#[simd]` attribute, which is overly simple and
|
||||
not the SIMD interface we want to expose in the long term.
|
||||
|
||||
* `simd_ffi` - Allows use of SIMD vectors in signatures for foreign functions.
|
||||
The SIMD interface is subject to change.
|
||||
|
||||
* `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.
|
||||
|
||||
* `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
|
||||
LLVM's implementation which works in concert with the kernel
|
||||
loader and dynamic linker. This is not necessarily available
|
||||
on all platforms, and usage of it is discouraged.
|
||||
|
||||
* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
|
||||
hack that will certainly be removed.
|
||||
|
||||
* `unboxed_closures` - Rust's new closure design, which is currently a work in
|
||||
progress feature with many known bugs.
|
||||
|
||||
* `allow_internal_unstable` - Allows `macro_rules!` macros to be tagged with the
|
||||
`#[allow_internal_unstable]` attribute, designed
|
||||
to allow `std` macros to call
|
||||
`#[unstable]`/feature-gated functionality
|
||||
internally without imposing on callers
|
||||
(i.e. making them behave like function calls in
|
||||
terms of encapsulation).
|
||||
|
||||
* `default_type_parameter_fallback` - Allows type parameter defaults to
|
||||
influence type inference.
|
||||
|
||||
* `stmt_expr_attributes` - Allows attributes on expressions.
|
||||
|
||||
* `type_ascription` - Allows type ascription expressions `expr: Type`.
|
||||
|
||||
* `abi_vectorcall` - Allows the usage of the vectorcall calling convention
|
||||
(e.g. `extern "vectorcall" func fn_();`)
|
||||
|
||||
* `abi_sysv64` - Allows the usage of the system V AMD64 calling convention
|
||||
(e.g. `extern "sysv64" func fn_();`)
|
||||
|
||||
If a feature is promoted to a language feature, then all existing programs will
|
||||
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
|
||||
necessary, and it's likely that existing code will break if the feature isn't
|
||||
removed.
|
||||
|
||||
If an unknown feature is found in a directive, it results in a compiler error.
|
||||
An unknown feature is one which has never been recognized by the compiler.
|
||||
35
src/doc/reference/src/behavior-considered-undefined.md
Normal file
35
src/doc/reference/src/behavior-considered-undefined.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
## 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 T` and `&T` 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
|
||||
15
src/doc/reference/src/behavior-not-considered-unsafe.md
Normal file
15
src/doc/reference/src/behavior-not-considered-unsafe.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
## 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
|
||||
20
src/doc/reference/src/comments.md
Normal file
20
src/doc/reference/src/comments.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Comments
|
||||
|
||||
Comments in Rust code follow the general C++ style of line (`//`) and
|
||||
block (`/* ... */`) comment forms. Nested block comments are supported.
|
||||
|
||||
Line comments beginning with exactly _three_ slashes (`///`), and block
|
||||
comments (`/** ... */`), are interpreted as a special syntax for `doc`
|
||||
[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 `/*! ... */` 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
|
||||
modules that occupy a source file.
|
||||
|
||||
Non-doc comments are interpreted as a form of whitespace.
|
||||
|
||||
[attributes]: attributes.html
|
||||
73
src/doc/reference/src/crates-and-source-files.md
Normal file
73
src/doc/reference/src/crates-and-source-files.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# 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,
|
||||
and the language has
|
||||
always been designed to be compiled. For these reasons, this section assumes a
|
||||
compiler.
|
||||
|
||||
Rust's semantics obey a *phase distinction* between compile-time and
|
||||
run-time.[^phase-distinction] Semantic rules that have a *static
|
||||
interpretation* govern the success or failure of compilation, while
|
||||
semantic rules
|
||||
that have a *dynamic interpretation* govern the behavior of the program at
|
||||
run-time.
|
||||
|
||||
The compilation model centers on artifacts called _crates_. Each compilation
|
||||
processes a single crate in source form, and if successful, produces a single
|
||||
crate in binary form: either an executable or some sort of
|
||||
library.[^cratesourcefile]
|
||||
|
||||
A _crate_ is a unit of compilation and linking, as well as versioning,
|
||||
distribution and runtime loading. A crate contains a _tree_ of nested
|
||||
[module] scopes. The top level of this tree is a module that is
|
||||
anonymous (from the point of view of paths within the module) and any item
|
||||
within a crate has a canonical [module path] denoting its location
|
||||
within the crate's module tree.
|
||||
|
||||
The Rust compiler is always invoked with a single source file as input, and
|
||||
always produces a single output crate. The processing of that source file may
|
||||
result in other source files being loaded as modules. Source files have the
|
||||
extension `.rs`.
|
||||
|
||||
A Rust source file describes a module, the name and location of which —
|
||||
in the module tree of the current crate — are defined from outside the
|
||||
source file: either by an explicit `mod_item` in a referencing source file, or
|
||||
by the name of the crate itself. Every source file is a module, but not every
|
||||
module needs its own source file: [module definitions][module] can be nested
|
||||
within one file.
|
||||
|
||||
Each source file contains a sequence of zero or more `item` definitions, and
|
||||
may optionally begin with any number of [attributes]
|
||||
that apply to the containing module, most of which influence the behavior of
|
||||
the compiler. The anonymous crate module can have additional attributes that
|
||||
apply to the crate as a whole.
|
||||
|
||||
```rust,no_run
|
||||
// Specify the crate name.
|
||||
#![crate_name = "projx"]
|
||||
|
||||
// Specify the type of output artifact.
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// Turn on a warning.
|
||||
// This can be done in any module, not just the anonymous crate module.
|
||||
#![warn(non_camel_case_types)]
|
||||
```
|
||||
|
||||
A crate that contains a `main` function can be compiled to an executable. If a
|
||||
`main` function is present, its return type must be `()`
|
||||
("[unit]") and it must take no arguments.
|
||||
|
||||
[^phase-distinction]: This distinction would also exist in an interpreter.
|
||||
Static checks like syntactic analysis, type checking, and lints should
|
||||
happen before the program is executed regardless of when it is executed.
|
||||
|
||||
[^cratesourcefile]: A crate is somewhat analogous to an *assembly* in the
|
||||
ECMA-335 CLI model, a *library* in the SML/NJ Compilation Manager, a *unit*
|
||||
in the Owens and Flatt module system, or a *configuration* in Mesa.
|
||||
|
||||
[module]: items.html#modules
|
||||
[module path]: paths.html
|
||||
[attributes]: items-and-attributes.html
|
||||
[unit]: types.html#tuple-types
|
||||
863
src/doc/reference/src/expressions.md
Normal file
863
src/doc/reference/src/expressions.md
Normal file
|
|
@ -0,0 +1,863 @@
|
|||
# Expressions
|
||||
|
||||
An expression may have two roles: it always produces a *value*, and it may have
|
||||
*effects* (otherwise known as "side effects"). An expression *evaluates to* a
|
||||
value, and has effects during *evaluation*. Many expressions contain
|
||||
sub-expressions (operands). The meaning of each kind of expression dictates
|
||||
several things:
|
||||
|
||||
* Whether or not to evaluate the sub-expressions when evaluating the expression
|
||||
* The order in which to evaluate the sub-expressions
|
||||
* How to combine the sub-expressions' values to obtain the value of the expression
|
||||
|
||||
In this way, the structure of expressions dictates the structure of execution.
|
||||
Blocks are just another kind of expression, so blocks, statements, expressions,
|
||||
and blocks again can recursively nest inside each other to an arbitrary depth.
|
||||
|
||||
### Lvalues, rvalues and temporaries
|
||||
|
||||
Expressions are divided into two main categories: _lvalues_ and _rvalues_.
|
||||
Likewise within each expression, sub-expressions may occur in _lvalue context_
|
||||
or _rvalue context_. The evaluation of an expression depends both on its own
|
||||
category and the context it occurs within.
|
||||
|
||||
An lvalue is an expression that represents a memory location. These expressions
|
||||
are [paths](#path-expressions) (which refer to local variables, function and
|
||||
method arguments, or static variables), dereferences (`*expr`), [indexing
|
||||
expressions](#index-expressions) (`expr[expr]`), and [field
|
||||
references](#field-expressions) (`expr.f`). All other expressions are rvalues.
|
||||
|
||||
The left operand of an [assignment](#assignment-expressions) or
|
||||
[compound-assignment](#compound-assignment-expressions) expression is
|
||||
an lvalue context, as is the single operand of a unary
|
||||
[borrow](#unary-operator-expressions). The discriminant or subject of
|
||||
a [match expression](#match-expressions) may be an lvalue context, if
|
||||
ref bindings are made, but is otherwise an rvalue context. All other
|
||||
expression contexts are rvalue contexts.
|
||||
|
||||
When an lvalue is evaluated in an _lvalue context_, it denotes a memory
|
||||
location; when evaluated in an _rvalue context_, it denotes the value held _in_
|
||||
that memory location.
|
||||
|
||||
#### Temporary lifetimes
|
||||
|
||||
When an rvalue is used in an lvalue context, a temporary un-named
|
||||
lvalue is created and used instead. The lifetime of temporary values
|
||||
is typically the innermost enclosing statement; the tail expression of
|
||||
a block is considered part of the statement that encloses the block.
|
||||
|
||||
When a temporary rvalue is being created that is assigned into a `let`
|
||||
declaration, however, the temporary is created with the lifetime of
|
||||
the enclosing block instead, as using the enclosing statement (the
|
||||
`let` declaration) would be a guaranteed error (since a pointer to the
|
||||
temporary would be stored into a variable, but the temporary would be
|
||||
freed before the variable could be used). The compiler uses simple
|
||||
syntactic rules to decide which values are being assigned into a `let`
|
||||
binding, and therefore deserve a longer temporary lifetime.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
- `let x = foo(&temp())`. The expression `temp()` is an rvalue. As it
|
||||
is being borrowed, a temporary is created which will be freed after
|
||||
the innermost enclosing statement (the `let` declaration, in this case).
|
||||
- `let x = temp().foo()`. This is the same as the previous example,
|
||||
except that the value of `temp()` is being borrowed via autoref on a
|
||||
method-call. Here we are assuming that `foo()` is an `&self` method
|
||||
defined in some trait, say `Foo`. In other words, the expression
|
||||
`temp().foo()` is equivalent to `Foo::foo(&temp())`.
|
||||
- `let x = &temp()`. Here, the same temporary is being assigned into
|
||||
`x`, rather than being passed as a parameter, and hence the
|
||||
temporary's lifetime is considered to be the enclosing block.
|
||||
- `let x = SomeStruct { foo: &temp() }`. As in the previous case, the
|
||||
temporary is assigned into a struct which is then assigned into a
|
||||
binding, and hence it is given the lifetime of the enclosing block.
|
||||
- `let x = [ &temp() ]`. As in the previous case, the
|
||||
temporary is assigned into an array which is then assigned into a
|
||||
binding, and hence it is given the lifetime of the enclosing block.
|
||||
- `let ref x = temp()`. In this case, the temporary is created using a ref binding,
|
||||
but the result is the same: the lifetime is extended to the enclosing block.
|
||||
|
||||
### Moved and copied types
|
||||
|
||||
When a [local variable](variables.html) is used as an
|
||||
[rvalue](expressions.html#lvalues-rvalues-and-temporaries), the variable will
|
||||
be copied if its type implements `Copy`. All others are moved.
|
||||
|
||||
## Literal expressions
|
||||
|
||||
A _literal expression_ consists of one of the [literal](tokens.html#literals) forms
|
||||
described earlier. It directly describes a number, character, string, boolean
|
||||
value, or the unit value.
|
||||
|
||||
```text
|
||||
(); // unit type
|
||||
"hello"; // string type
|
||||
'5'; // character type
|
||||
5; // integer type
|
||||
```
|
||||
|
||||
## Path expressions
|
||||
|
||||
A [path](paths.html) used as an expression context denotes either a local
|
||||
variable or an item. Path expressions are
|
||||
[lvalues](expressions.html#lvalues-rvalues-and-temporaries).
|
||||
|
||||
## Tuple expressions
|
||||
|
||||
Tuples are written by enclosing zero or more comma-separated expressions in
|
||||
parentheses. They are used to create [tuple-typed](types.html#tuple-types)
|
||||
values.
|
||||
|
||||
```{.tuple}
|
||||
(0.0, 4.5);
|
||||
("a", 4usize, true);
|
||||
```
|
||||
|
||||
You can disambiguate a single-element tuple from a value in parentheses with a
|
||||
comma:
|
||||
|
||||
```
|
||||
(0,); // single-element tuple
|
||||
(0); // zero in parentheses
|
||||
```
|
||||
|
||||
## Struct expressions
|
||||
|
||||
There are several forms of struct expressions. A _struct expression_
|
||||
consists of the [path](paths.html) of a [struct item](items.html#structs), followed
|
||||
by a brace-enclosed list of zero or more comma-separated name-value pairs,
|
||||
providing the field values of a new instance of the struct. A field name can be
|
||||
any identifier, and is separated from its value expression by a colon. The
|
||||
location denoted by a struct field is mutable if and only if the enclosing
|
||||
struct is mutable.
|
||||
|
||||
A _tuple struct expression_ consists of the [path](paths.html) of a [struct
|
||||
item](items.html#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 struct expression_ consists only of the [path](paths.html) of a
|
||||
[struct item](items.html#structs).
|
||||
|
||||
The following are examples of struct expressions:
|
||||
|
||||
```
|
||||
# struct Point { x: f64, y: f64 }
|
||||
# struct NothingInMe { }
|
||||
# struct TuplePoint(f64, f64);
|
||||
# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } }
|
||||
# struct Cookie; fn some_fn<T>(t: T) {}
|
||||
Point {x: 10.0, y: 20.0};
|
||||
NothingInMe {};
|
||||
TuplePoint(10.0, 20.0);
|
||||
let u = game::User {name: "Joe", age: 35, score: 100_000};
|
||||
some_fn::<Cookie>(Cookie);
|
||||
```
|
||||
|
||||
A struct expression forms a new value of the named struct type. Note
|
||||
that for a given *unit-like* struct type, this will always be the same
|
||||
value.
|
||||
|
||||
A struct expression can terminate with the syntax `..` followed by an
|
||||
expression to denote a functional update. The expression following `..` (the
|
||||
base) must have the same struct type as the new struct type being formed.
|
||||
The entire expression denotes the result of constructing a new struct (with
|
||||
the same type as the base expression) with the given values for the fields that
|
||||
were explicitly specified and the values in the base expression for all other
|
||||
fields.
|
||||
|
||||
```
|
||||
# struct Point3d { x: i32, y: i32, z: i32 }
|
||||
let base = Point3d {x: 1, y: 2, z: 3};
|
||||
Point3d {y: 0, z: 10, .. base};
|
||||
```
|
||||
|
||||
#### Struct field init shorthand
|
||||
|
||||
When initializing a data structure (struct, enum, union) with named fields,
|
||||
it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`.
|
||||
This allows a compact syntax with less duplication.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
# struct Point3d { x: i32, y: i32, z: i32 }
|
||||
# let x = 0;
|
||||
# let y_value = 0;
|
||||
# let z = 0;
|
||||
Point3d { x: x, y: y_value, z: z };
|
||||
Point3d { x, y: y_value, z };
|
||||
```
|
||||
|
||||
## Block expressions
|
||||
|
||||
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
|
||||
the block itself.
|
||||
|
||||
A block will execute each statement sequentially, and then execute the
|
||||
expression (if given). If the block ends in a statement, its value is `()`:
|
||||
|
||||
```
|
||||
let x: () = { println!("Hello."); };
|
||||
```
|
||||
|
||||
If it ends in an expression, its value and type are that of the expression:
|
||||
|
||||
```
|
||||
let x: i32 = { println!("Hello."); 5 };
|
||||
|
||||
assert_eq!(5, x);
|
||||
```
|
||||
|
||||
## Method-call expressions
|
||||
|
||||
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
|
||||
exact `self`-type of the left-hand-side is known, or dynamically dispatching if
|
||||
the left-hand-side expression is an indirect [trait
|
||||
object](types.html#trait-objects).
|
||||
|
||||
## Field expressions
|
||||
|
||||
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 [struct](types.html#struct-types).
|
||||
|
||||
```{.ignore .field}
|
||||
mystruct.myfield;
|
||||
foo().x;
|
||||
(Struct {a: 10, b: 20}).a;
|
||||
```
|
||||
|
||||
A field access is an [lvalue](expressions.html#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.
|
||||
|
||||
Also, if the type of the expression to the left of the dot is a
|
||||
pointer, it is automatically dereferenced as many times as necessary
|
||||
to make the field access possible. In cases of ambiguity, we prefer
|
||||
fewer autoderefs to more.
|
||||
|
||||
## Array expressions
|
||||
|
||||
An [array](types.html#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
|
||||
constant expression that can be evaluated at compile time, such as a
|
||||
[literal](tokens.html#literals) or a [static item](items.html#static-items).
|
||||
|
||||
```
|
||||
[1, 2, 3, 4];
|
||||
["a", "b", "c", "d"];
|
||||
[0; 128]; // array with 128 zeros
|
||||
[0u8, 0u8, 0u8, 0u8];
|
||||
```
|
||||
|
||||
## Index expressions
|
||||
|
||||
[Array](types.html#array-and-slice-types)-typed expressions can be indexed by
|
||||
writing a square-bracket-enclosed expression (the index) after them. When the
|
||||
array is mutable, the resulting
|
||||
[lvalue](expressions.html#lvalues-rvalues-and-temporaries) can be assigned to.
|
||||
|
||||
Indices are zero-based, and may be of any integral type. Vector access is
|
||||
bounds-checked at compile-time for constant arrays being accessed with a
|
||||
constant index value. Otherwise a check will be performed at run-time that
|
||||
will put the thread in a _panicked state_ if it fails.
|
||||
|
||||
```{should-fail}
|
||||
([1, 2, 3, 4])[0];
|
||||
|
||||
let x = (["a", "b"])[10]; // compiler error: const index-expr is out of bounds
|
||||
|
||||
let n = 10;
|
||||
let y = (["a", "b"])[n]; // panics
|
||||
|
||||
let arr = ["a", "b"];
|
||||
arr[10]; // panics
|
||||
```
|
||||
|
||||
Also, if the type of the expression to the left of the brackets is a
|
||||
pointer, it is automatically dereferenced as many times as necessary
|
||||
to make the indexing possible. In cases of ambiguity, we prefer fewer
|
||||
autoderefs to more.
|
||||
|
||||
## Range expressions
|
||||
|
||||
The `..` operator will construct an object of one of the `std::ops::Range` variants.
|
||||
|
||||
```
|
||||
1..2; // std::ops::Range
|
||||
3..; // std::ops::RangeFrom
|
||||
..4; // std::ops::RangeTo
|
||||
..; // std::ops::RangeFull
|
||||
```
|
||||
|
||||
The following expressions are equivalent.
|
||||
|
||||
```
|
||||
let x = std::ops::Range {start: 0, end: 10};
|
||||
let y = 0..10;
|
||||
|
||||
assert_eq!(x, y);
|
||||
```
|
||||
|
||||
Similarly, the `...` operator will construct an object of one of the
|
||||
`std::ops::RangeInclusive` variants.
|
||||
|
||||
```
|
||||
# #![feature(inclusive_range_syntax)]
|
||||
1...2; // std::ops::RangeInclusive
|
||||
...4; // std::ops::RangeToInclusive
|
||||
```
|
||||
|
||||
The following expressions are equivalent.
|
||||
|
||||
```
|
||||
# #![feature(inclusive_range_syntax, inclusive_range)]
|
||||
let x = std::ops::RangeInclusive::NonEmpty {start: 0, end: 10};
|
||||
let y = 0...10;
|
||||
|
||||
assert_eq!(x, y);
|
||||
```
|
||||
|
||||
## Unary operator expressions
|
||||
|
||||
Rust defines the following unary operators. With the exception of `?`, they are
|
||||
all written as prefix operators, before the expression they apply to.
|
||||
|
||||
* `-`
|
||||
: Negation. Signed integer types and floating-point types support negation. It
|
||||
is an error to apply negation to unsigned types; for example, the compiler
|
||||
rejects `-1u32`.
|
||||
* `*`
|
||||
: Dereference. When applied to a [pointer](types.html#pointer-types) it
|
||||
denotes the pointed-to location. For pointers to mutable locations, the
|
||||
resulting [lvalue](expressions.html#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 could mutate the dereference), and produces
|
||||
the result of dereferencing the `&` or `&mut` borrowed pointer returned
|
||||
from the overload method.
|
||||
* `!`
|
||||
: Logical negation. On the boolean type, this flips between `true` and
|
||||
`false`. On integer types, this inverts the individual bits in the
|
||||
two's complement representation of the value.
|
||||
* `&` and `&mut`
|
||||
: Borrowing. When applied to an lvalue, these operators produce a
|
||||
reference (pointer) to the lvalue. The lvalue is also placed into
|
||||
a borrowed state for the duration of the reference. For a shared
|
||||
borrow (`&`), this implies that the lvalue may not be mutated, but
|
||||
it may be read or shared again. For a mutable borrow (`&mut`), the
|
||||
lvalue may not be accessed in any way until the borrow expires.
|
||||
If the `&` or `&mut` operators are applied to an rvalue, a
|
||||
temporary value is created; the lifetime of this temporary value
|
||||
is defined by [syntactic rules](#temporary-lifetimes).
|
||||
* `?`
|
||||
: Propagating errors if applied to `Err(_)` and unwrapping if
|
||||
applied to `Ok(_)`. Only works on the `Result<T, E>` type,
|
||||
and written in postfix notation.
|
||||
|
||||
## Binary operator expressions
|
||||
|
||||
Binary operators expressions are given in terms of [operator
|
||||
precedence](#operator-precedence).
|
||||
|
||||
### Arithmetic operators
|
||||
|
||||
Binary arithmetic expressions are syntactic sugar for calls to built-in traits,
|
||||
defined in the `std::ops` module of the `std` library. This means that
|
||||
arithmetic operators can be overridden for user-defined types. The default
|
||||
meaning of the operators on standard types is given here.
|
||||
|
||||
* `+`
|
||||
: Addition and array/string concatenation.
|
||||
Calls the `add` method on the `std::ops::Add` trait.
|
||||
* `-`
|
||||
: Subtraction.
|
||||
Calls the `sub` method on the `std::ops::Sub` trait.
|
||||
* `*`
|
||||
: Multiplication.
|
||||
Calls the `mul` method on the `std::ops::Mul` trait.
|
||||
* `/`
|
||||
: Quotient.
|
||||
Calls the `div` method on the `std::ops::Div` trait.
|
||||
* `%`
|
||||
: Remainder.
|
||||
Calls the `rem` method on the `std::ops::Rem` trait.
|
||||
|
||||
### Bitwise operators
|
||||
|
||||
Like the [arithmetic operators](#arithmetic-operators), bitwise operators are
|
||||
syntactic sugar for calls to methods of built-in traits. This means that
|
||||
bitwise operators can be overridden for user-defined types. The default
|
||||
meaning of the operators on standard types is given here. Bitwise `&`, `|` and
|
||||
`^` applied to boolean arguments are equivalent to logical `&&`, `||` and `!=`
|
||||
evaluated in non-lazy fashion.
|
||||
|
||||
* `&`
|
||||
: Bitwise AND.
|
||||
Calls the `bitand` method of the `std::ops::BitAnd` trait.
|
||||
* `|`
|
||||
: Bitwise inclusive OR.
|
||||
Calls the `bitor` method of the `std::ops::BitOr` trait.
|
||||
* `^`
|
||||
: Bitwise exclusive OR.
|
||||
Calls the `bitxor` method of the `std::ops::BitXor` trait.
|
||||
* `<<`
|
||||
: Left shift.
|
||||
Calls the `shl` method of the `std::ops::Shl` trait.
|
||||
* `>>`
|
||||
: Right shift (arithmetic).
|
||||
Calls the `shr` method of the `std::ops::Shr` trait.
|
||||
|
||||
### Lazy boolean operators
|
||||
|
||||
The operators `||` and `&&` may be applied to operands of boolean type. The
|
||||
`||` operator denotes logical 'or', and the `&&` operator denotes logical
|
||||
'and'. They differ from `|` and `&` in that the right-hand operand is only
|
||||
evaluated when the left-hand operand does not already determine the result of
|
||||
the expression. That is, `||` only evaluates its right-hand operand when the
|
||||
left-hand operand evaluates to `false`, and `&&` only when it evaluates to
|
||||
`true`.
|
||||
|
||||
### Comparison operators
|
||||
|
||||
Comparison operators are, like the [arithmetic
|
||||
operators](#arithmetic-operators), and [bitwise operators](#bitwise-operators),
|
||||
syntactic sugar for calls to built-in traits. This means that comparison
|
||||
operators can be overridden for user-defined types. The default meaning of the
|
||||
operators on standard types is given here.
|
||||
|
||||
* `==`
|
||||
: Equal to.
|
||||
Calls the `eq` method on the `std::cmp::PartialEq` trait.
|
||||
* `!=`
|
||||
: Unequal to.
|
||||
Calls the `ne` method on the `std::cmp::PartialEq` trait.
|
||||
* `<`
|
||||
: Less than.
|
||||
Calls the `lt` method on the `std::cmp::PartialOrd` trait.
|
||||
* `>`
|
||||
: Greater than.
|
||||
Calls the `gt` method on the `std::cmp::PartialOrd` trait.
|
||||
* `<=`
|
||||
: Less than or equal.
|
||||
Calls the `le` method on the `std::cmp::PartialOrd` trait.
|
||||
* `>=`
|
||||
: Greater than or equal.
|
||||
Calls the `ge` method on the `std::cmp::PartialOrd` trait.
|
||||
|
||||
### Type cast expressions
|
||||
|
||||
A type cast expression is denoted with the binary operator `as`.
|
||||
|
||||
Executing an `as` expression casts the value on the left-hand side to the type
|
||||
on the right-hand side.
|
||||
|
||||
An example of an `as` expression:
|
||||
|
||||
```
|
||||
# fn sum(values: &[f64]) -> f64 { 0.0 }
|
||||
# fn len(values: &[f64]) -> i32 { 0 }
|
||||
|
||||
fn average(values: &[f64]) -> f64 {
|
||||
let sum: f64 = sum(values);
|
||||
let size: f64 = len(values) as f64;
|
||||
sum / size
|
||||
}
|
||||
```
|
||||
|
||||
Some of the conversions which can be done through the `as` operator
|
||||
can also be done implicitly at various points in the program, such as
|
||||
argument passing and assignment to a `let` binding with an explicit
|
||||
type. Implicit conversions are limited to "harmless" conversions that
|
||||
do not lose information and which have minimal or no risk of
|
||||
surprising side-effects on the dynamic execution semantics.
|
||||
|
||||
### Assignment expressions
|
||||
|
||||
An _assignment expression_ consists of an
|
||||
[lvalue](expressions.html#lvalues-rvalues-and-temporaries) expression followed
|
||||
by an equals sign (`=`) and an
|
||||
[rvalue](expressions.html#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
|
||||
operand.
|
||||
|
||||
```
|
||||
# let mut x = 0;
|
||||
# let y = 0;
|
||||
x = y;
|
||||
```
|
||||
|
||||
### Compound assignment expressions
|
||||
|
||||
The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be
|
||||
composed with the `=` operator. The expression `lval OP= val` is equivalent to
|
||||
`lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`.
|
||||
|
||||
Any such expression always has the [`unit`](types.html#tuple-types) type.
|
||||
|
||||
### Operator precedence
|
||||
|
||||
The precedence of Rust binary operators is ordered as follows, going from
|
||||
strong to weak:
|
||||
|
||||
```{.text .precedence}
|
||||
as :
|
||||
* / %
|
||||
+ -
|
||||
<< >>
|
||||
&
|
||||
^
|
||||
|
|
||||
== != < > <= >=
|
||||
&&
|
||||
||
|
||||
.. ...
|
||||
<-
|
||||
=
|
||||
```
|
||||
|
||||
Operators at the same precedence level are evaluated left-to-right. [Unary
|
||||
operators](#unary-operator-expressions) have the same precedence level and are
|
||||
stronger than any of the binary operators.
|
||||
|
||||
## Grouped expressions
|
||||
|
||||
An expression enclosed in parentheses evaluates to the result of the enclosed
|
||||
expression. Parentheses can be used to explicitly specify evaluation order
|
||||
within an expression.
|
||||
|
||||
An example of a parenthesized expression:
|
||||
|
||||
```
|
||||
let x: i32 = (2 + 3) * 4;
|
||||
```
|
||||
|
||||
|
||||
## Call expressions
|
||||
|
||||
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.
|
||||
|
||||
Some examples of call expressions:
|
||||
|
||||
```
|
||||
# fn add(x: i32, y: i32) -> i32 { 0 }
|
||||
|
||||
let x: i32 = add(1i32, 2i32);
|
||||
let pi: Result<f32, _> = "3.14".parse();
|
||||
```
|
||||
|
||||
## Lambda expressions
|
||||
|
||||
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
|
||||
expression.
|
||||
|
||||
A lambda expression denotes a function that maps a list of parameters
|
||||
(`ident_list`) onto the expression that follows the `ident_list`. The
|
||||
identifiers in the `ident_list` are the parameters to the function. These
|
||||
parameters' types need not be specified, as the compiler infers them from
|
||||
context.
|
||||
|
||||
Lambda expressions are most useful when passing functions as arguments to other
|
||||
functions, as an abbreviation for defining and capturing a separate function.
|
||||
|
||||
Significantly, lambda expressions _capture their environment_, which regular
|
||||
[function definitions](items.html#functions) do not. The exact type of capture
|
||||
depends on the [function type](types.html#function-types) inferred for the
|
||||
lambda expression. In the simplest and least-expensive form (analogous to a
|
||||
```|| { }``` expression), the lambda expression captures its environment by
|
||||
reference, effectively borrowing pointers to all outer variables mentioned
|
||||
inside the function. Alternately, the compiler may infer that a lambda
|
||||
expression should copy or move values (depending on their type) from the
|
||||
environment into the lambda expression's captured environment. A lambda can be
|
||||
forced to capture its environment by moving values by prefixing it with the
|
||||
`move` keyword.
|
||||
|
||||
In this example, we define a function `ten_times` that takes a higher-order
|
||||
function argument, and we then call it with a lambda expression as an argument,
|
||||
followed by a lambda expression that moves values from its environment.
|
||||
|
||||
```
|
||||
fn ten_times<F>(f: F) where F: Fn(i32) {
|
||||
for index in 0..10 {
|
||||
f(index);
|
||||
}
|
||||
}
|
||||
|
||||
ten_times(|j| println!("hello, {}", j));
|
||||
|
||||
let word = "konnichiwa".to_owned();
|
||||
ten_times(move |j| println!("{}, {}", word, j));
|
||||
```
|
||||
|
||||
## Infinite loops
|
||||
|
||||
A `loop` expression denotes an infinite loop.
|
||||
|
||||
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
|
||||
within this loop may exit out of this loop or return control to its head.
|
||||
See [break expressions](#break-expressions) and [continue
|
||||
expressions](#continue-expressions).
|
||||
|
||||
## `break` expressions
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
the case of a `while` loop, the head is the conditional expression controlling
|
||||
the loop. In the case of a `for` loop, the head is the call-expression
|
||||
controlling the loop. If the label is present, then `continue 'foo` returns
|
||||
control to the head of the loop with label `'foo`, which need not be the
|
||||
innermost label enclosing the `continue` expression, but must enclose it.
|
||||
|
||||
A `continue` expression is only permitted in the body of a loop.
|
||||
|
||||
## `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
|
||||
executes and control returns to the loop conditional expression. If the loop
|
||||
conditional expression evaluates to `false`, the `while` expression completes.
|
||||
|
||||
An example:
|
||||
|
||||
```
|
||||
let mut i = 0;
|
||||
|
||||
while i < 10 {
|
||||
println!("hello");
|
||||
i = i + 1;
|
||||
}
|
||||
```
|
||||
|
||||
Like `loop` expressions, `while` loops can be controlled with `break` or
|
||||
`continue`, and may optionally have a _label_. See [infinite
|
||||
loops](#infinite-loops), [break expressions](#break-expressions), and
|
||||
[continue expressions](#continue-expressions) for more information.
|
||||
|
||||
## `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:
|
||||
|
||||
```
|
||||
# type Foo = i32;
|
||||
# fn bar(f: &Foo) { }
|
||||
# let a = 0;
|
||||
# let b = 0;
|
||||
# let c = 0;
|
||||
|
||||
let v: &[Foo] = &[a, b, c];
|
||||
|
||||
for e in v {
|
||||
bar(e);
|
||||
}
|
||||
```
|
||||
|
||||
An example of a for loop over a series of integers:
|
||||
|
||||
```
|
||||
# fn bar(b:usize) { }
|
||||
for i in 0..256 {
|
||||
bar(i);
|
||||
}
|
||||
```
|
||||
|
||||
Like `loop` expressions, `for` loops can be controlled with `break` or
|
||||
`continue`, and may optionally have a _label_. See [infinite
|
||||
loops](#infinite-loops), [break expressions](#break-expressions), and
|
||||
[continue expressions](#continue-expressions) for more information.
|
||||
|
||||
## `if` expressions
|
||||
|
||||
An `if` expression is a conditional branch in program control. The form of an
|
||||
`if` expression is a condition expression, followed by a consequent block, any
|
||||
number of `else if` conditions and blocks, and an optional trailing `else`
|
||||
block. The condition expressions must have type `bool`. If a condition
|
||||
expression evaluates to `true`, the consequent block is executed and any
|
||||
subsequent `else if` or `else` block is skipped. If a condition expression
|
||||
evaluates to `false`, the consequent block is skipped and any subsequent `else
|
||||
if` condition is evaluated. If all `if` and `else if` conditions evaluate to
|
||||
`false` then any `else` block is executed.
|
||||
|
||||
## `match` expressions
|
||||
|
||||
A `match` expression branches on a *pattern*. The exact form of matching that
|
||||
occurs depends on the pattern. Patterns consist of some combination of
|
||||
literals, destructured arrays or enum constructors, structs and tuples,
|
||||
variable binding specifications, wildcards (`..`), and placeholders (`_`). A
|
||||
`match` expression has a *head expression*, which is the value to compare to
|
||||
the patterns. The type of the patterns must equal the type of the head
|
||||
expression.
|
||||
|
||||
In a pattern whose head expression has an `enum` type, a placeholder (`_`)
|
||||
stands for a *single* data field, whereas a wildcard `..` stands for *all* the
|
||||
fields of a particular variant.
|
||||
|
||||
A `match` behaves differently depending on whether or not the head expression
|
||||
is an [lvalue or an rvalue](expressions.html#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 target of the `match`, any variables bound by the pattern
|
||||
are assigned to local variables in the arm's block, and control enters the
|
||||
block.
|
||||
|
||||
When the head expression is an lvalue, the match does not allocate a temporary
|
||||
location (however, a by-value binding may copy or move from the lvalue). When
|
||||
possible, it is preferable to match on lvalues, as the lifetime of these
|
||||
matches inherits the lifetime of the lvalue, rather than being restricted to
|
||||
the inside of the match.
|
||||
|
||||
An example of a `match` expression:
|
||||
|
||||
```
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
1 => println!("one"),
|
||||
2 => println!("two"),
|
||||
3 => println!("three"),
|
||||
4 => println!("four"),
|
||||
5 => println!("five"),
|
||||
_ => println!("something else"),
|
||||
}
|
||||
```
|
||||
|
||||
Patterns that bind variables default to binding to a copy or move of the
|
||||
matched value (depending on the matched value's type). This can be changed to
|
||||
bind to a reference by using the `ref` keyword, or to a mutable reference using
|
||||
`ref mut`.
|
||||
|
||||
Subpatterns can also be bound to variables by the use of the syntax `variable @
|
||||
subpattern`. For example:
|
||||
|
||||
```
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
e @ 1 ... 5 => println!("got a range element {}", e),
|
||||
_ => println!("anything"),
|
||||
}
|
||||
```
|
||||
|
||||
Patterns can also dereference pointers by using the `&`, `&mut` and `box`
|
||||
symbols, as appropriate. For example, these two matches on `x: &i32` are
|
||||
equivalent:
|
||||
|
||||
```
|
||||
# let x = &3;
|
||||
let y = match *x { 0 => "zero", _ => "some" };
|
||||
let z = match x { &0 => "zero", _ => "some" };
|
||||
|
||||
assert_eq!(y, z);
|
||||
```
|
||||
|
||||
Multiple match patterns may be joined with the `|` operator. A range of values
|
||||
may be specified with `...`. For example:
|
||||
|
||||
```
|
||||
# let x = 2;
|
||||
|
||||
let message = match x {
|
||||
0 | 1 => "not many",
|
||||
2 ... 9 => "a few",
|
||||
_ => "lots"
|
||||
};
|
||||
```
|
||||
|
||||
Range patterns only work on scalar types (like integers and characters; not
|
||||
like arrays and structs, which have sub-components). A range pattern may not
|
||||
be a sub-range of another range pattern inside the same `match`.
|
||||
|
||||
Finally, match patterns can accept *pattern guards* to further refine the
|
||||
criteria for matching a case. Pattern guards appear after the pattern and
|
||||
consist of a bool-typed expression following the `if` keyword. A pattern guard
|
||||
may refer to the variables bound within the pattern they follow.
|
||||
|
||||
```
|
||||
# let maybe_digit = Some(0);
|
||||
# fn process_digit(i: i32) { }
|
||||
# fn process_other(i: i32) { }
|
||||
|
||||
let message = match maybe_digit {
|
||||
Some(x) if x < 10 => process_digit(x),
|
||||
Some(x) => process_other(x),
|
||||
None => panic!(),
|
||||
};
|
||||
```
|
||||
|
||||
## `if let` expressions
|
||||
|
||||
An `if let` expression is semantically 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");
|
||||
|
||||
// this body will be skipped because the pattern is refuted
|
||||
if let ("Bacon", b) = dish {
|
||||
println!("Bacon is served with {}", b);
|
||||
}
|
||||
|
||||
// this body will execute
|
||||
if let ("Ham", b) = dish {
|
||||
println!("Ham is served with {}", b);
|
||||
}
|
||||
```
|
||||
|
||||
## `while let` loops
|
||||
|
||||
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 are denoted with the keyword `return`. Evaluating a `return`
|
||||
expression moves its argument into the designated output location for the
|
||||
current function call, destroys the current function activation frame, and
|
||||
transfers control to the caller frame.
|
||||
|
||||
An example of a `return` expression:
|
||||
|
||||
```
|
||||
fn max(a: i32, b: i32) -> i32 {
|
||||
if a > b {
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
```
|
||||
24
src/doc/reference/src/identifiers.md
Normal file
24
src/doc/reference/src/identifiers.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Identifiers
|
||||
|
||||
An identifier is any nonempty Unicode[^non_ascii_idents] string of the following form:
|
||||
|
||||
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].
|
||||
|
||||
> **Note**: `XID_start` and `XID_continue` as character properties cover the
|
||||
> character ranges used to form the more familiar C and Java language-family
|
||||
> identifiers.
|
||||
|
||||
[keywords]: ../grammar.html#keywords
|
||||
[^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature
|
||||
gated. This is expected to improve soon.
|
||||
22
src/doc/reference/src/influences.md
Normal file
22
src/doc/reference/src/influences.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Influences
|
||||
|
||||
Rust is not a particularly original language, with design elements coming from
|
||||
a wide range of sources. Some of these are listed below (including elements
|
||||
that have since been removed):
|
||||
|
||||
* SML, OCaml: algebraic data types, pattern matching, type inference,
|
||||
semicolon statement separation
|
||||
* C++: references, RAII, smart pointers, move semantics, monomorphization,
|
||||
memory model
|
||||
* ML Kit, Cyclone: region based memory management
|
||||
* Haskell (GHC): typeclasses, type families
|
||||
* Newsqueak, Alef, Limbo: channels, concurrency
|
||||
* Erlang: message passing, thread failure, <strike>linked thread failure</strike>,
|
||||
<strike>lightweight concurrency</strike>
|
||||
* Swift: optional bindings
|
||||
* Scheme: hygienic macros
|
||||
* C#: attributes
|
||||
* Ruby: <strike>block syntax</strike>
|
||||
* NIL, Hermes: <strike>typestate</strike>
|
||||
* [Unicode Annex #31](http://www.unicode.org/reports/tr31/): identifier and
|
||||
pattern syntax
|
||||
10
src/doc/reference/src/input-format.md
Normal file
10
src/doc/reference/src/input-format.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Input format
|
||||
|
||||
Rust input is interpreted as a sequence of Unicode code points encoded in UTF-8.
|
||||
Most Rust grammar rules are defined in terms of printable ASCII-range
|
||||
code points, but a small number are defined in terms of Unicode properties or
|
||||
explicit code point lists. [^inputformat]
|
||||
|
||||
[^inputformat]: Substitute definitions for the special Unicode productions are
|
||||
provided to the grammar verifier, restricted to ASCII range, when verifying the
|
||||
grammar in this document.
|
||||
31
src/doc/reference/src/introduction.md
Normal file
31
src/doc/reference/src/introduction.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Introduction
|
||||
|
||||
This document is the primary reference for the Rust programming language. It
|
||||
provides three kinds of material:
|
||||
|
||||
- Chapters that informally describe each language construct and their use.
|
||||
- Chapters that informally describe the memory model, concurrency model,
|
||||
runtime services, linkage model and debugging facilities.
|
||||
- Appendix chapters providing rationale and references to languages that
|
||||
influenced the design.
|
||||
|
||||
This document does not serve as an introduction to the language. Background
|
||||
familiarity with the language is assumed. A separate [book] is available to
|
||||
help acquire such background familiarity.
|
||||
|
||||
This document also does not serve as a reference to the [standard] library
|
||||
included in the language distribution. Those libraries are documented
|
||||
separately by extracting documentation attributes from their source code. Many
|
||||
of the features that one might expect to be language features are library
|
||||
features in Rust, so what you're looking for may be there, not here.
|
||||
|
||||
Finally, this document is not normative. It may include details that are
|
||||
specific to `rustc` itself, and should not be taken as a specification for
|
||||
the Rust language. We intend to produce such a document someday, but this
|
||||
is what we have for now.
|
||||
|
||||
You may also be interested in the [grammar].
|
||||
|
||||
[book]: ../book/index.html
|
||||
[standard]: ../std/index.html
|
||||
[grammar]: ../grammar.html
|
||||
7
src/doc/reference/src/items-and-attributes.md
Normal file
7
src/doc/reference/src/items-and-attributes.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Items and attributes
|
||||
|
||||
Crates contain [items], each of which may have some number of
|
||||
[attributes] attached to it.
|
||||
|
||||
[items]: items.html
|
||||
[attributes]: attributes.html
|
||||
1091
src/doc/reference/src/items.md
Normal file
1091
src/doc/reference/src/items.md
Normal file
File diff suppressed because it is too large
Load diff
1
src/doc/reference/src/lexical-structure.md
Normal file
1
src/doc/reference/src/lexical-structure.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Lexical structure
|
||||
127
src/doc/reference/src/linkage.md
Normal file
127
src/doc/reference/src/linkage.md
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
# Linkage
|
||||
|
||||
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].
|
||||
|
||||
[ffi]: ../book/ffi.html
|
||||
|
||||
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 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
|
||||
produced. This requires that there is a `main` function in the crate which
|
||||
will be run when the program begins executing. This will link in all Rust and
|
||||
native dependencies, producing a distributable binary.
|
||||
|
||||
* `--crate-type=lib`, `#[crate_type = "lib"]` - A Rust library will be produced.
|
||||
This is an ambiguous concept as to what exactly is produced because a library
|
||||
can manifest itself in several forms. The purpose of this generic `lib` option
|
||||
is to generate the "compiler recommended" style of library. The output library
|
||||
will always be usable by rustc, but the actual type of library may change from
|
||||
time-to-time. The remaining output types are all different flavors of
|
||||
libraries, and the `lib` type can be seen as an alias for one of them (but the
|
||||
actual one is compiler-defined).
|
||||
|
||||
* `--crate-type=dylib`, `#[crate_type = "dylib"]` - A dynamic Rust library will
|
||||
be produced. This is different from the `lib` output type in that this forces
|
||||
dynamic library generation. The resulting dynamic library can be used as a
|
||||
dependency for other libraries and/or executables. This output type will
|
||||
create `*.so` files on linux, `*.dylib` files on osx, and `*.dll` files on
|
||||
windows.
|
||||
|
||||
* `--crate-type=staticlib`, `#[crate_type = "staticlib"]` - A static system
|
||||
library will be produced. This is different from other library outputs in that
|
||||
the Rust compiler will never attempt to link to `staticlib` outputs. The
|
||||
purpose of this output type is to create a static library containing all of
|
||||
the local crate's code along with all upstream dependencies. The static
|
||||
library is actually a `*.a` archive on linux and osx and a `*.lib` file on
|
||||
windows. This format is recommended for use in situations such as linking
|
||||
Rust code into an existing non-Rust application because it will not have
|
||||
dynamic dependencies on other Rust code.
|
||||
|
||||
* `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system
|
||||
library will be produced. This is used when compiling Rust code as
|
||||
a dynamic library to be loaded from another language. This output type will
|
||||
create `*.so` files on Linux, `*.dylib` files on OSX, and `*.dll` files on
|
||||
Windows.
|
||||
|
||||
* `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be
|
||||
produced. This is used as an intermediate artifact and can be thought of as a
|
||||
"static Rust library". These `rlib` files, unlike `staticlib` files, are
|
||||
interpreted by the Rust compiler in future linkage. This essentially means
|
||||
that `rustc` will look for metadata in `rlib` files like it looks for metadata
|
||||
in dynamic libraries. This form of output is used to produce statically linked
|
||||
executables as well as `staticlib` outputs.
|
||||
|
||||
* `--crate-type=proc-macro`, `#[crate_type = "proc-macro"]` - The output
|
||||
produced is not specified, but if a `-L` path is provided to it then the
|
||||
compiler will recognize the output artifacts as a macro and it can be loaded
|
||||
for a program. If a crate is compiled with the `proc-macro` crate type it
|
||||
will forbid exporting any items in the crate other than those functions
|
||||
tagged `#[proc_macro_derive]` and those functions must also be placed at the
|
||||
crate root. Finally, the compiler will automatically set the
|
||||
`cfg(proc_macro)` annotation whenever any crate type of a compilation is the
|
||||
`proc-macro` crate type.
|
||||
|
||||
Note that these outputs are stackable in the sense that if multiple are
|
||||
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 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
|
||||
the compiler could find B in various different forms throughout the system. The
|
||||
only forms looked for by the compiler, however, are the `rlib` format and the
|
||||
dynamic library format. With these two options for a dependent library, the
|
||||
compiler must at some point make a choice between these two formats. With this
|
||||
in mind, the compiler follows these rules when determining what format of
|
||||
dependencies will be used:
|
||||
|
||||
1. If a static library is being produced, all upstream dependencies are
|
||||
required to be available in `rlib` formats. This requirement stems from the
|
||||
reason that a dynamic library cannot be converted into a static format.
|
||||
|
||||
Note that it is impossible to link in native dynamic dependencies to a static
|
||||
library, and in this case warnings will be printed about all unlinked native
|
||||
dynamic dependencies.
|
||||
|
||||
2. If an `rlib` file is being produced, then there are no restrictions on what
|
||||
format the upstream dependencies are available in. It is simply required that
|
||||
all upstream dependencies be available for reading metadata from.
|
||||
|
||||
The reason for this is that `rlib` files do not contain any of their upstream
|
||||
dependencies. It wouldn't be very efficient for all `rlib` files to contain a
|
||||
copy of `libstd.rlib`!
|
||||
|
||||
3. If an executable is being produced and the `-C prefer-dynamic` flag is not
|
||||
specified, then dependencies are first attempted to be found in the `rlib`
|
||||
format. If some dependencies are not available in an rlib format, then
|
||||
dynamic linking is attempted (see below).
|
||||
|
||||
4. If a dynamic library or an executable that is being dynamically linked is
|
||||
being produced, then the compiler will attempt to reconcile the available
|
||||
dependencies in either the rlib or dylib format to create a final product.
|
||||
|
||||
A major goal of the compiler is to ensure that a library never appears more
|
||||
than once in any artifact. For example, if dynamic libraries B and C were
|
||||
each statically linked to library A, then a crate could not link to B and C
|
||||
together because there would be two copies of A. The compiler allows mixing
|
||||
the rlib and dylib formats, but this restriction must be satisfied.
|
||||
|
||||
The compiler currently implements no method of hinting what format a library
|
||||
should be linked with. When dynamically linking, the compiler will attempt to
|
||||
maximize dynamic dependencies while still allowing some dependencies to be
|
||||
linked in via an rlib.
|
||||
|
||||
For most situations, having all libraries available as a dylib is recommended
|
||||
if dynamically linking. For other situations, the compiler will emit a
|
||||
warning if it is unable to determine which formats to link each library with.
|
||||
|
||||
In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for
|
||||
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.
|
||||
88
src/doc/reference/src/macros-by-example.md
Normal file
88
src/doc/reference/src/macros-by-example.md
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# Macros By Example
|
||||
|
||||
`macro_rules` allows users to define syntax extension in a declarative way. We
|
||||
call such extensions "macros by example" or simply "macros".
|
||||
|
||||
Currently, macros can expand to expressions, statements, items, or patterns.
|
||||
|
||||
(A `sep_token` is any token other than `*` and `+`. A `non_special_token` is
|
||||
any token other than a delimiter or `$`.)
|
||||
|
||||
The macro expander looks up macro invocations by name, and tries each macro
|
||||
rule in turn. It transcribes the first successful match. Matching and
|
||||
transcription are closely related to each other, and we will describe them
|
||||
together.
|
||||
|
||||
The macro expander matches and transcribes every token that does not begin with
|
||||
a `$` literally, including delimiters. For parsing reasons, delimiters must be
|
||||
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`: an [item]
|
||||
* `block`: a [block]
|
||||
* `stmt`: a [statement]
|
||||
* `pat`: a [pattern]
|
||||
* `expr`: an [expression]
|
||||
* `ty`: a [type]
|
||||
* `ident`: an [identifier]
|
||||
* `path`: a [path]
|
||||
* `tt`: a token tree (a single [token] by matching `()`, `[]`, or `{}`)
|
||||
* `meta`: the contents of an [attribute]
|
||||
|
||||
[item]: items.html
|
||||
[block]: expressions.html#block-expressions
|
||||
[statement]: statements.html
|
||||
[pattern]: expressions.html#match-expressions
|
||||
[expression]: expressions.html
|
||||
[type]: types.html
|
||||
[identifier]: identifiers.html
|
||||
[path]: paths.html
|
||||
[token]: tokens.html
|
||||
[attribute]: attributes.html
|
||||
|
||||
In the transcriber, the
|
||||
designator is already known, and so only the name of a matched nonterminal comes
|
||||
after the dollar sign.
|
||||
|
||||
In both the matcher and transcriber, the Kleene star-like operator indicates
|
||||
repetition. The Kleene star operator consists of `$` and parentheses, optionally
|
||||
followed by a separator token, followed by `*` or `+`. `*` means zero or more
|
||||
repetitions, `+` means at least one repetition. The parentheses are not matched or
|
||||
transcribed. On the matcher side, a name is bound to _all_ of the names it
|
||||
matches, in a structure that mimics the structure of the repetition encountered
|
||||
on a successful match. The job of the transcriber is to sort that structure
|
||||
out.
|
||||
|
||||
The rules for transcription of these repetitions are called "Macro By Example".
|
||||
Essentially, one "layer" of repetition is discharged at a time, and all of them
|
||||
must be discharged by the time a name is transcribed. Therefore, `( $( $i:ident
|
||||
),* ) => ( $i )` is an invalid macro, but `( $( $i:ident ),* ) => ( $( $i:ident
|
||||
),* )` is acceptable (if trivial).
|
||||
|
||||
When Macro By Example encounters a repetition, it examines all of the `$`
|
||||
_name_ s that occur in its body. At the "current layer", they all must repeat
|
||||
the same number of times, so ` ( $( $i:ident ),* ; $( $j:ident ),* ) => ( $(
|
||||
($i,$j) ),* )` is valid if given the argument `(a,b,c ; d,e,f)`, but not
|
||||
`(a,b,c ; d,e)`. The repetition walks through the choices at that layer in
|
||||
lockstep, so the former input transcribes to `(a,d), (b,e), (c,f)`.
|
||||
|
||||
Nested repetitions are allowed.
|
||||
|
||||
### Parsing limitations
|
||||
|
||||
The parser used by the macro system is reasonably powerful, but the parsing of
|
||||
Rust syntax is restricted in two ways:
|
||||
|
||||
1. Macro definitions are required to include suitable separators after parsing
|
||||
expressions and other bits of the Rust grammar. This implies that
|
||||
a macro definition like `$i:expr [ , ]` is not legal, because `[` could be part
|
||||
of an expression. A macro definition like `$i:expr,` or `$i:expr;` would be legal,
|
||||
however, because `,` and `;` are legal separators. See [RFC 550] for more information.
|
||||
2. The parser must have eliminated all ambiguity by the time it reaches a `$`
|
||||
_name_ `:` _designator_. This requirement most often affects name-designator
|
||||
pairs when they occur at the beginning of, or immediately after, a `$(...)*`;
|
||||
requiring a distinctive token in front can solve the problem.
|
||||
|
||||
[RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md
|
||||
17
src/doc/reference/src/macros.md
Normal file
17
src/doc/reference/src/macros.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Macros
|
||||
|
||||
A number of minor features of Rust are not central enough to have their own
|
||||
syntax, and yet are not implementable as functions. Instead, they are given
|
||||
names, and invoked through a consistent syntax: `some_extension!(...)`.
|
||||
|
||||
Users of `rustc` can define new macros in two ways:
|
||||
|
||||
* [Macros] define new syntax in a higher-level,
|
||||
declarative way.
|
||||
* [Procedural Macros] can be used to implement custom derive.
|
||||
|
||||
And one unstable way: [compiler plugins].
|
||||
|
||||
[Macros]: ../book/macros.html
|
||||
[Procedural Macros]: ../book/procedural-macros.html
|
||||
[compiler plugins]: ../book/compiler-plugins.html
|
||||
13
src/doc/reference/src/memory-allocation-and-lifetime.md
Normal file
13
src/doc/reference/src/memory-allocation-and-lifetime.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Memory allocation and lifetime
|
||||
|
||||
The _items_ of a program are those functions, modules and types that have their
|
||||
value calculated at compile-time and stored uniquely in the memory image of the
|
||||
rust process. Items are neither dynamically allocated nor freed.
|
||||
|
||||
The _heap_ is a general term that describes boxes. The lifetime of an
|
||||
allocation in the heap depends on the lifetime of the box values pointing to
|
||||
it. Since box values may themselves be passed in and out of frames, or stored
|
||||
in the heap, heap allocations may outlive the frame they are allocated within.
|
||||
An allocation in the heap is guaranteed to reside at a single location in the
|
||||
heap for the whole lifetime of the allocation - it will never be relocated as
|
||||
a result of moving a box value.
|
||||
10
src/doc/reference/src/memory-model.md
Normal file
10
src/doc/reference/src/memory-model.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Memory model
|
||||
|
||||
A Rust program's memory consists of a static set of *items* and a *heap*.
|
||||
Immutable portions of the heap may be safely shared between threads, mutable
|
||||
portions may not be safely shared, but several mechanisms for effectively-safe
|
||||
sharing of mutable values, built on unsafe code but enforcing a safe locking
|
||||
discipline, exist in the standard library.
|
||||
|
||||
Allocations in the stack consist of *variables*, and allocations in the heap
|
||||
consist of *boxes*.
|
||||
4
src/doc/reference/src/memory-ownership.md
Normal file
4
src/doc/reference/src/memory-ownership.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
## Memory ownership
|
||||
|
||||
When a stack frame is exited, its local allocations are all released, and its
|
||||
references to boxes are dropped.
|
||||
1
src/doc/reference/src/notation.md
Normal file
1
src/doc/reference/src/notation.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Notation
|
||||
105
src/doc/reference/src/paths.md
Normal file
105
src/doc/reference/src/paths.md
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# Paths
|
||||
|
||||
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] or a [variable] in a local control
|
||||
scope. If a path has multiple components, it refers to an item.
|
||||
|
||||
[item]: items.html
|
||||
[variable]: variables.html
|
||||
|
||||
Every item has a _canonical path_ within its crate, but the path naming an item
|
||||
is only meaningful within a given crate. There is no global namespace across
|
||||
crates; an item's canonical path merely identifies it within the crate.
|
||||
|
||||
Two examples of simple paths consisting of only identifier components:
|
||||
|
||||
```{.ignore}
|
||||
x;
|
||||
x::y::z;
|
||||
```
|
||||
|
||||
Path components are usually [identifiers], but they may
|
||||
also include angle-bracket-enclosed lists of type arguments. In
|
||||
[expression] context, the type argument list is given
|
||||
after a `::` namespace qualifier in order to disambiguate it from a
|
||||
relational expression involving the less-than symbol (`<`). In type
|
||||
expression context, the final namespace qualifier is omitted.
|
||||
|
||||
[identifiers]: identifiers.html
|
||||
[expression]: expressions.html
|
||||
|
||||
Two examples of paths with type arguments:
|
||||
|
||||
```rust
|
||||
# struct HashMap<K, V>(K,V);
|
||||
# fn f() {
|
||||
# fn id<T>(t: T) -> T { t }
|
||||
type T = HashMap<i32,String>; // Type arguments used in a type expression
|
||||
let x = id::<i32>(10); // Type arguments used in a call expression
|
||||
# }
|
||||
```
|
||||
|
||||
Paths can be denoted with various leading qualifiers to change the meaning of
|
||||
how it is resolved:
|
||||
|
||||
* Paths starting with `::` are considered to be global paths where the
|
||||
components of the path start being resolved from the crate root. Each
|
||||
identifier in the path must resolve to an item.
|
||||
|
||||
```rust
|
||||
mod a {
|
||||
pub fn foo() {}
|
||||
}
|
||||
mod b {
|
||||
pub fn foo() {
|
||||
::a::foo(); // call a's foo function
|
||||
}
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
* Paths starting with the keyword `super` begin resolution relative to the
|
||||
parent module. Each further identifier must resolve to an item.
|
||||
|
||||
```rust
|
||||
mod a {
|
||||
pub fn foo() {}
|
||||
}
|
||||
mod b {
|
||||
pub fn foo() {
|
||||
super::a::foo(); // call a's foo function
|
||||
}
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
* Paths starting with the keyword `self` begin resolution relative to the
|
||||
current module. Each further identifier must resolve to an item.
|
||||
|
||||
```rust
|
||||
fn foo() {}
|
||||
fn bar() {
|
||||
self::foo();
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
Additionally keyword `super` may be repeated several times after the first
|
||||
`super` or `self` to refer to ancestor modules.
|
||||
|
||||
```rust
|
||||
mod a {
|
||||
fn foo() {}
|
||||
|
||||
mod b {
|
||||
mod c {
|
||||
fn foo() {
|
||||
super::super::foo(); // call a's foo function
|
||||
self::super::super::foo(); // call a's foo function
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
23
src/doc/reference/src/procedural-macros.md
Normal file
23
src/doc/reference/src/procedural-macros.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
## Procedural Macros
|
||||
|
||||
"Procedural macros" are the second way to implement a macro. For now, the only
|
||||
thing they can be used for is to implement derive on your own types. See
|
||||
[the book][procedural macros] for a tutorial.
|
||||
|
||||
[procedural macros]: ../book/procedural-macros.html
|
||||
|
||||
Procedural macros involve a few different parts of the language and its
|
||||
standard libraries. First is the `proc_macro` crate, included with Rust,
|
||||
that defines an interface for building a procedural macro. The
|
||||
`#[proc_macro_derive(Foo)]` attribute is used to mark the deriving
|
||||
function. This function must have the type signature:
|
||||
|
||||
```rust,ignore
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro_derive(Hello)]
|
||||
pub fn hello_world(input: TokenStream) -> TokenStream
|
||||
```
|
||||
|
||||
Finally, procedural macros must be in their own crate, with the `proc-macro`
|
||||
crate type.
|
||||
3
src/doc/reference/src/special-traits.md
Normal file
3
src/doc/reference/src/special-traits.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Special traits
|
||||
|
||||
Several traits define special evaluation behavior.
|
||||
11
src/doc/reference/src/statements-and-expressions.md
Normal file
11
src/doc/reference/src/statements-and-expressions.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Statements and expressions
|
||||
|
||||
Rust is _primarily_ an expression language. This means that most forms of
|
||||
value-producing or effect-causing evaluation are directed by the uniform syntax
|
||||
category of _expressions_. Each kind of expression can typically _nest_ within
|
||||
each other kind of expression, and rules for evaluation of expressions involve
|
||||
specifying both the value produced by the expression and the order in which its
|
||||
sub-expressions are themselves evaluated.
|
||||
|
||||
In contrast, statements in Rust serve _mostly_ to contain and explicitly
|
||||
sequence expression evaluation.
|
||||
42
src/doc/reference/src/statements.md
Normal file
42
src/doc/reference/src/statements.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Statements
|
||||
|
||||
A _statement_ is a component of a block, which is in turn a component of an
|
||||
outer [expression](expressions.html) or [function](items.html#functions).
|
||||
|
||||
Rust has two kinds of statement: [declaration
|
||||
statements](#declaration-statements) and [expression
|
||||
statements](#expression-statements).
|
||||
|
||||
## Declaration statements
|
||||
|
||||
A _declaration statement_ is one that introduces one or more *names* into the
|
||||
enclosing statement block. The declared names may denote new variables or new
|
||||
items.
|
||||
|
||||
### Item declarations
|
||||
|
||||
An _item declaration statement_ has a syntactic form identical to an
|
||||
[item](items.html) declaration within a module. Declaring an item — a
|
||||
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.
|
||||
|
||||
### `let` statements
|
||||
|
||||
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.
|
||||
Any variables introduced by a variable declaration are visible from the point of
|
||||
declaration until the end of the enclosing block scope.
|
||||
|
||||
## Expression statements
|
||||
|
||||
An _expression statement_ is one that evaluates an [expression](expressions.html)
|
||||
and ignores its result. The type of an expression statement `e;` is always
|
||||
`()`, regardless of the type of `e`. As a rule, an expression statement's
|
||||
purpose is to trigger the effects of evaluating its expression.
|
||||
18
src/doc/reference/src/string-table-productions.md
Normal file
18
src/doc/reference/src/string-table-productions.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# String table productions
|
||||
|
||||
Some rules in the grammar — notably [unary
|
||||
operators], [binary operators], and [keywords][keywords] — are
|
||||
given in a simplified form: as a listing of a table of unquoted, printable
|
||||
whitespace-separated strings. These cases form a subset of the rules regarding
|
||||
the [token][tokens] rule, and are assumed to be the result of a
|
||||
lexical-analysis phase feeding the parser, driven by a DFA, operating over the
|
||||
disjunction of all such string table entries.
|
||||
|
||||
When such a string enclosed in double-quotes (`"`) occurs inside the grammar,
|
||||
it is an implicit reference to a single member of such a string table
|
||||
production. See [tokens] for more information.
|
||||
|
||||
[binary operators]: expressions.html#binary-operator-expressions
|
||||
[keywords]: ../grammar.html#keywords
|
||||
[tokens]: tokens.html
|
||||
[unary operators]: expressions.html#unary-operator-expressions
|
||||
19
src/doc/reference/src/subtyping.md
Normal file
19
src/doc/reference/src/subtyping.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Subtyping
|
||||
|
||||
Subtyping is implicit and can occur at any stage in type checking or
|
||||
inference. Subtyping in Rust is very restricted and occurs only due to
|
||||
variance with respect to lifetimes and between types with higher ranked
|
||||
lifetimes. If we were to erase lifetimes from types, then the only subtyping
|
||||
would be due to type equality.
|
||||
|
||||
Consider the following example: string literals always have `'static`
|
||||
lifetime. Nevertheless, we can assign `s` to `t`:
|
||||
|
||||
```
|
||||
fn bar<'a>() {
|
||||
let s: &'static str = "hi";
|
||||
let t: &'a str = s;
|
||||
}
|
||||
```
|
||||
Since `'static` "lives longer" than `'a`, `&'static str` is a subtype of
|
||||
`&'a str`.
|
||||
4
src/doc/reference/src/the-copy-trait.md
Normal file
4
src/doc/reference/src/the-copy-trait.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# The `Copy` trait
|
||||
|
||||
The `Copy` trait changes the semantics of a type implementing it. Values whose
|
||||
type implements `Copy` are copied rather than moved upon assignment.
|
||||
7
src/doc/reference/src/the-deref-trait.md
Normal file
7
src/doc/reference/src/the-deref-trait.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# The `Deref` trait
|
||||
|
||||
The `Deref<Target = U>` trait allows a type to implicitly implement all the methods
|
||||
of the type `U`. When attempting to resolve a method call, the compiler will search
|
||||
the top-level type for the implementation of the called method. If no such method is
|
||||
found, `.deref()` is called and the compiler continues to search for the method
|
||||
implementation in the returned type `U`.
|
||||
4
src/doc/reference/src/the-drop-trait.md
Normal file
4
src/doc/reference/src/the-drop-trait.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# The `Drop` trait
|
||||
|
||||
The `Drop` trait provides a destructor, to be run whenever a value of this type
|
||||
is to be destroyed.
|
||||
4
src/doc/reference/src/the-send-trait.md
Normal file
4
src/doc/reference/src/the-send-trait.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# The `Send` trait
|
||||
|
||||
The `Send` trait indicates that a value of this type is safe to send from one
|
||||
thread to another.
|
||||
3
src/doc/reference/src/the-sized-trait.md
Normal file
3
src/doc/reference/src/the-sized-trait.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# The `Sized` trait
|
||||
|
||||
The `Sized` trait indicates that the size of this type is known at compile-time.
|
||||
4
src/doc/reference/src/the-sync-trait.md
Normal file
4
src/doc/reference/src/the-sync-trait.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# The `Sync` trait
|
||||
|
||||
The `Sync` trait indicates that a value of this type is safe to share between
|
||||
multiple threads.
|
||||
798
src/doc/reference/src/theme/book.css
Normal file
798
src/doc/reference/src/theme/book.css
Normal file
|
|
@ -0,0 +1,798 @@
|
|||
html,
|
||||
body {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
color: #333;
|
||||
}
|
||||
.left {
|
||||
float: left;
|
||||
}
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
h2,
|
||||
h3 {
|
||||
margin-top: 2.5em;
|
||||
}
|
||||
h4,
|
||||
h5 {
|
||||
margin-top: 2em;
|
||||
}
|
||||
.header + .header h3,
|
||||
.header + .header h4,
|
||||
.header + .header h5 {
|
||||
margin-top: 1em;
|
||||
}
|
||||
table {
|
||||
margin: 0 auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table td {
|
||||
padding: 3px 20px;
|
||||
border: 1px solid;
|
||||
}
|
||||
table thead td {
|
||||
font-weight: 700;
|
||||
}
|
||||
.sidebar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
overflow-y: auto;
|
||||
padding: 10px 10px;
|
||||
font-size: 0.875em;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
-webkit-transition: left 0.5s;
|
||||
-moz-transition: left 0.5s;
|
||||
-o-transition: left 0.5s;
|
||||
-ms-transition: left 0.5s;
|
||||
transition: left 0.5s;
|
||||
}
|
||||
@media only screen and (max-width: 1060px) {
|
||||
.sidebar {
|
||||
left: -300px;
|
||||
}
|
||||
}
|
||||
.sidebar code {
|
||||
line-height: 2em;
|
||||
}
|
||||
.sidebar-hidden .sidebar {
|
||||
left: -300px;
|
||||
}
|
||||
.sidebar-visible .sidebar {
|
||||
left: 0;
|
||||
}
|
||||
.chapter {
|
||||
list-style: none outside none;
|
||||
padding-left: 0;
|
||||
line-height: 1.9em;
|
||||
}
|
||||
.chapter li a {
|
||||
padding: 5px 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
.chapter li a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.chapter .spacer {
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
.section {
|
||||
list-style: none outside none;
|
||||
padding-left: 20px;
|
||||
line-height: 2.5em;
|
||||
}
|
||||
.section li {
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.page-wrapper {
|
||||
position: absolute;
|
||||
overflow-y: auto;
|
||||
left: 315px;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
min-height: 100%;
|
||||
-webkit-transition: left 0.5s;
|
||||
-moz-transition: left 0.5s;
|
||||
-o-transition: left 0.5s;
|
||||
-ms-transition: left 0.5s;
|
||||
transition: left 0.5s;
|
||||
}
|
||||
@media only screen and (max-width: 1060px) {
|
||||
.page-wrapper {
|
||||
left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
.sidebar-hidden .page-wrapper {
|
||||
left: 15px;
|
||||
}
|
||||
.sidebar-visible .page-wrapper {
|
||||
left: 315px;
|
||||
}
|
||||
.page {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding-right: 15px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.content {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 750px;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.content a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.content a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.content img {
|
||||
max-width: 100%;
|
||||
}
|
||||
.menu-bar {
|
||||
position: relative;
|
||||
height: 50px;
|
||||
}
|
||||
.menu-bar i {
|
||||
position: relative;
|
||||
margin: 0 10px;
|
||||
z-index: 10;
|
||||
line-height: 50px;
|
||||
-webkit-transition: color 0.5s;
|
||||
-moz-transition: color 0.5s;
|
||||
-o-transition: color 0.5s;
|
||||
-ms-transition: color 0.5s;
|
||||
transition: color 0.5s;
|
||||
}
|
||||
.menu-bar i:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.menu-bar .left-buttons {
|
||||
float: left;
|
||||
}
|
||||
.menu-bar .right-buttons {
|
||||
float: right;
|
||||
}
|
||||
.menu-title {
|
||||
display: inline-block;
|
||||
font-weight: 200;
|
||||
font-size: 20px;
|
||||
line-height: 50px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
|
||||
filter: alpha(opacity=0);
|
||||
-webkit-transition: opacity 0.5s ease-in-out;
|
||||
-moz-transition: opacity 0.5s ease-in-out;
|
||||
-o-transition: opacity 0.5s ease-in-out;
|
||||
-ms-transition: opacity 0.5s ease-in-out;
|
||||
transition: opacity 0.5s ease-in-out;
|
||||
}
|
||||
.menu-bar:hover .menu-title {
|
||||
opacity: 1;
|
||||
-ms-filter: none;
|
||||
filter: none;
|
||||
}
|
||||
.nav-chapters {
|
||||
font-size: 2.5em;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
position: absolute;
|
||||
top: 50px /* Height of menu-bar */;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
max-width: 150px;
|
||||
min-width: 90px;
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: box;
|
||||
display: flex;
|
||||
-webkit-box-pack: center;
|
||||
-moz-box-pack: center;
|
||||
-o-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
-ms-flex-line-pack: center;
|
||||
-webkit-align-content: center;
|
||||
align-content: center;
|
||||
-webkit-box-orient: vertical;
|
||||
-moz-box-orient: vertical;
|
||||
-o-box-orient: vertical;
|
||||
-webkit-flex-direction: column;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-transition: color 0.5s;
|
||||
-moz-transition: color 0.5s;
|
||||
-o-transition: color 0.5s;
|
||||
-ms-transition: color 0.5s;
|
||||
transition: color 0.5s;
|
||||
}
|
||||
.mobile-nav-chapters {
|
||||
display: none;
|
||||
}
|
||||
.nav-chapters:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.previous {
|
||||
left: 0;
|
||||
}
|
||||
.next {
|
||||
right: 15px;
|
||||
}
|
||||
.theme-popup {
|
||||
position: relative;
|
||||
left: 10px;
|
||||
z-index: 1000;
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.7em;
|
||||
}
|
||||
.theme-popup .theme {
|
||||
margin: 0;
|
||||
padding: 2px 10px;
|
||||
line-height: 25px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.theme-popup .theme:hover:first-child {
|
||||
border-top-left-radius: inherit;
|
||||
border-top-right-radius: inherit;
|
||||
}
|
||||
.theme-popup .theme:hover:last-child {
|
||||
border-bottom-left-radius: inherit;
|
||||
border-bottom-right-radius: inherit;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1250px) {
|
||||
.nav-chapters {
|
||||
display: none;
|
||||
}
|
||||
.mobile-nav-chapters {
|
||||
font-size: 2.5em;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
max-width: 150px;
|
||||
min-width: 90px;
|
||||
-webkit-box-pack: center;
|
||||
-moz-box-pack: center;
|
||||
-o-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
-ms-flex-line-pack: center;
|
||||
-webkit-align-content: center;
|
||||
align-content: center;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-bottom: 50px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.next {
|
||||
float: right;
|
||||
}
|
||||
.previous {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
.light {
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
/* Inline code */
|
||||
}
|
||||
.light .content .header:link,
|
||||
.light .content .header:visited {
|
||||
color: #333;
|
||||
pointer: cursor;
|
||||
}
|
||||
.light .content .header:link:hover,
|
||||
.light .content .header:visited:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.light .sidebar {
|
||||
background-color: #fafafa;
|
||||
color: #364149;
|
||||
}
|
||||
.light .chapter li {
|
||||
color: #aaa;
|
||||
}
|
||||
.light .chapter li a {
|
||||
color: #364149;
|
||||
}
|
||||
.light .chapter li .active,
|
||||
.light .chapter li a:hover {
|
||||
/* Animate color change */
|
||||
color: #008cff;
|
||||
}
|
||||
.light .chapter .spacer {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.light .menu-bar,
|
||||
.light .menu-bar:visited,
|
||||
.light .nav-chapters,
|
||||
.light .nav-chapters:visited,
|
||||
.light .mobile-nav-chapters,
|
||||
.light .mobile-nav-chapters:visited {
|
||||
color: #ccc;
|
||||
}
|
||||
.light .menu-bar i:hover,
|
||||
.light .nav-chapters:hover,
|
||||
.light .mobile-nav-chapters i:hover {
|
||||
color: #333;
|
||||
}
|
||||
.light .mobile-nav-chapters i:hover {
|
||||
color: #364149;
|
||||
}
|
||||
.light .mobile-nav-chapters {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
.light .content a:link,
|
||||
.light a:visited {
|
||||
color: #4183c4;
|
||||
}
|
||||
.light .theme-popup {
|
||||
color: #333;
|
||||
background: #fafafa;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.light .theme-popup .theme:hover {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.light .theme-popup .default {
|
||||
color: #ccc;
|
||||
}
|
||||
.light blockquote {
|
||||
margin: 20px 0;
|
||||
padding: 0 20px;
|
||||
color: #333;
|
||||
background-color: #f2f7f9;
|
||||
border-top: 0.1em solid #e1edf1;
|
||||
border-bottom: 0.1em solid #e1edf1;
|
||||
}
|
||||
.light table td {
|
||||
border-color: #f2f2f2;
|
||||
}
|
||||
.light table tbody tr:nth-child(2n) {
|
||||
background: #f7f7f7;
|
||||
}
|
||||
.light table thead {
|
||||
background: #ccc;
|
||||
}
|
||||
.light table thead td {
|
||||
border: none;
|
||||
}
|
||||
.light table thead tr {
|
||||
border: 1px #ccc solid;
|
||||
}
|
||||
.light :not(pre) > .hljs {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 0.1em 0.3em;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.light pre {
|
||||
position: relative;
|
||||
}
|
||||
.light pre > .buttons {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
color: #364149;
|
||||
cursor: pointer;
|
||||
}
|
||||
.light pre > .buttons :hover {
|
||||
color: #008cff;
|
||||
}
|
||||
.light pre > .buttons i {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.light pre > .result {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.coal {
|
||||
color: #98a3ad;
|
||||
background-color: #141617;
|
||||
/* Inline code */
|
||||
}
|
||||
.coal .content .header:link,
|
||||
.coal .content .header:visited {
|
||||
color: #98a3ad;
|
||||
pointer: cursor;
|
||||
}
|
||||
.coal .content .header:link:hover,
|
||||
.coal .content .header:visited:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.coal .sidebar {
|
||||
background-color: #292c2f;
|
||||
color: #a1adb8;
|
||||
}
|
||||
.coal .chapter li {
|
||||
color: #505254;
|
||||
}
|
||||
.coal .chapter li a {
|
||||
color: #a1adb8;
|
||||
}
|
||||
.coal .chapter li .active,
|
||||
.coal .chapter li a:hover {
|
||||
/* Animate color change */
|
||||
color: #3473ad;
|
||||
}
|
||||
.coal .chapter .spacer {
|
||||
background-color: #393939;
|
||||
}
|
||||
.coal .menu-bar,
|
||||
.coal .menu-bar:visited,
|
||||
.coal .nav-chapters,
|
||||
.coal .nav-chapters:visited,
|
||||
.coal .mobile-nav-chapters,
|
||||
.coal .mobile-nav-chapters:visited {
|
||||
color: #43484d;
|
||||
}
|
||||
.coal .menu-bar i:hover,
|
||||
.coal .nav-chapters:hover,
|
||||
.coal .mobile-nav-chapters i:hover {
|
||||
color: #b3c0cc;
|
||||
}
|
||||
.coal .mobile-nav-chapters i:hover {
|
||||
color: #a1adb8;
|
||||
}
|
||||
.coal .mobile-nav-chapters {
|
||||
background-color: #292c2f;
|
||||
}
|
||||
.coal .content a:link,
|
||||
.coal a:visited {
|
||||
color: #2b79a2;
|
||||
}
|
||||
.coal .theme-popup {
|
||||
color: #98a3ad;
|
||||
background: #141617;
|
||||
border: 1px solid #43484d;
|
||||
}
|
||||
.coal .theme-popup .theme:hover {
|
||||
background-color: #1f2124;
|
||||
}
|
||||
.coal .theme-popup .default {
|
||||
color: #43484d;
|
||||
}
|
||||
.coal blockquote {
|
||||
margin: 20px 0;
|
||||
padding: 0 20px;
|
||||
color: #98a3ad;
|
||||
background-color: #242637;
|
||||
border-top: 0.1em solid #2c2f44;
|
||||
border-bottom: 0.1em solid #2c2f44;
|
||||
}
|
||||
.coal table td {
|
||||
border-color: #1f2223;
|
||||
}
|
||||
.coal table tbody tr:nth-child(2n) {
|
||||
background: #1b1d1e;
|
||||
}
|
||||
.coal table thead {
|
||||
background: #3f4649;
|
||||
}
|
||||
.coal table thead td {
|
||||
border: none;
|
||||
}
|
||||
.coal table thead tr {
|
||||
border: 1px #3f4649 solid;
|
||||
}
|
||||
.coal :not(pre) > .hljs {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 0.1em 0.3em;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.coal pre {
|
||||
position: relative;
|
||||
}
|
||||
.coal pre > .buttons {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
color: #a1adb8;
|
||||
cursor: pointer;
|
||||
}
|
||||
.coal pre > .buttons :hover {
|
||||
color: #3473ad;
|
||||
}
|
||||
.coal pre > .buttons i {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.coal pre > .result {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.navy {
|
||||
color: #bcbdd0;
|
||||
background-color: #161923;
|
||||
/* Inline code */
|
||||
}
|
||||
.navy .content .header:link,
|
||||
.navy .content .header:visited {
|
||||
color: #bcbdd0;
|
||||
pointer: cursor;
|
||||
}
|
||||
.navy .content .header:link:hover,
|
||||
.navy .content .header:visited:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.navy .sidebar {
|
||||
background-color: #282d3f;
|
||||
color: #c8c9db;
|
||||
}
|
||||
.navy .chapter li {
|
||||
color: #505274;
|
||||
}
|
||||
.navy .chapter li a {
|
||||
color: #c8c9db;
|
||||
}
|
||||
.navy .chapter li .active,
|
||||
.navy .chapter li a:hover {
|
||||
/* Animate color change */
|
||||
color: #2b79a2;
|
||||
}
|
||||
.navy .chapter .spacer {
|
||||
background-color: #2d334f;
|
||||
}
|
||||
.navy .menu-bar,
|
||||
.navy .menu-bar:visited,
|
||||
.navy .nav-chapters,
|
||||
.navy .nav-chapters:visited,
|
||||
.navy .mobile-nav-chapters,
|
||||
.navy .mobile-nav-chapters:visited {
|
||||
color: #737480;
|
||||
}
|
||||
.navy .menu-bar i:hover,
|
||||
.navy .nav-chapters:hover,
|
||||
.navy .mobile-nav-chapters i:hover {
|
||||
color: #b7b9cc;
|
||||
}
|
||||
.navy .mobile-nav-chapters i:hover {
|
||||
color: #c8c9db;
|
||||
}
|
||||
.navy .mobile-nav-chapters {
|
||||
background-color: #282d3f;
|
||||
}
|
||||
.navy .content a:link,
|
||||
.navy a:visited {
|
||||
color: #2b79a2;
|
||||
}
|
||||
.navy .theme-popup {
|
||||
color: #bcbdd0;
|
||||
background: #161923;
|
||||
border: 1px solid #737480;
|
||||
}
|
||||
.navy .theme-popup .theme:hover {
|
||||
background-color: #282e40;
|
||||
}
|
||||
.navy .theme-popup .default {
|
||||
color: #737480;
|
||||
}
|
||||
.navy blockquote {
|
||||
margin: 20px 0;
|
||||
padding: 0 20px;
|
||||
color: #bcbdd0;
|
||||
background-color: #262933;
|
||||
border-top: 0.1em solid #2f333f;
|
||||
border-bottom: 0.1em solid #2f333f;
|
||||
}
|
||||
.navy table td {
|
||||
border-color: #1f2331;
|
||||
}
|
||||
.navy table tbody tr:nth-child(2n) {
|
||||
background: #1b1f2b;
|
||||
}
|
||||
.navy table thead {
|
||||
background: #39415b;
|
||||
}
|
||||
.navy table thead td {
|
||||
border: none;
|
||||
}
|
||||
.navy table thead tr {
|
||||
border: 1px #39415b solid;
|
||||
}
|
||||
.navy :not(pre) > .hljs {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 0.1em 0.3em;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.navy pre {
|
||||
position: relative;
|
||||
}
|
||||
.navy pre > .buttons {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
color: #c8c9db;
|
||||
cursor: pointer;
|
||||
}
|
||||
.navy pre > .buttons :hover {
|
||||
color: #2b79a2;
|
||||
}
|
||||
.navy pre > .buttons i {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.navy pre > .result {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.rust {
|
||||
color: #262625;
|
||||
background-color: #e1e1db;
|
||||
/* Inline code */
|
||||
}
|
||||
.rust .content .header:link,
|
||||
.rust .content .header:visited {
|
||||
color: #262625;
|
||||
pointer: cursor;
|
||||
}
|
||||
.rust .content .header:link:hover,
|
||||
.rust .content .header:visited:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.rust .sidebar {
|
||||
background-color: #3b2e2a;
|
||||
color: #c8c9db;
|
||||
}
|
||||
.rust .chapter li {
|
||||
color: #505254;
|
||||
}
|
||||
.rust .chapter li a {
|
||||
color: #c8c9db;
|
||||
}
|
||||
.rust .chapter li .active,
|
||||
.rust .chapter li a:hover {
|
||||
/* Animate color change */
|
||||
color: #e69f67;
|
||||
}
|
||||
.rust .chapter .spacer {
|
||||
background-color: #45373a;
|
||||
}
|
||||
.rust .menu-bar,
|
||||
.rust .menu-bar:visited,
|
||||
.rust .nav-chapters,
|
||||
.rust .nav-chapters:visited,
|
||||
.rust .mobile-nav-chapters,
|
||||
.rust .mobile-nav-chapters:visited {
|
||||
color: #737480;
|
||||
}
|
||||
.rust .menu-bar i:hover,
|
||||
.rust .nav-chapters:hover,
|
||||
.rust .mobile-nav-chapters i:hover {
|
||||
color: #262625;
|
||||
}
|
||||
.rust .mobile-nav-chapters i:hover {
|
||||
color: #c8c9db;
|
||||
}
|
||||
.rust .mobile-nav-chapters {
|
||||
background-color: #3b2e2a;
|
||||
}
|
||||
.rust .content a:link,
|
||||
.rust a:visited {
|
||||
color: #2b79a2;
|
||||
}
|
||||
.rust .theme-popup {
|
||||
color: #262625;
|
||||
background: #e1e1db;
|
||||
border: 1px solid #b38f6b;
|
||||
}
|
||||
.rust .theme-popup .theme:hover {
|
||||
background-color: #99908a;
|
||||
}
|
||||
.rust .theme-popup .default {
|
||||
color: #737480;
|
||||
}
|
||||
.rust blockquote {
|
||||
margin: 20px 0;
|
||||
padding: 0 20px;
|
||||
color: #262625;
|
||||
background-color: #c1c1bb;
|
||||
border-top: 0.1em solid #b8b8b1;
|
||||
border-bottom: 0.1em solid #b8b8b1;
|
||||
}
|
||||
.rust table td {
|
||||
border-color: #d7d7cf;
|
||||
}
|
||||
.rust table tbody tr:nth-child(2n) {
|
||||
background: #dbdbd4;
|
||||
}
|
||||
.rust table thead {
|
||||
background: #b3a497;
|
||||
}
|
||||
.rust table thead td {
|
||||
border: none;
|
||||
}
|
||||
.rust table thead tr {
|
||||
border: 1px #b3a497 solid;
|
||||
}
|
||||
.rust :not(pre) > .hljs {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 0.1em 0.3em;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.rust pre {
|
||||
position: relative;
|
||||
}
|
||||
.rust pre > .buttons {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
color: #c8c9db;
|
||||
cursor: pointer;
|
||||
}
|
||||
.rust pre > .buttons :hover {
|
||||
color: #e69f67;
|
||||
}
|
||||
.rust pre > .buttons i {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.rust pre > .result {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
@media print {
|
||||
#sidebar {
|
||||
display: none;
|
||||
}
|
||||
#page-wrapper {
|
||||
left: 0;
|
||||
overflow-y: initial;
|
||||
}
|
||||
#content {
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#menu-bar {
|
||||
display: none;
|
||||
}
|
||||
.page {
|
||||
overflow-y: initial;
|
||||
}
|
||||
.nav-chapters {
|
||||
display: none;
|
||||
}
|
||||
.mobile-nav-chapters {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
div.footnote-definition p {
|
||||
display: inline;
|
||||
}
|
||||
326
src/doc/reference/src/tokens.md
Normal file
326
src/doc/reference/src/tokens.md
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
# Tokens
|
||||
|
||||
Tokens are primitive productions in the grammar defined by regular
|
||||
(non-recursive) languages. "Simple" tokens are given in [string table
|
||||
production] form, and occur in the rest of the
|
||||
grammar as double-quoted strings. Other tokens have exact rules given.
|
||||
|
||||
[string table production]: string-table-productions.html
|
||||
|
||||
## Literals
|
||||
|
||||
A literal is an expression consisting of a single token, rather than a sequence
|
||||
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.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Characters and strings
|
||||
|
||||
| | Example | `#` sets | Characters | 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 | [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
|
||||
|
||||
| | Name |
|
||||
|---|------|
|
||||
| `\x7F` | 8-bit character code (exactly 2 digits) |
|
||||
| `\n` | Newline |
|
||||
| `\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 |
|
||||
|----------------------------------------|---------|----------------|----------|
|
||||
| Decimal integer | `98_222` | `N/A` | Integer suffixes |
|
||||
| Hex integer | `0xff` | `N/A` | Integer suffixes |
|
||||
| Octal integer | `0o77` | `N/A` | Integer suffixes |
|
||||
| Binary integer | `0b1111_0000` | `N/A` | Integer suffixes |
|
||||
| Floating-point | `123.0E+77` | `Optional` | Floating-point suffixes |
|
||||
|
||||
`*` All number literals allow `_` as a visual separator: `1_234.0E+18f64`
|
||||
|
||||
#### Suffixes
|
||||
|
||||
| Integer | Floating-point |
|
||||
|---------|----------------|
|
||||
| `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `isize`, `usize` | `f32`, `f64` |
|
||||
|
||||
### Character and string literals
|
||||
|
||||
#### Character literals
|
||||
|
||||
A _character literal_ is a single Unicode character enclosed within two
|
||||
`U+0027` (single-quote) characters, with the exception of `U+0027` itself,
|
||||
which must be _escaped_ by a preceding `U+005C` character (`\`).
|
||||
|
||||
#### String literals
|
||||
|
||||
A _string literal_ is a sequence of any Unicode characters enclosed within two
|
||||
`U+0022` (double-quote) characters, with the exception of `U+0022` itself,
|
||||
which must be _escaped_ by a preceding `U+005C` character (`\`).
|
||||
|
||||
Line-break characters are allowed in string literals. Normally they represent
|
||||
themselves (i.e. no translation), but as a special exception, when an unescaped
|
||||
`U+005C` character (`\`) occurs immediately before the newline (`U+000A`), the
|
||||
`U+005C` character, the newline, and all whitespace at the beginning of the
|
||||
next line are ignored. Thus `a` and `b` are equal:
|
||||
|
||||
```rust
|
||||
let a = "foobar";
|
||||
let b = "foo\
|
||||
bar";
|
||||
|
||||
assert_eq!(a,b);
|
||||
```
|
||||
|
||||
#### Character escapes
|
||||
|
||||
Some additional _escapes_ are available in either character or non-raw string
|
||||
literals. An escape starts with a `U+005C` (`\`) and continues with one of the
|
||||
following forms:
|
||||
|
||||
* An _8-bit code point escape_ starts with `U+0078` (`x`) and is
|
||||
followed by exactly two _hex digits_. It denotes the Unicode code point
|
||||
equal to the provided hex value.
|
||||
* A _24-bit code point escape_ starts with `U+0075` (`u`) and is followed
|
||||
by up to six _hex digits_ surrounded by braces `U+007B` (`{`) and `U+007D`
|
||||
(`}`). It denotes the Unicode code point equal to the provided hex value.
|
||||
* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072`
|
||||
(`r`), or `U+0074` (`t`), denoting the Unicode values `U+000A` (LF),
|
||||
`U+000D` (CR) or `U+0009` (HT) respectively.
|
||||
* The _null escape_ is the character `U+0030` (`0`) and denotes the Unicode
|
||||
value `U+0000` (NUL).
|
||||
* The _backslash escape_ is the character `U+005C` (`\`) which must be
|
||||
escaped in order to denote *itself*.
|
||||
|
||||
#### Raw string literals
|
||||
|
||||
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_ 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
|
||||
many `U+0023` (`#`) characters as were used to start the raw string literal) or
|
||||
`U+005C` (`\`) do not have any special meaning.
|
||||
|
||||
Examples for string literals:
|
||||
|
||||
```
|
||||
"foo"; r"foo"; // foo
|
||||
"\"foo\""; r#""foo""#; // "foo"
|
||||
|
||||
"foo #\"# bar";
|
||||
r##"foo #"# bar"##; // foo #"# bar
|
||||
|
||||
"\x52"; "R"; r"R"; // R
|
||||
"\\x52"; r"\x52"; // \x52
|
||||
```
|
||||
|
||||
### Byte and byte string literals
|
||||
|
||||
#### Byte literals
|
||||
|
||||
A _byte literal_ is a single ASCII character (in the `U+0000` to `U+007F`
|
||||
range) or a single _escape_ preceded by the characters `U+0062` (`b`) and
|
||||
`U+0027` (single-quote), and followed by the character `U+0027`. If the character
|
||||
`U+0027` is present within the literal, it must be _escaped_ by a preceding
|
||||
`U+005C` (`\`) character. It is equivalent to a `u8` unsigned 8-bit integer
|
||||
_number literal_.
|
||||
|
||||
#### Byte string literals
|
||||
|
||||
A non-raw _byte string literal_ is a sequence of ASCII characters and _escapes_,
|
||||
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 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
|
||||
literals. An escape starts with a `U+005C` (`\`) and continues with one of the
|
||||
following forms:
|
||||
|
||||
* A _byte escape_ escape starts with `U+0078` (`x`) and is
|
||||
followed by exactly two _hex digits_. It denotes the byte
|
||||
equal to the provided hex value.
|
||||
* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072`
|
||||
(`r`), or `U+0074` (`t`), denoting the bytes values `0x0A` (ASCII LF),
|
||||
`0x0D` (ASCII CR) or `0x09` (ASCII HT) respectively.
|
||||
* The _null escape_ is the character `U+0030` (`0`) and denotes the byte
|
||||
value `0x00` (ASCII NUL).
|
||||
* The _backslash escape_ is the character `U+005C` (`\`) which must be
|
||||
escaped in order to denote its ASCII encoding `0x5C`.
|
||||
|
||||
#### Raw byte string literals
|
||||
|
||||
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_ 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
|
||||
many `U+0023` (`#`) characters as were used to start the raw string literal) or
|
||||
`U+005C` (`\`) do not have any special meaning.
|
||||
|
||||
Examples for byte string literals:
|
||||
|
||||
```
|
||||
b"foo"; br"foo"; // foo
|
||||
b"\"foo\""; br#""foo""#; // "foo"
|
||||
|
||||
b"foo #\"# bar";
|
||||
br##"foo #"# bar"##; // foo #"# bar
|
||||
|
||||
b"\x52"; b"R"; br"R"; // R
|
||||
b"\\x52"; br"\x52"; // \x52
|
||||
```
|
||||
|
||||
### Number literals
|
||||
|
||||
A _number literal_ is either an _integer literal_ or a _floating-point
|
||||
literal_. The grammar for recognizing the two kinds of literals is mixed.
|
||||
|
||||
#### Integer literals
|
||||
|
||||
An _integer literal_ has one of four forms:
|
||||
|
||||
* A _decimal literal_ starts with a *decimal digit* and continues with any
|
||||
mixture of *decimal digits* and _underscores_.
|
||||
* A _hex literal_ starts with the character sequence `U+0030` `U+0078`
|
||||
(`0x`) and continues as any mixture of hex digits and underscores.
|
||||
* An _octal literal_ starts with the character sequence `U+0030` `U+006F`
|
||||
(`0o`) and continues as any mixture of octal digits and underscores.
|
||||
* A _binary literal_ starts with the character sequence `U+0030` `U+0062`
|
||||
(`0b`) and continues as any mixture of binary digits and underscores.
|
||||
|
||||
Like any literal, an integer literal may be followed (immediately,
|
||||
without any spaces) by an _integer suffix_, which forcibly sets the
|
||||
type of the literal. The integer suffix must be the name of one of the
|
||||
integral types: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`,
|
||||
`isize`, or `usize`.
|
||||
|
||||
The type of an _unsuffixed_ integer literal is determined by type inference:
|
||||
|
||||
* If an integer type can be _uniquely_ determined from the surrounding
|
||||
program context, the unsuffixed integer literal has that type.
|
||||
|
||||
* If the program context under-constrains the type, it defaults to the
|
||||
signed 32-bit integer `i32`.
|
||||
|
||||
* If the program context over-constrains the type, it is considered a
|
||||
static type error.
|
||||
|
||||
Examples of integer literals of various forms:
|
||||
|
||||
```
|
||||
123i32; // type i32
|
||||
123u32; // type u32
|
||||
123_u32; // type u32
|
||||
0xff_u8; // type u8
|
||||
0o70_i16; // type i16
|
||||
0b1111_1111_1001_0000_i32; // type i32
|
||||
0usize; // type usize
|
||||
```
|
||||
|
||||
Note that the Rust syntax considers `-1i8` as an application of the [unary minus
|
||||
operator] to an integer literal `1i8`, rather than
|
||||
a single integer literal.
|
||||
|
||||
[unary minus operator]: expressions.html#unary-operator-expressions
|
||||
|
||||
#### Floating-point literals
|
||||
|
||||
A _floating-point literal_ has one of two forms:
|
||||
|
||||
* A _decimal literal_ followed by a period character `U+002E` (`.`). This is
|
||||
optionally followed by another decimal literal, with an optional _exponent_.
|
||||
* A single _decimal literal_ followed by an _exponent_.
|
||||
|
||||
Like integer literals, a floating-point literal may be followed by a
|
||||
suffix, so long as the pre-suffix part does not end with `U+002E` (`.`).
|
||||
The suffix forcibly sets the type of the literal. There are two valid
|
||||
_floating-point suffixes_, `f32` and `f64` (the 32-bit and 64-bit floating point
|
||||
types), which explicitly determine the type of the literal.
|
||||
|
||||
The type of an _unsuffixed_ floating-point literal is determined by
|
||||
type inference:
|
||||
|
||||
* If a floating-point type can be _uniquely_ determined from the
|
||||
surrounding program context, the unsuffixed floating-point literal
|
||||
has that type.
|
||||
|
||||
* If the program context under-constrains the type, it defaults to `f64`.
|
||||
|
||||
* If the program context over-constrains the type, it is considered a
|
||||
static type error.
|
||||
|
||||
Examples of floating-point literals of various forms:
|
||||
|
||||
```
|
||||
123.0f64; // type f64
|
||||
0.1f64; // type f64
|
||||
0.1f32; // type f32
|
||||
12E+99_f64; // type f64
|
||||
let x: f64 = 2.; // type f64
|
||||
```
|
||||
|
||||
This last example is different because it is not possible to use the suffix
|
||||
syntax with a floating point literal ending in a period. `2.f64` would attempt
|
||||
to call a method named `f64` on `2`.
|
||||
|
||||
The representation semantics of floating-point numbers are described in
|
||||
["Machine Types"].
|
||||
|
||||
["Machine Types"]: types.html#machine-types
|
||||
|
||||
### Boolean literals
|
||||
|
||||
The two values of the boolean type are written `true` and `false`.
|
||||
|
||||
## Symbols
|
||||
|
||||
Symbols are a general class of printable [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], [binary
|
||||
operators], or [keywords].
|
||||
They are catalogued in [the Symbols section][symbols] of the Grammar document.
|
||||
|
||||
[unary operators]: expressions.html#unary-operator-expressions
|
||||
[binary operators]: expressions.html#binary-operator-expressions
|
||||
[tokens]: #tokens
|
||||
[symbols]: ../grammar.html#symbols
|
||||
[keywords]: ../grammar.html#keywords
|
||||
145
src/doc/reference/src/type-coercions.md
Normal file
145
src/doc/reference/src/type-coercions.md
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
# Type coercions
|
||||
|
||||
Coercions are defined in [RFC 401]. A coercion is implicit and has no syntax.
|
||||
|
||||
[RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
||||
|
||||
## Coercion sites
|
||||
|
||||
A coercion can only occur at certain coercion sites in a program; these are
|
||||
typically places where the desired type is explicit or can be derived by
|
||||
propagation from explicit types (without type inference). Possible coercion
|
||||
sites are:
|
||||
|
||||
* `let` statements where an explicit type is given.
|
||||
|
||||
For example, `42` is coerced to have type `i8` in the following:
|
||||
|
||||
```rust
|
||||
let _: i8 = 42;
|
||||
```
|
||||
|
||||
* `static` and `const` statements (similar to `let` statements).
|
||||
|
||||
* Arguments for function calls
|
||||
|
||||
The value being coerced is the actual parameter, and it is coerced to
|
||||
the type of the formal parameter.
|
||||
|
||||
For example, `42` is coerced to have type `i8` in the following:
|
||||
|
||||
```rust
|
||||
fn bar(_: i8) { }
|
||||
|
||||
fn main() {
|
||||
bar(42);
|
||||
}
|
||||
```
|
||||
|
||||
* Instantiations of struct or variant fields
|
||||
|
||||
For example, `42` is coerced to have type `i8` in the following:
|
||||
|
||||
```rust
|
||||
struct Foo { x: i8 }
|
||||
|
||||
fn main() {
|
||||
Foo { x: 42 };
|
||||
}
|
||||
```
|
||||
|
||||
* Function results, either the final line of a block if it is not
|
||||
semicolon-terminated or any expression in a `return` statement
|
||||
|
||||
For example, `42` is coerced to have type `i8` in the following:
|
||||
|
||||
```rust
|
||||
fn foo() -> i8 {
|
||||
42
|
||||
}
|
||||
```
|
||||
|
||||
If the expression in one of these coercion sites is a coercion-propagating
|
||||
expression, then the relevant sub-expressions in that expression are also
|
||||
coercion sites. Propagation recurses from these new coercion sites.
|
||||
Propagating expressions and their relevant sub-expressions are:
|
||||
|
||||
* Array literals, where the array has type `[U; n]`. Each sub-expression in
|
||||
the array literal is a coercion site for coercion to type `U`.
|
||||
|
||||
* Array literals with repeating syntax, where the array has type `[U; n]`. The
|
||||
repeated sub-expression is a coercion site for coercion to type `U`.
|
||||
|
||||
* Tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`.
|
||||
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`.
|
||||
|
||||
* 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
|
||||
it is not semicolon-terminated) is a coercion site to `U`. This includes
|
||||
blocks which are part of control flow statements, such as `if`/`else`, if
|
||||
the block has a known type.
|
||||
|
||||
## Coercion types
|
||||
|
||||
Coercion is allowed between the following types:
|
||||
|
||||
* `T` to `U` if `T` is a subtype of `U` (*reflexive case*)
|
||||
|
||||
* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3`
|
||||
(*transitive case*)
|
||||
|
||||
Note that this is not fully supported yet
|
||||
|
||||
* `&mut T` to `&T`
|
||||
|
||||
* `*mut T` to `*const T`
|
||||
|
||||
* `&T` to `*const T`
|
||||
|
||||
* `&mut T` to `*mut T`
|
||||
|
||||
* `&T` to `&U` if `T` implements `Deref<Target = U>`. For example:
|
||||
|
||||
```rust
|
||||
use std::ops::Deref;
|
||||
|
||||
struct CharContainer {
|
||||
value: char,
|
||||
}
|
||||
|
||||
impl Deref for CharContainer {
|
||||
type Target = char;
|
||||
|
||||
fn deref<'a>(&'a self) -> &'a char {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
fn foo(arg: &char) {}
|
||||
|
||||
fn main() {
|
||||
let x = &mut CharContainer { value: 'y' };
|
||||
foo(x); //&mut CharContainer is coerced to &char.
|
||||
}
|
||||
```
|
||||
|
||||
* `&mut T` to `&mut U` if `T` implements `DerefMut<Target = U>`.
|
||||
|
||||
* TyCtor(`T`) to TyCtor(coerce_inner(`T`)), where TyCtor(`T`) is one of
|
||||
- `&T`
|
||||
- `&mut T`
|
||||
- `*const T`
|
||||
- `*mut T`
|
||||
- `Box<T>`
|
||||
|
||||
and where
|
||||
- coerce_inner(`[T, ..n]`) = `[T]`
|
||||
- coerce_inner(`T`) = `U` where `T` is a concrete type which implements the
|
||||
trait `U`.
|
||||
|
||||
In the future, coerce_inner will be recursively extended to tuples and
|
||||
structs. In addition, coercions from sub-traits to super-traits will be
|
||||
added. See [RFC 401] for more details.
|
||||
1
src/doc/reference/src/type-system.md
Normal file
1
src/doc/reference/src/type-system.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Type system
|
||||
398
src/doc/reference/src/types.md
Normal file
398
src/doc/reference/src/types.md
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
# Types
|
||||
|
||||
Every variable, item and value in a Rust program has a type. The _type_ of a
|
||||
*value* defines the interpretation of the memory holding it.
|
||||
|
||||
Built-in types and type-constructors are tightly integrated into the language,
|
||||
in nontrivial ways that are not possible to emulate in user-defined types.
|
||||
User-defined types have limited capabilities.
|
||||
|
||||
## Primitive types
|
||||
|
||||
The primitive types are the following:
|
||||
|
||||
* The boolean type `bool` with values `true` and `false`.
|
||||
* The machine types (integer and floating-point).
|
||||
* The machine-dependent integer types.
|
||||
* Arrays
|
||||
* Tuples
|
||||
* Slices
|
||||
* Function pointers
|
||||
|
||||
### Machine types
|
||||
|
||||
The machine types are the following:
|
||||
|
||||
* The unsigned word types `u8`, `u16`, `u32` and `u64`, with values drawn from
|
||||
the integer intervals [0, 2^8 - 1], [0, 2^16 - 1], [0, 2^32 - 1] and
|
||||
[0, 2^64 - 1] respectively.
|
||||
|
||||
* The signed two's complement word types `i8`, `i16`, `i32` and `i64`, with
|
||||
values drawn from the integer intervals [-(2^(7)), 2^7 - 1],
|
||||
[-(2^(15)), 2^15 - 1], [-(2^(31)), 2^31 - 1], [-(2^(63)), 2^63 - 1]
|
||||
respectively.
|
||||
|
||||
* The IEEE 754-2008 `binary32` and `binary64` floating-point types: `f32` and
|
||||
`f64`, respectively.
|
||||
|
||||
### Machine-dependent integer types
|
||||
|
||||
The `usize` type is an unsigned integer type with the same number of bits as the
|
||||
platform's pointer type. It can represent every memory address in the process.
|
||||
|
||||
The `isize` type is a signed integer type with the same number of bits as the
|
||||
platform's pointer type. The theoretical upper bound on object and array size
|
||||
is the maximum `isize` value. This ensures that `isize` can be used to calculate
|
||||
differences between pointers into an object or array and can address every byte
|
||||
within an object along with one byte past the end.
|
||||
|
||||
## Textual types
|
||||
|
||||
The types `char` and `str` hold textual data.
|
||||
|
||||
A value of type `char` is a [Unicode scalar value](
|
||||
http://www.unicode.org/glossary/#unicode_scalar_value) (i.e. a code point that
|
||||
is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to
|
||||
0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` array is effectively an UCS-4 /
|
||||
UTF-32 string.
|
||||
|
||||
A value of type `str` is a Unicode string, represented as an array of 8-bit
|
||||
unsigned bytes holding a sequence of UTF-8 code points. Since `str` is of
|
||||
unknown size, it is not a _first-class_ type, but can only be instantiated
|
||||
through a pointer type, such as `&str`.
|
||||
|
||||
## Tuple types
|
||||
|
||||
A tuple *type* is a heterogeneous product of other types, called the *elements*
|
||||
of the tuple. It has no nominal name and is instead structurally typed.
|
||||
|
||||
Tuple types and values are denoted by listing the types or values of their
|
||||
elements, respectively, in a parenthesized, comma-separated list.
|
||||
|
||||
Because tuple elements don't have a name, they can only be accessed by
|
||||
pattern-matching or by using `N` directly as a field to access the
|
||||
`N`th element.
|
||||
|
||||
An example of a tuple type and its use:
|
||||
|
||||
```
|
||||
type Pair<'a> = (i32, &'a str);
|
||||
let p: Pair<'static> = (10, "ten");
|
||||
let (a, b) = p;
|
||||
|
||||
assert_eq!(a, 10);
|
||||
assert_eq!(b, "ten");
|
||||
assert_eq!(p.0, 10);
|
||||
assert_eq!(p.1, "ten");
|
||||
```
|
||||
|
||||
For historical reasons and convenience, the tuple type with no elements (`()`)
|
||||
is often called ‘unit’ or ‘the unit type’.
|
||||
|
||||
## Array, and Slice types
|
||||
|
||||
Rust has two different types for a list of items:
|
||||
|
||||
* `[T; N]`, an 'array'
|
||||
* `&[T]`, a 'slice'
|
||||
|
||||
An array has a fixed size, and can be allocated on either the stack or the
|
||||
heap.
|
||||
|
||||
A slice is a 'view' into an array. It doesn't own the data it points
|
||||
to, it borrows it.
|
||||
|
||||
Examples:
|
||||
|
||||
```{rust}
|
||||
// A stack-allocated array
|
||||
let array: [i32; 3] = [1, 2, 3];
|
||||
|
||||
// A heap-allocated array
|
||||
let vector: Vec<i32> = vec![1, 2, 3];
|
||||
|
||||
// A slice into an array
|
||||
let slice: &[i32] = &vector[..];
|
||||
```
|
||||
|
||||
As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
|
||||
`vec!` macro is also part of the standard library, rather than the language.
|
||||
|
||||
All in-bounds elements of arrays and slices are always initialized, and access
|
||||
to an array or slice is always bounds-checked.
|
||||
|
||||
## 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 *struct* types of the Lisp family.
|
||||
|
||||
New instances of a `struct` can be constructed with a [struct
|
||||
expression](expressions.html#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
|
||||
`#[repr(...)]` attribute. In either case, fields may be given in any order in
|
||||
a corresponding struct *expression*; the resulting `struct` value will always
|
||||
have the same memory layout.
|
||||
|
||||
The fields of a `struct` may be qualified by [visibility
|
||||
modifiers](visibility-and-privacy.html), to allow access to data in a
|
||||
struct outside a module.
|
||||
|
||||
A _tuple struct_ type is just like a struct type, except that the fields are
|
||||
anonymous.
|
||||
|
||||
A _unit-like struct_ type is like a struct type, except that it has no
|
||||
fields. The one value constructed by the associated [struct
|
||||
expression](expressions.html#struct-expressions) is the only value that inhabits such a
|
||||
type.
|
||||
|
||||
## Enumerated types
|
||||
|
||||
An *enumerated type* is a nominal, heterogeneous disjoint union type, denoted
|
||||
by the name of an [`enum` item](items.html#enumerations). [^enumtype]
|
||||
|
||||
[^enumtype]: The `enum` type is analogous to a `data` constructor declaration in
|
||||
ML, or a *pick ADT* in Limbo.
|
||||
|
||||
An [`enum` item](items.html#enumerations) declares both the type and a number of *variant
|
||||
constructors*, each of which is independently named and takes an optional tuple
|
||||
of arguments.
|
||||
|
||||
New instances of an `enum` can be constructed by calling one of the variant
|
||||
constructors, in a [call expression](expressions.html#call-expressions).
|
||||
|
||||
Any `enum` value consumes as much memory as the largest variant constructor for
|
||||
its corresponding `enum` type.
|
||||
|
||||
Enum types cannot be denoted *structurally* as types, but must be denoted by
|
||||
named reference to an [`enum` item](items.html#enumerations).
|
||||
|
||||
## Recursive types
|
||||
|
||||
Nominal types — [enumerations](#enumerated-types) and
|
||||
[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)).
|
||||
* 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;
|
||||
in other words the recursive fields of the type must be [pointer types](#pointer-types).
|
||||
* Recursive type definitions can cross module boundaries, but not module *visibility* boundaries,
|
||||
or crate boundaries (in order to simplify the module system and type checker).
|
||||
|
||||
An example of a *recursive* type and its use:
|
||||
|
||||
```
|
||||
enum List<T> {
|
||||
Nil,
|
||||
Cons(T, Box<List<T>>)
|
||||
}
|
||||
|
||||
let a: List<i32> = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil))));
|
||||
```
|
||||
|
||||
## Pointer types
|
||||
|
||||
All pointers in Rust are explicit first-class values. They can be copied,
|
||||
stored into data structs, and returned from functions. There are two
|
||||
varieties of pointer in Rust:
|
||||
|
||||
* References (`&`)
|
||||
: These point to memory _owned by some other value_.
|
||||
A reference type is written `&type`,
|
||||
or `&'a type` when you need to specify an explicit lifetime.
|
||||
Copying a reference is a "shallow" operation:
|
||||
it involves only copying the pointer itself.
|
||||
Releasing a reference has no effect on the value it points to,
|
||||
but a reference of a temporary value will keep it alive during the scope
|
||||
of the reference itself.
|
||||
|
||||
* Raw pointers (`*`)
|
||||
: Raw pointers are pointers without safety or liveness guarantees.
|
||||
Raw pointers are written as `*const T` or `*mut T`,
|
||||
for example `*const i32` means a raw pointer to a 32-bit integer.
|
||||
Copying or dropping a raw pointer has no effect on the lifecycle of any
|
||||
other value. Dereferencing a raw pointer or converting it to any other
|
||||
pointer type is an [`unsafe` operation](unsafe-functions.html).
|
||||
Raw pointers are generally discouraged in Rust code;
|
||||
they exist to support interoperability with foreign code,
|
||||
and writing performance-critical or low-level functions.
|
||||
|
||||
The standard library contains additional 'smart pointer' types beyond references
|
||||
and raw pointers.
|
||||
|
||||
## Function types
|
||||
|
||||
The function type constructor `fn` forms new function types. A function type
|
||||
consists of a possibly-empty set of function-type modifiers (such as `unsafe`
|
||||
or `extern`), a sequence of input types and an output type.
|
||||
|
||||
An example of a `fn` type:
|
||||
|
||||
```
|
||||
fn add(x: i32, y: i32) -> i32 {
|
||||
x + y
|
||||
}
|
||||
|
||||
let mut x = add(5,7);
|
||||
|
||||
type Binop = fn(i32, i32) -> i32;
|
||||
let bo: Binop = add;
|
||||
x = bo(5,7);
|
||||
```
|
||||
|
||||
### Function types for specific items
|
||||
|
||||
Internal to the compiler, there are also function types that are specific to a particular
|
||||
function item. In the following snippet, for example, the internal types of the functions
|
||||
`foo` and `bar` are different, despite the fact that they have the same signature:
|
||||
|
||||
```
|
||||
fn foo() { }
|
||||
fn bar() { }
|
||||
```
|
||||
|
||||
The types of `foo` and `bar` can both be implicitly coerced to the fn
|
||||
pointer type `fn()`. There is currently no syntax for unique fn types,
|
||||
though the compiler will emit a type like `fn() {foo}` in error
|
||||
messages to indicate "the unique fn type for the function `foo`".
|
||||
|
||||
## Closure types
|
||||
|
||||
A [lambda expression](expressions.html#lambda-expressions) produces a closure
|
||||
value with a unique, anonymous type that cannot be written out.
|
||||
|
||||
Depending on the requirements of the closure, its type implements one or
|
||||
more of the closure traits:
|
||||
|
||||
* `FnOnce`
|
||||
: The closure can be called once. A closure called as `FnOnce`
|
||||
can move out values from its environment.
|
||||
|
||||
* `FnMut`
|
||||
: The closure can be called multiple times as mutable. A closure called as
|
||||
`FnMut` can mutate values from its environment. `FnMut` inherits from
|
||||
`FnOnce` (i.e. anything implementing `FnMut` also implements `FnOnce`).
|
||||
|
||||
* `Fn`
|
||||
: The closure can be called multiple times through a shared reference.
|
||||
A closure called as `Fn` can neither move out from nor mutate values
|
||||
from its environment. `Fn` inherits from `FnMut`, which itself
|
||||
inherits from `FnOnce`.
|
||||
|
||||
|
||||
## Trait objects
|
||||
|
||||
In Rust, a type like `&SomeTrait` or `Box<SomeTrait>` is called a _trait object_.
|
||||
Each instance of a trait object includes:
|
||||
|
||||
- a pointer to an instance of a type `T` that implements `SomeTrait`
|
||||
- a _virtual method table_, often just called a _vtable_, which contains, for
|
||||
each method of `SomeTrait` that `T` implements, a pointer to `T`'s
|
||||
implementation (i.e. a function pointer).
|
||||
|
||||
The purpose of trait objects is to permit "late binding" of methods. Calling a
|
||||
method on a trait object results in virtual dispatch at runtime: that is, a
|
||||
function pointer is loaded from the trait object vtable and invoked indirectly.
|
||||
The actual implementation for each vtable entry can vary on an object-by-object
|
||||
basis.
|
||||
|
||||
Note that for a trait object to be instantiated, the trait must be
|
||||
_object-safe_. Object safety rules are defined in [RFC 255].
|
||||
|
||||
[RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
|
||||
|
||||
Given a pointer-typed expression `E` of type `&T` or `Box<T>`, where `T`
|
||||
implements trait `R`, casting `E` to the corresponding pointer type `&R` or
|
||||
`Box<R>` results in a value of the _trait object_ `R`. This result is
|
||||
represented as a pair of pointers: the vtable pointer for the `T`
|
||||
implementation of `R`, and the pointer value of `E`.
|
||||
|
||||
An example of a trait object:
|
||||
|
||||
```
|
||||
trait Printable {
|
||||
fn stringify(&self) -> String;
|
||||
}
|
||||
|
||||
impl Printable for i32 {
|
||||
fn stringify(&self) -> String { self.to_string() }
|
||||
}
|
||||
|
||||
fn print(a: Box<Printable>) {
|
||||
println!("{}", a.stringify());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
print(Box::new(10) as Box<Printable>);
|
||||
}
|
||||
```
|
||||
|
||||
In this example, the trait `Printable` occurs as a trait object in both the
|
||||
type signature of `print`, and the cast expression in `main`.
|
||||
|
||||
### Type parameters
|
||||
|
||||
Within the body of an item that has type parameter declarations, the names of
|
||||
its type parameters are types:
|
||||
|
||||
```ignore
|
||||
fn to_vec<A: Clone>(xs: &[A]) -> Vec<A> {
|
||||
if xs.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
let first: A = xs[0].clone();
|
||||
let mut rest: Vec<A> = to_vec(&xs[1..]);
|
||||
rest.insert(0, first);
|
||||
rest
|
||||
}
|
||||
```
|
||||
|
||||
Here, `first` has type `A`, referring to `to_vec`'s `A` type parameter; and `rest`
|
||||
has type `Vec<A>`, a vector with element type `A`.
|
||||
|
||||
## Self types
|
||||
|
||||
The special type `Self` has a meaning within traits and impls. In a trait definition, it refers
|
||||
to an implicit type parameter representing the "implementing" type. In an impl,
|
||||
it is an alias for the implementing type. For example, in:
|
||||
|
||||
```
|
||||
pub trait From<T> {
|
||||
fn from(T) -> Self;
|
||||
}
|
||||
|
||||
impl From<i32> for String {
|
||||
fn from(x: i32) -> Self {
|
||||
x.to_string()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The notation `Self` in the impl refers to the implementing type: `String`. In another
|
||||
example:
|
||||
|
||||
```
|
||||
trait Printable {
|
||||
fn make_string(&self) -> String;
|
||||
}
|
||||
|
||||
impl Printable for String {
|
||||
fn make_string(&self) -> String {
|
||||
(*self).clone()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The notation `&self` is a shorthand for `self: &Self`. In this case,
|
||||
in the impl, `Self` refers to the value of type `String` that is the
|
||||
receiver for a call to the method `make_string`.
|
||||
9
src/doc/reference/src/unicode-productions.md
Normal file
9
src/doc/reference/src/unicode-productions.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Unicode productions
|
||||
|
||||
A few productions in Rust's grammar permit Unicode code points outside the
|
||||
ASCII range. We define these productions in terms of character properties
|
||||
specified in the Unicode standard, rather than in terms of ASCII-range code
|
||||
points. The grammar has a [Special Unicode Productions][unicodeproductions]
|
||||
section that lists these productions.
|
||||
|
||||
[unicodeproductions]: ../grammar.html#special-unicode-productions
|
||||
22
src/doc/reference/src/unsafe-blocks.md
Normal file
22
src/doc/reference/src/unsafe-blocks.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# 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.
|
||||
5
src/doc/reference/src/unsafe-functions.md
Normal file
5
src/doc/reference/src/unsafe-functions.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# 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.
|
||||
11
src/doc/reference/src/unsafety.md
Normal file
11
src/doc/reference/src/unsafety.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# 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](types.html#pointer-types).
|
||||
- Reading or writing a [mutable static variable](items.html#mutable-statics).
|
||||
- Calling an unsafe function (including an intrinsic or foreign function).
|
||||
31
src/doc/reference/src/variables.md
Normal file
31
src/doc/reference/src/variables.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Variables
|
||||
|
||||
A _variable_ is a component of a stack frame, either a named function parameter,
|
||||
an anonymous [temporary](expressions.html#lvalues-rvalues-and-temporaries), or a named local
|
||||
variable.
|
||||
|
||||
A _local variable_ (or *stack-local* allocation) holds a value directly,
|
||||
allocated within the stack's memory. The value is a part of the stack frame.
|
||||
|
||||
Local variables are immutable unless declared otherwise like: `let mut x = ...`.
|
||||
|
||||
Function parameters are immutable unless declared with `mut`. The `mut` keyword
|
||||
applies only to the following parameter (so `|mut x, y|` and `fn f(mut x:
|
||||
Box<i32>, y: Box<i32>)` declare one mutable variable `x` and one immutable
|
||||
variable `y`).
|
||||
|
||||
Methods that take either `self` or `Box<Self>` can optionally place them in a
|
||||
mutable variable by prefixing them with `mut` (similar to regular arguments):
|
||||
|
||||
```
|
||||
trait Changer: Sized {
|
||||
fn change(mut self) {}
|
||||
fn modify(mut self: Box<Self>) {}
|
||||
}
|
||||
```
|
||||
|
||||
Local variables are not initialized when allocated; the entire frame worth of
|
||||
local variables are allocated at once, on frame-entry, in an uninitialized
|
||||
state. Subsequent statements within a function may or may not initialize the
|
||||
local variables. Local variables can be used only after they have been
|
||||
initialized; this is enforced by the compiler.
|
||||
160
src/doc/reference/src/visibility-and-privacy.md
Normal file
160
src/doc/reference/src/visibility-and-privacy.md
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
# Visibility and Privacy
|
||||
|
||||
These two terms are often used interchangeably, and what they are attempting to
|
||||
convey is the answer to the question "Can this item be used at this location?"
|
||||
|
||||
Rust's name resolution operates on a global hierarchy of namespaces. Each level
|
||||
in the hierarchy can be thought of as some item. The items are one of those
|
||||
mentioned above, but also include external crates. Declaring or defining a new
|
||||
module can be thought of as inserting a new tree into the hierarchy at the
|
||||
location of the definition.
|
||||
|
||||
To control whether interfaces can be used across modules, Rust checks each use
|
||||
of an item to see whether it should be allowed or not. This is where privacy
|
||||
warnings are generated, or otherwise "you used a private item of another module
|
||||
and weren't allowed to."
|
||||
|
||||
By default, everything in Rust is *private*, with two exceptions: Associated
|
||||
items in a `pub` Trait are public by default; Enum variants
|
||||
in a `pub` enum are also public by default. When an item is declared as `pub`,
|
||||
it can be thought of as being accessible to the outside world. For example:
|
||||
|
||||
```
|
||||
# fn main() {}
|
||||
// Declare a private struct
|
||||
struct Foo;
|
||||
|
||||
// Declare a public struct with a private field
|
||||
pub struct Bar {
|
||||
field: i32,
|
||||
}
|
||||
|
||||
// Declare a public enum with two public variants
|
||||
pub enum State {
|
||||
PubliclyAccessibleState,
|
||||
PubliclyAccessibleState2,
|
||||
}
|
||||
```
|
||||
|
||||
With the notion of an item being either public or private, Rust allows item
|
||||
accesses in two cases:
|
||||
|
||||
1. If an item is public, then it can be used externally through any of its
|
||||
public ancestors.
|
||||
2. If an item is private, it may be accessed by the current module and its
|
||||
descendants.
|
||||
|
||||
These two cases are surprisingly powerful for creating module hierarchies
|
||||
exposing public APIs while hiding internal implementation details. To help
|
||||
explain, here's a few use cases and what they would entail:
|
||||
|
||||
* A library developer needs to expose functionality to crates which link
|
||||
against their library. As a consequence of the first case, this means that
|
||||
anything which is usable externally must be `pub` from the root down to the
|
||||
destination item. Any private item in the chain will disallow external
|
||||
accesses.
|
||||
|
||||
* A crate needs a global available "helper module" to itself, but it doesn't
|
||||
want to expose the helper module as a public API. To accomplish this, the
|
||||
root of the crate's hierarchy would have a private module which then
|
||||
internally has a "public API". Because the entire crate is a descendant of
|
||||
the root, then the entire local crate can access this private module through
|
||||
the second case.
|
||||
|
||||
* When writing unit tests for a module, it's often a common idiom to have an
|
||||
immediate child of the module to-be-tested named `mod test`. This module
|
||||
could access any items of the parent module through the second case, meaning
|
||||
that internal implementation details could also be seamlessly tested from the
|
||||
child module.
|
||||
|
||||
In the second case, it mentions that a private item "can be accessed" by the
|
||||
current module and its descendants, but the exact meaning of accessing an item
|
||||
depends on what the item is. Accessing a module, for example, would mean
|
||||
looking inside of it (to import more items). On the other hand, accessing a
|
||||
function would mean that it is invoked. Additionally, path expressions and
|
||||
import statements are considered to access an item in the sense that the
|
||||
import/expression is only valid if the destination is in the current visibility
|
||||
scope.
|
||||
|
||||
Here's an example of a program which exemplifies the three cases outlined
|
||||
above:
|
||||
|
||||
```
|
||||
// This module is private, meaning that no external crate can access this
|
||||
// module. Because it is private at the root of this current crate, however, any
|
||||
// module in the crate may access any publicly visible item in this module.
|
||||
mod crate_helper_module {
|
||||
|
||||
// This function can be used by anything in the current crate
|
||||
pub fn crate_helper() {}
|
||||
|
||||
// This function *cannot* be used by anything else in the crate. It is not
|
||||
// publicly visible outside of the `crate_helper_module`, so only this
|
||||
// current module and its descendants may access it.
|
||||
fn implementation_detail() {}
|
||||
}
|
||||
|
||||
// This function is "public to the root" meaning that it's available to external
|
||||
// crates linking against this one.
|
||||
pub fn public_api() {}
|
||||
|
||||
// Similarly to 'public_api', this module is public so external crates may look
|
||||
// inside of it.
|
||||
pub mod submodule {
|
||||
use crate_helper_module;
|
||||
|
||||
pub fn my_method() {
|
||||
// Any item in the local crate may invoke the helper module's public
|
||||
// interface through a combination of the two rules above.
|
||||
crate_helper_module::crate_helper();
|
||||
}
|
||||
|
||||
// This function is hidden to any module which is not a descendant of
|
||||
// `submodule`
|
||||
fn my_implementation() {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
#[test]
|
||||
fn test_my_implementation() {
|
||||
// Because this module is a descendant of `submodule`, it's allowed
|
||||
// to access private items inside of `submodule` without a privacy
|
||||
// violation.
|
||||
super::my_implementation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
For a Rust program to pass the privacy checking pass, all paths must be valid
|
||||
accesses given the two rules above. This includes all use statements,
|
||||
expressions, types, etc.
|
||||
|
||||
## Re-exporting and Visibility
|
||||
|
||||
Rust allows publicly re-exporting items through a `pub use` directive. Because
|
||||
this is a public directive, this allows the item to be used in the current
|
||||
module through the rules above. It essentially allows public access into the
|
||||
re-exported item. For example, this program is valid:
|
||||
|
||||
```
|
||||
pub use self::implementation::api;
|
||||
|
||||
mod implementation {
|
||||
pub mod api {
|
||||
pub fn f() {}
|
||||
}
|
||||
}
|
||||
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
This means that any external crate referencing `implementation::api::f` would
|
||||
receive a privacy violation, while the path `api::f` would be allowed.
|
||||
|
||||
When re-exporting a private item, it can be thought of as allowing the "privacy
|
||||
chain" being short-circuited through the reexport instead of passing through
|
||||
the namespace hierarchy as it normally would.
|
||||
22
src/doc/reference/src/whitespace.md
Normal file
22
src/doc/reference/src/whitespace.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Whitespace
|
||||
|
||||
Whitespace is any non-empty string containing only characters that have the
|
||||
`Pattern_White_Space` Unicode property, namely:
|
||||
|
||||
- `U+0009` (horizontal tab, `'\t'`)
|
||||
- `U+000A` (line feed, `'\n'`)
|
||||
- `U+000B` (vertical tab)
|
||||
- `U+000C` (form feed)
|
||||
- `U+000D` (carriage return, `'\r'`)
|
||||
- `U+0020` (space, `' '`)
|
||||
- `U+0085` (next line)
|
||||
- `U+200E` (left-to-right mark)
|
||||
- `U+200F` (right-to-left mark)
|
||||
- `U+2028` (line separator)
|
||||
- `U+2029` (paragraph separator)
|
||||
|
||||
Rust is a "free-form" language, meaning that all forms of whitespace serve only
|
||||
to separate _tokens_ in the grammar, and have no semantic significance.
|
||||
|
||||
A Rust program has identical meaning if each whitespace element is replaced
|
||||
with any other legal whitespace element, such as a single space character.
|
||||
|
|
@ -102,7 +102,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
|||
/// [downgrade]: struct.Arc.html#method.downgrade
|
||||
/// [upgrade]: struct.Weak.html#method.upgrade
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
/// [assoc]: ../../book/method-syntax.html#Associated%20functions
|
||||
/// [assoc]: ../../book/method-syntax.html#associated-functions
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@
|
|||
//! [downgrade]: struct.Rc.html#method.downgrade
|
||||
//! [upgrade]: struct.Weak.html#method.upgrade
|
||||
//! [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
//! [assoc]: ../../book/method-syntax.html#Associated%20functions
|
||||
//! [assoc]: ../../book/method-syntax.html#associated-functions
|
||||
//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
|||
|
|
@ -1250,17 +1250,17 @@ impl String {
|
|||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Divide one string into two at an index.
|
||||
/// Splits the string into two at the given index.
|
||||
///
|
||||
/// The argument, `mid`, should be a byte offset from the start of the string. It must also
|
||||
/// be on the boundary of a UTF-8 code point.
|
||||
/// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and
|
||||
/// the returned `String` contains bytes `[at, len)`. `at` must be on the
|
||||
/// boundary of a UTF-8 code point.
|
||||
///
|
||||
/// The two strings returned go from the start of the string to `mid`, and from `mid` to the end
|
||||
/// of the string.
|
||||
/// Note that the capacity of `self` does not change.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `mid` is not on a `UTF-8` code point boundary, or if it is beyond the last
|
||||
/// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last
|
||||
/// code point of the string.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -1275,9 +1275,9 @@ impl String {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "string_split_off", since = "1.16.0")]
|
||||
pub fn split_off(&mut self, mid: usize) -> String {
|
||||
assert!(self.is_char_boundary(mid));
|
||||
let other = self.vec.split_off(mid);
|
||||
pub fn split_off(&mut self, at: usize) -> String {
|
||||
assert!(self.is_char_boundary(at));
|
||||
let other = self.vec.split_off(at);
|
||||
unsafe { String::from_utf8_unchecked(other) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -687,7 +687,7 @@ extern "rust-intrinsic" {
|
|||
/// The [nomicon](../../nomicon/transmutes.html) has additional
|
||||
/// documentation.
|
||||
///
|
||||
/// [ub]: ../../reference.html#behavior-considered-undefined
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1603,12 +1603,12 @@ pub trait Iterator {
|
|||
let mut i = self.len();
|
||||
|
||||
while let Some(v) = self.next_back() {
|
||||
if predicate(v) {
|
||||
return Some(i - 1);
|
||||
}
|
||||
// No need for an overflow check here, because `ExactSizeIterator`
|
||||
// implies that the number of elements fits into a `usize`.
|
||||
i -= 1;
|
||||
if predicate(v) {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
@ -1616,7 +1616,9 @@ pub trait Iterator {
|
|||
/// Returns the maximum element of an iterator.
|
||||
///
|
||||
/// If several elements are equally maximum, the last element is
|
||||
/// returned.
|
||||
/// returned. If the iterator is empty, [`None`] is returned.
|
||||
///
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1624,8 +1626,10 @@ pub trait Iterator {
|
|||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
/// let b: Vec<u32> = Vec::new();
|
||||
///
|
||||
/// assert_eq!(a.iter().max(), Some(&3));
|
||||
/// assert_eq!(b.iter().max(), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -1642,7 +1646,9 @@ pub trait Iterator {
|
|||
/// Returns the minimum element of an iterator.
|
||||
///
|
||||
/// If several elements are equally minimum, the first element is
|
||||
/// returned.
|
||||
/// returned. If the iterator is empty, [`None`] is returned.
|
||||
///
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1650,8 +1656,10 @@ pub trait Iterator {
|
|||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
/// let b: Vec<u32> = Vec::new();
|
||||
///
|
||||
/// assert_eq!(a.iter().min(), Some(&1));
|
||||
/// assert_eq!(b.iter().min(), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -1669,7 +1677,9 @@ pub trait Iterator {
|
|||
/// specified function.
|
||||
///
|
||||
/// If several elements are equally maximum, the last element is
|
||||
/// returned.
|
||||
/// returned. If the iterator is empty, [`None`] is returned.
|
||||
///
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1694,7 +1704,9 @@ pub trait Iterator {
|
|||
/// specified comparison function.
|
||||
///
|
||||
/// If several elements are equally maximum, the last element is
|
||||
/// returned.
|
||||
/// returned. If the iterator is empty, [`None`] is returned.
|
||||
///
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1719,7 +1731,9 @@ pub trait Iterator {
|
|||
/// specified function.
|
||||
///
|
||||
/// If several elements are equally minimum, the first element is
|
||||
/// returned.
|
||||
/// returned. If the iterator is empty, [`None`] is returned.
|
||||
///
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1743,7 +1757,9 @@ pub trait Iterator {
|
|||
/// specified comparison function.
|
||||
///
|
||||
/// If several elements are equally minimum, the first element is
|
||||
/// returned.
|
||||
/// returned. If the iterator is empty, [`None`] is returned.
|
||||
///
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ use hash::Hasher;
|
|||
///
|
||||
/// [`Rc`]: ../../std/rc/struct.Rc.html
|
||||
/// [arc]: ../../std/sync/struct.Arc.html
|
||||
/// [ub]: ../../reference.html#behavior-considered-undefined
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "send"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||
|
|
@ -338,7 +338,7 @@ pub trait Copy : Clone {
|
|||
/// [mutex]: ../../std/sync/struct.Mutex.html
|
||||
/// [rwlock]: ../../std/sync/struct.RwLock.html
|
||||
/// [unsafecell]: ../cell/struct.UnsafeCell.html
|
||||
/// [ub]: ../../reference.html#behavior-considered-undefined
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
/// [transmute]: ../../std/mem/fn.transmute.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "sync"]
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ pub use intrinsics::transmute;
|
|||
/// [FFI]: ../../book/ffi.html
|
||||
/// [box]: ../../std/boxed/struct.Box.html
|
||||
/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
|
||||
/// [ub]: ../../reference.html#behavior-considered-undefined
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn forget<T>(t: T) {
|
||||
|
|
@ -318,7 +318,7 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
|
|||
///
|
||||
/// [uninit]: fn.uninitialized.html
|
||||
/// [FFI]: ../../book/ffi.html
|
||||
/// [ub]: ../../reference.html#behavior-considered-undefined
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -417,7 +417,7 @@ pub unsafe fn zeroed<T>() -> T {
|
|||
/// [`Vec`]: ../../std/vec/struct.Vec.html
|
||||
/// [`vec!`]: ../../std/macro.vec.html
|
||||
/// [`Clone`]: ../../std/clone/trait.Clone.html
|
||||
/// [ub]: ../../reference.html#behavior-considered-undefined
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
/// [write]: ../ptr/fn.write.html
|
||||
/// [copy]: ../intrinsics/fn.copy.html
|
||||
/// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html
|
||||
|
|
@ -525,7 +525,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
|
|||
/// it will not release any borrows, as borrows are based on lexical scope.
|
||||
///
|
||||
/// This effectively does nothing for
|
||||
/// [types which implement `Copy`](../../book/ownership.html#Copy%20types),
|
||||
/// [types which implement `Copy`](../../book/ownership.html#copy-types),
|
||||
/// e.g. integers. Such values are copied and _then_ moved into the function,
|
||||
/// so the value persists after this function call.
|
||||
///
|
||||
|
|
@ -626,7 +626,7 @@ pub fn drop<T>(_x: T) { }
|
|||
/// same size. This function triggers [undefined behavior][ub] if `U` is larger than
|
||||
/// `T`.
|
||||
///
|
||||
/// [ub]: ../../reference.html#behavior-considered-undefined
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
/// [size_of]: fn.size_of.html
|
||||
///
|
||||
/// # Examples
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
/// Book][moreinfo] contains more details about the precise nature of
|
||||
/// these internals.
|
||||
///
|
||||
/// [moreinfo]: ../../book/trait-objects.html#Representation
|
||||
/// [moreinfo]: ../../book/trait-objects.html#representation
|
||||
///
|
||||
/// `TraitObject` is guaranteed to match layouts, but it is not the
|
||||
/// type of trait objects (e.g. the fields are not directly accessible
|
||||
|
|
|
|||
|
|
@ -131,7 +131,37 @@ pub enum DepNode<D: Clone + Debug> {
|
|||
// which would yield an overly conservative dep-graph.
|
||||
TraitItems(D),
|
||||
ReprHints(D),
|
||||
TraitSelect(Vec<D>),
|
||||
|
||||
// Trait selection cache is a little funny. Given a trait
|
||||
// reference like `Foo: SomeTrait<Bar>`, there could be
|
||||
// arbitrarily many def-ids to map on in there (e.g., `Foo`,
|
||||
// `SomeTrait`, `Bar`). We could have a vector of them, but it
|
||||
// requires heap-allocation, and trait sel in general can be a
|
||||
// surprisingly hot path. So instead we pick two def-ids: the
|
||||
// trait def-id, and the first def-id in the input types. If there
|
||||
// is no def-id in the input types, then we use the trait def-id
|
||||
// again. So for example:
|
||||
//
|
||||
// - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
|
||||
// - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
|
||||
// - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
|
||||
// - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
|
||||
// - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
|
||||
// - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
||||
// - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
||||
// - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
||||
// - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
||||
//
|
||||
// You can see that we map many trait refs to the same
|
||||
// trait-select node. This is not a problem, it just means
|
||||
// imprecision in our dep-graph tracking. The important thing is
|
||||
// that for any given trait-ref, we always map to the **same**
|
||||
// trait-select node.
|
||||
TraitSelect { trait_def_id: D, input_def_id: D },
|
||||
|
||||
// For proj. cache, we just keep a list of all def-ids, since it is
|
||||
// not a hotspot.
|
||||
ProjectionCache { def_ids: Vec<D> },
|
||||
}
|
||||
|
||||
impl<D: Clone + Debug> DepNode<D> {
|
||||
|
|
@ -236,9 +266,17 @@ impl<D: Clone + Debug> DepNode<D> {
|
|||
TraitImpls(ref d) => op(d).map(TraitImpls),
|
||||
TraitItems(ref d) => op(d).map(TraitItems),
|
||||
ReprHints(ref d) => op(d).map(ReprHints),
|
||||
TraitSelect(ref type_ds) => {
|
||||
let type_ds = try_opt!(type_ds.iter().map(|d| op(d)).collect());
|
||||
Some(TraitSelect(type_ds))
|
||||
TraitSelect { ref trait_def_id, ref input_def_id } => {
|
||||
op(trait_def_id).and_then(|trait_def_id| {
|
||||
op(input_def_id).and_then(|input_def_id| {
|
||||
Some(TraitSelect { trait_def_id: trait_def_id,
|
||||
input_def_id: input_def_id })
|
||||
})
|
||||
})
|
||||
}
|
||||
ProjectionCache { ref def_ids } => {
|
||||
let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
|
||||
def_ids.map(|d| ProjectionCache { def_ids: d })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,32 +59,45 @@ pub enum Def {
|
|||
Err,
|
||||
}
|
||||
|
||||
/// The result of resolving a path.
|
||||
/// Before type checking completes, `depth` represents the number of
|
||||
/// trailing segments which are yet unresolved. Afterwards, if there
|
||||
/// were no errors, all paths should be fully resolved, with `depth`
|
||||
/// set to `0` and `base_def` representing the final resolution.
|
||||
///
|
||||
/// The result of resolving a path before lowering to HIR.
|
||||
/// `base_def` is definition of resolved part of the
|
||||
/// path, `unresolved_segments` is the number of unresolved
|
||||
/// segments.
|
||||
/// module::Type::AssocX::AssocY::MethodOrAssocType
|
||||
/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/// base_def depth = 3
|
||||
/// base_def unresolved_segments = 3
|
||||
///
|
||||
/// <T as Trait>::AssocX::AssocY::MethodOrAssocType
|
||||
/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/// base_def depth = 2
|
||||
/// base_def unresolved_segments = 2
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct PathResolution {
|
||||
pub base_def: Def,
|
||||
pub depth: usize
|
||||
base_def: Def,
|
||||
unresolved_segments: usize,
|
||||
}
|
||||
|
||||
impl PathResolution {
|
||||
pub fn new(def: Def) -> PathResolution {
|
||||
PathResolution { base_def: def, depth: 0 }
|
||||
pub fn new(def: Def) -> Self {
|
||||
PathResolution { base_def: def, unresolved_segments: 0 }
|
||||
}
|
||||
|
||||
pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
|
||||
if def == Def::Err { unresolved_segments = 0 }
|
||||
PathResolution { base_def: def, unresolved_segments: unresolved_segments }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn base_def(&self) -> Def {
|
||||
self.base_def
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn unresolved_segments(&self) -> usize {
|
||||
self.unresolved_segments
|
||||
}
|
||||
|
||||
pub fn kind_name(&self) -> &'static str {
|
||||
if self.depth != 0 {
|
||||
if self.unresolved_segments != 0 {
|
||||
"associated item"
|
||||
} else {
|
||||
self.base_def.kind_name()
|
||||
|
|
|
|||
|
|
@ -217,10 +217,10 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
fn expect_full_def(&mut self, id: NodeId) -> Def {
|
||||
self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
|
||||
if pr.depth != 0 {
|
||||
if pr.unresolved_segments() != 0 {
|
||||
bug!("path not fully resolved: {:?}", pr);
|
||||
}
|
||||
pr.base_def
|
||||
pr.base_def()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -421,9 +421,9 @@ impl<'a> LoweringContext<'a> {
|
|||
let resolution = self.resolver.get_resolution(id)
|
||||
.unwrap_or(PathResolution::new(Def::Err));
|
||||
|
||||
let proj_start = p.segments.len() - resolution.depth;
|
||||
let proj_start = p.segments.len() - resolution.unresolved_segments();
|
||||
let path = P(hir::Path {
|
||||
def: resolution.base_def,
|
||||
def: resolution.base_def(),
|
||||
segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
|
||||
let param_mode = match (qself_position, param_mode) {
|
||||
(Some(j), ParamMode::Optional) if i < j => {
|
||||
|
|
@ -443,7 +443,7 @@ impl<'a> LoweringContext<'a> {
|
|||
index: this.def_key(def_id).parent.expect("missing parent")
|
||||
}
|
||||
};
|
||||
let type_def_id = match resolution.base_def {
|
||||
let type_def_id = match resolution.base_def() {
|
||||
Def::AssociatedTy(def_id) if i + 2 == proj_start => {
|
||||
Some(parent_def_id(self, def_id))
|
||||
}
|
||||
|
|
@ -474,7 +474,7 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
// Simple case, either no projections, or only fully-qualified.
|
||||
// E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
|
||||
if resolution.depth == 0 {
|
||||
if resolution.unresolved_segments() == 0 {
|
||||
return hir::QPath::Resolved(qself, path);
|
||||
}
|
||||
|
||||
|
|
@ -749,7 +749,7 @@ impl<'a> LoweringContext<'a> {
|
|||
bound_pred.bound_lifetimes.is_empty() => {
|
||||
if let Some(Def::TyParam(def_id)) =
|
||||
self.resolver.get_resolution(bound_pred.bounded_ty.id)
|
||||
.map(|d| d.base_def) {
|
||||
.map(|d| d.base_def()) {
|
||||
if let Some(node_id) =
|
||||
self.resolver.definitions().as_local_node_id(def_id) {
|
||||
for ty_param in &g.ty_params {
|
||||
|
|
@ -1295,7 +1295,7 @@ impl<'a> LoweringContext<'a> {
|
|||
PatKind::Wild => hir::PatKind::Wild,
|
||||
PatKind::Ident(ref binding_mode, pth1, ref sub) => {
|
||||
self.with_parent_def(p.id, |this| {
|
||||
match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
|
||||
match this.resolver.get_resolution(p.id).map(|d| d.base_def()) {
|
||||
// `None` can occur in body-less function signatures
|
||||
def @ None | def @ Some(Def::Local(_)) => {
|
||||
let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| {
|
||||
|
|
|
|||
|
|
@ -65,9 +65,6 @@ use super::region_inference::ConcreteFailure;
|
|||
use super::region_inference::SubSupConflict;
|
||||
use super::region_inference::GenericBoundFailure;
|
||||
use super::region_inference::GenericKind;
|
||||
use super::region_inference::ProcessedErrors;
|
||||
use super::region_inference::ProcessedErrorOrigin;
|
||||
use super::region_inference::SameRegions;
|
||||
|
||||
use hir::map as hir_map;
|
||||
use hir;
|
||||
|
|
@ -77,11 +74,10 @@ use infer;
|
|||
use middle::region;
|
||||
use traits::{ObligationCause, ObligationCauseCode};
|
||||
use ty::{self, TyCtxt, TypeFoldable};
|
||||
use ty::{Region, ReFree, Issue32330};
|
||||
use ty::{Region, Issue32330};
|
||||
use ty::error::TypeError;
|
||||
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use syntax_pos::{Pos, Span};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
|
|
@ -255,8 +251,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
// try to pre-process the errors, which will group some of them
|
||||
// together into a `ProcessedErrors` group:
|
||||
let processed_errors = self.process_errors(errors);
|
||||
let errors = processed_errors.as_ref().unwrap_or(errors);
|
||||
let errors = self.process_errors(errors);
|
||||
|
||||
debug!("report_region_errors: {} errors after preprocessing", errors.len());
|
||||
|
||||
|
|
@ -278,13 +273,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
sub_origin, sub_r,
|
||||
sup_origin, sup_r);
|
||||
}
|
||||
|
||||
ProcessedErrors(ref origins,
|
||||
ref same_regions) => {
|
||||
if !same_regions.is_empty() {
|
||||
self.report_processed_errors(origins);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -300,202 +288,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
// duplicates that will be unhelpful to the end-user. But
|
||||
// obviously it never weeds out ALL errors.
|
||||
fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
|
||||
-> Option<Vec<RegionResolutionError<'tcx>>> {
|
||||
-> Vec<RegionResolutionError<'tcx>> {
|
||||
debug!("process_errors()");
|
||||
let mut origins = Vec::new();
|
||||
|
||||
// we collect up ConcreteFailures and SubSupConflicts that are
|
||||
// relating free-regions bound on the fn-header and group them
|
||||
// together into this vector
|
||||
let mut same_regions = Vec::new();
|
||||
// We want to avoid reporting generic-bound failures if we can
|
||||
// avoid it: these have a very high rate of being unhelpful in
|
||||
// practice. This is because they are basically secondary
|
||||
// checks that test the state of the region graph after the
|
||||
// rest of inference is done, and the other kinds of errors
|
||||
// indicate that the region constraint graph is internally
|
||||
// inconsistent, so these test results are likely to be
|
||||
// meaningless.
|
||||
//
|
||||
// Therefore, we filter them out of the list unless they are
|
||||
// the only thing in the list.
|
||||
|
||||
// here we put errors that we will not be able to process nicely
|
||||
let mut other_errors = Vec::new();
|
||||
let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
|
||||
ConcreteFailure(..) => false,
|
||||
SubSupConflict(..) => false,
|
||||
GenericBoundFailure(..) => true,
|
||||
};
|
||||
|
||||
// we collect up GenericBoundFailures in here.
|
||||
let mut bound_failures = Vec::new();
|
||||
|
||||
for error in errors {
|
||||
// Check whether we can process this error into some other
|
||||
// form; if not, fall through.
|
||||
match *error {
|
||||
ConcreteFailure(ref origin, sub, sup) => {
|
||||
debug!("processing ConcreteFailure");
|
||||
if let SubregionOrigin::CompareImplMethodObligation { .. } = *origin {
|
||||
// When comparing an impl method against a
|
||||
// trait method, it is not helpful to suggest
|
||||
// changes to the impl method. This is
|
||||
// because the impl method signature is being
|
||||
// checked using the trait's environment, so
|
||||
// usually the changes we suggest would
|
||||
// actually have to be applied to the *trait*
|
||||
// method (and it's not clear that the trait
|
||||
// method is even under the user's control).
|
||||
} else if let Some(same_frs) = free_regions_from_same_fn(self.tcx, sub, sup) {
|
||||
origins.push(
|
||||
ProcessedErrorOrigin::ConcreteFailure(
|
||||
origin.clone(),
|
||||
sub,
|
||||
sup));
|
||||
append_to_same_regions(&mut same_regions, &same_frs);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
SubSupConflict(ref var_origin, ref sub_origin, sub, ref sup_origin, sup) => {
|
||||
debug!("processing SubSupConflict sub: {:?} sup: {:?}", sub, sup);
|
||||
match (sub_origin, sup_origin) {
|
||||
(&SubregionOrigin::CompareImplMethodObligation { .. }, _) => {
|
||||
// As above, when comparing an impl method
|
||||
// against a trait method, it is not helpful
|
||||
// to suggest changes to the impl method.
|
||||
}
|
||||
(_, &SubregionOrigin::CompareImplMethodObligation { .. }) => {
|
||||
// See above.
|
||||
}
|
||||
_ => {
|
||||
if let Some(same_frs) = free_regions_from_same_fn(self.tcx, sub, sup) {
|
||||
origins.push(
|
||||
ProcessedErrorOrigin::VariableFailure(
|
||||
var_origin.clone()));
|
||||
append_to_same_regions(&mut same_regions, &same_frs);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GenericBoundFailure(ref origin, ref kind, region) => {
|
||||
bound_failures.push((origin.clone(), kind.clone(), region));
|
||||
continue;
|
||||
}
|
||||
ProcessedErrors(..) => {
|
||||
bug!("should not encounter a `ProcessedErrors` yet: {:?}", error)
|
||||
}
|
||||
}
|
||||
|
||||
// No changes to this error.
|
||||
other_errors.push(error.clone());
|
||||
}
|
||||
|
||||
// ok, let's pull together the errors, sorted in an order that
|
||||
// we think will help user the best
|
||||
let mut processed_errors = vec![];
|
||||
|
||||
// first, put the processed errors, if any
|
||||
if !same_regions.is_empty() {
|
||||
let common_scope_id = same_regions[0].scope_id;
|
||||
for sr in &same_regions {
|
||||
// Since ProcessedErrors is used to reconstruct the function
|
||||
// declaration, we want to make sure that they are, in fact,
|
||||
// from the same scope
|
||||
if sr.scope_id != common_scope_id {
|
||||
debug!("returning empty result from process_errors because
|
||||
{} != {}", sr.scope_id, common_scope_id);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
assert!(origins.len() > 0);
|
||||
let pe = ProcessedErrors(origins, same_regions);
|
||||
debug!("errors processed: {:?}", pe);
|
||||
processed_errors.push(pe);
|
||||
}
|
||||
|
||||
// next, put the other misc errors
|
||||
processed_errors.extend(other_errors);
|
||||
|
||||
// finally, put the `T: 'a` errors, but only if there were no
|
||||
// other errors. otherwise, these have a very high rate of
|
||||
// being unhelpful in practice. This is because they are
|
||||
// basically secondary checks that test the state of the
|
||||
// region graph after the rest of inference is done, and the
|
||||
// other kinds of errors indicate that the region constraint
|
||||
// graph is internally inconsistent, so these test results are
|
||||
// likely to be meaningless.
|
||||
if processed_errors.is_empty() {
|
||||
for (origin, kind, region) in bound_failures {
|
||||
processed_errors.push(GenericBoundFailure(origin, kind, region));
|
||||
}
|
||||
}
|
||||
|
||||
// we should always wind up with SOME errors, unless there were no
|
||||
// errors to start
|
||||
assert!(if errors.len() > 0 {processed_errors.len() > 0} else {true});
|
||||
|
||||
return Some(processed_errors);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FreeRegionsFromSameFn {
|
||||
sub_fr: ty::FreeRegion,
|
||||
sup_fr: ty::FreeRegion,
|
||||
scope_id: ast::NodeId
|
||||
}
|
||||
|
||||
impl FreeRegionsFromSameFn {
|
||||
fn new(sub_fr: ty::FreeRegion,
|
||||
sup_fr: ty::FreeRegion,
|
||||
scope_id: ast::NodeId)
|
||||
-> FreeRegionsFromSameFn {
|
||||
FreeRegionsFromSameFn {
|
||||
sub_fr: sub_fr,
|
||||
sup_fr: sup_fr,
|
||||
scope_id: scope_id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn free_regions_from_same_fn<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
sub: &'tcx Region,
|
||||
sup: &'tcx Region)
|
||||
-> Option<FreeRegionsFromSameFn> {
|
||||
debug!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub, sup);
|
||||
let (scope_id, fr1, fr2) = match (sub, sup) {
|
||||
(&ReFree(fr1), &ReFree(fr2)) => {
|
||||
if fr1.scope != fr2.scope {
|
||||
return None
|
||||
}
|
||||
assert!(fr1.scope == fr2.scope);
|
||||
(fr1.scope.node_id(&tcx.region_maps), fr1, fr2)
|
||||
},
|
||||
_ => return None
|
||||
};
|
||||
let parent = tcx.hir.get_parent(scope_id);
|
||||
let parent_node = tcx.hir.find(parent);
|
||||
match parent_node {
|
||||
Some(node) => match node {
|
||||
hir_map::NodeItem(item) => match item.node {
|
||||
hir::ItemFn(..) => {
|
||||
Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
hir_map::NodeImplItem(..) |
|
||||
hir_map::NodeTraitItem(..) => {
|
||||
Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
|
||||
},
|
||||
_ => None
|
||||
},
|
||||
None => {
|
||||
debug!("no parent node of scope_id {}", scope_id);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn append_to_same_regions(same_regions: &mut Vec<SameRegions>,
|
||||
same_frs: &FreeRegionsFromSameFn) {
|
||||
debug!("append_to_same_regions(same_regions={:?}, same_frs={:?})",
|
||||
same_regions, same_frs);
|
||||
let scope_id = same_frs.scope_id;
|
||||
let (sub_fr, sup_fr) = (same_frs.sub_fr, same_frs.sup_fr);
|
||||
for sr in same_regions.iter_mut() {
|
||||
if sr.contains(&sup_fr.bound_region) && scope_id == sr.scope_id {
|
||||
sr.push(sub_fr.bound_region);
|
||||
return
|
||||
}
|
||||
}
|
||||
same_regions.push(SameRegions {
|
||||
scope_id: scope_id,
|
||||
regions: vec![sub_fr.bound_region, sup_fr.bound_region]
|
||||
})
|
||||
if errors.iter().all(|e| is_bound_failure(e)) {
|
||||
errors.clone()
|
||||
} else {
|
||||
errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1072,20 +889,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
self.note_region_origin(&mut err, &sub_origin);
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn report_processed_errors(&self,
|
||||
origins: &[ProcessedErrorOrigin<'tcx>]) {
|
||||
for origin in origins.iter() {
|
||||
let mut err = match *origin {
|
||||
ProcessedErrorOrigin::VariableFailure(ref var_origin) =>
|
||||
self.report_inference_failure(var_origin.clone()),
|
||||
ProcessedErrorOrigin::ConcreteFailure(ref sr_origin, sub, sup) =>
|
||||
self.report_concrete_failure(sr_origin.clone(), sub, sup),
|
||||
};
|
||||
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use rustc_data_structures::graph::{self, Direction, NodeIndex, OUTGOING};
|
|||
use rustc_data_structures::unify::{self, UnificationTable};
|
||||
use middle::free_region::FreeRegionMap;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::{BoundRegion, Region, RegionVid};
|
||||
use ty::{Region, RegionVid};
|
||||
use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased};
|
||||
use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
|
||||
|
||||
|
|
@ -171,13 +171,6 @@ pub enum RegionResolutionError<'tcx> {
|
|||
&'tcx Region,
|
||||
SubregionOrigin<'tcx>,
|
||||
&'tcx Region),
|
||||
|
||||
/// For subsets of `ConcreteFailure` and `SubSupConflict`, we can derive
|
||||
/// more specific errors message by suggesting to the user where they
|
||||
/// should put a lifetime. In those cases we process and put those errors
|
||||
/// into `ProcessedErrors` before we do any reporting.
|
||||
ProcessedErrors(Vec<ProcessedErrorOrigin<'tcx>>,
|
||||
Vec<SameRegions>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -186,33 +179,6 @@ pub enum ProcessedErrorOrigin<'tcx> {
|
|||
VariableFailure(RegionVariableOrigin),
|
||||
}
|
||||
|
||||
/// SameRegions is used to group regions that we think are the same and would
|
||||
/// like to indicate so to the user.
|
||||
/// For example, the following function
|
||||
/// ```
|
||||
/// struct Foo { bar: i32 }
|
||||
/// fn foo2<'a, 'b>(x: &'a Foo) -> &'b i32 {
|
||||
/// &x.bar
|
||||
/// }
|
||||
/// ```
|
||||
/// would report an error because we expect 'a and 'b to match, and so we group
|
||||
/// 'a and 'b together inside a SameRegions struct
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SameRegions {
|
||||
pub scope_id: ast::NodeId,
|
||||
pub regions: Vec<BoundRegion>,
|
||||
}
|
||||
|
||||
impl SameRegions {
|
||||
pub fn contains(&self, other: &BoundRegion) -> bool {
|
||||
self.regions.contains(other)
|
||||
}
|
||||
|
||||
pub fn push(&mut self, other: BoundRegion) {
|
||||
self.regions.push(other);
|
||||
}
|
||||
}
|
||||
|
||||
pub type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
|
||||
|
||||
pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
|
|
|
|||
|
|
@ -777,6 +777,12 @@ pub enum StatementKind<'tcx> {
|
|||
/// End the current live range for the storage of the local.
|
||||
StorageDead(Lvalue<'tcx>),
|
||||
|
||||
InlineAsm {
|
||||
asm: InlineAsm,
|
||||
outputs: Vec<Lvalue<'tcx>>,
|
||||
inputs: Vec<Operand<'tcx>>
|
||||
},
|
||||
|
||||
/// No-op. Useful for deleting instructions without affecting statement indices.
|
||||
Nop,
|
||||
}
|
||||
|
|
@ -790,7 +796,10 @@ impl<'tcx> Debug for Statement<'tcx> {
|
|||
StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv),
|
||||
SetDiscriminant{lvalue: ref lv, variant_index: index} => {
|
||||
write!(fmt, "discriminant({:?}) = {:?}", lv, index)
|
||||
}
|
||||
},
|
||||
InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
|
||||
},
|
||||
Nop => write!(fmt, "nop"),
|
||||
}
|
||||
}
|
||||
|
|
@ -1004,12 +1013,6 @@ pub enum Rvalue<'tcx> {
|
|||
/// that `Foo` has a destructor. These rvalues can be optimized
|
||||
/// away after type-checking and before lowering.
|
||||
Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
|
||||
|
||||
InlineAsm {
|
||||
asm: InlineAsm,
|
||||
outputs: Vec<Lvalue<'tcx>>,
|
||||
inputs: Vec<Operand<'tcx>>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
|
|
@ -1111,10 +1114,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
|||
UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
|
||||
Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval),
|
||||
Box(ref t) => write!(fmt, "Box({:?})", t),
|
||||
InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
|
||||
}
|
||||
|
||||
Ref(_, borrow_kind, ref lv) => {
|
||||
let kind_str = match borrow_kind {
|
||||
BorrowKind::Shared => "",
|
||||
|
|
|
|||
|
|
@ -207,7 +207,6 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Rvalue::InlineAsm { .. } => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -333,6 +333,16 @@ macro_rules! make_mir_visitor {
|
|||
StatementKind::StorageDead(ref $($mutability)* lvalue) => {
|
||||
self.visit_lvalue(lvalue, LvalueContext::StorageDead, location);
|
||||
}
|
||||
StatementKind::InlineAsm { ref $($mutability)* outputs,
|
||||
ref $($mutability)* inputs,
|
||||
asm: _ } => {
|
||||
for output in & $($mutability)* outputs[..] {
|
||||
self.visit_lvalue(output, LvalueContext::Store, location);
|
||||
}
|
||||
for input in & $($mutability)* inputs[..] {
|
||||
self.visit_operand(input, location);
|
||||
}
|
||||
}
|
||||
StatementKind::Nop => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -526,17 +536,6 @@ macro_rules! make_mir_visitor {
|
|||
self.visit_operand(operand, location);
|
||||
}
|
||||
}
|
||||
|
||||
Rvalue::InlineAsm { ref $($mutability)* outputs,
|
||||
ref $($mutability)* inputs,
|
||||
asm: _ } => {
|
||||
for output in & $($mutability)* outputs[..] {
|
||||
self.visit_lvalue(output, LvalueContext::Store, location);
|
||||
}
|
||||
for input in & $($mutability)* inputs[..] {
|
||||
self.visit_operand(input, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -628,6 +628,11 @@ pub fn get_vtable_methods<'a, 'tcx>(
|
|||
|_, _| tcx.mk_region(ty::ReErased),
|
||||
|def, _| trait_ref.substs().type_for_def(def));
|
||||
|
||||
// the trait type may have higher-ranked lifetimes in it;
|
||||
// so erase them if they appear, so that we get the type
|
||||
// at some particular call site
|
||||
let substs = tcx.erase_late_bound_regions_and_normalize(&ty::Binder(substs));
|
||||
|
||||
// It's possible that the method relies on where clauses that
|
||||
// do not hold for this particular set of type parameters.
|
||||
// Note that this method could then never be called, so we
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue