mirror of
https://git.proxmox.com/git/rustc
synced 2025-05-03 01:08:18 +00:00
New upstream version 1.32.0+dfsg1
This commit is contained in:
parent
a1dfa0c682
commit
69743fb678
96
Cargo.lock
generated
96
Cargo.lock
generated
@ -69,7 +69,7 @@ name = "atty"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -81,7 +81,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -92,7 +92,7 @@ version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -128,7 +128,7 @@ dependencies = [
|
||||
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -205,7 +205,7 @@ dependencies = [
|
||||
"jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -223,7 +223,7 @@ dependencies = [
|
||||
"serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -392,7 +392,7 @@ name = "commoncrypto-sys"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -412,7 +412,7 @@ dependencies = [
|
||||
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -431,7 +431,7 @@ dependencies = [
|
||||
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -455,7 +455,7 @@ version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -567,7 +567,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -581,7 +581,7 @@ version = "0.4.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libnghttp2-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -631,7 +631,7 @@ name = "directories"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -756,7 +756,7 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -770,7 +770,7 @@ name = "flate2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -802,7 +802,7 @@ name = "fs2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -867,7 +867,7 @@ version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1007,7 +1007,7 @@ dependencies = [
|
||||
"flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1038,7 +1038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1046,7 +1046,7 @@ name = "jobserver"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1120,7 +1120,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.43"
|
||||
version = "0.2.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -1130,7 +1130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1151,7 +1151,7 @@ version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1164,7 +1164,7 @@ version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1213,7 +1213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1285,7 +1285,7 @@ name = "memchr"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1293,7 +1293,7 @@ name = "memmap"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1316,7 +1316,7 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1384,7 +1384,7 @@ name = "num_cpus"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1411,7 +1411,7 @@ dependencies = [
|
||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1434,7 +1434,7 @@ version = "0.9.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-src 111.0.1+1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1500,7 +1500,7 @@ name = "parking_lot_core"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1511,7 +1511,7 @@ name = "parking_lot_core"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1737,7 +1737,7 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1748,7 +1748,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1774,7 +1774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -2127,7 +2127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -2213,7 +2213,7 @@ dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2754,7 +2754,7 @@ version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -2939,11 +2939,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.19"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -2953,7 +2953,7 @@ name = "tempfile"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2996,7 +2996,7 @@ name = "termion"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -3040,7 +3040,7 @@ name = "time"
|
||||
version = "0.1.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -3197,7 +3197,7 @@ name = "wait-timeout"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3261,7 +3261,7 @@ name = "xattr"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3377,7 +3377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
|
||||
"checksum lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddba4c30a78328befecec92fc94970e53b3ae385827d28620f0f5bb2493081e0"
|
||||
"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
|
||||
"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
|
||||
"checksum libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4916b5addc78ec36cc309acfcdf0b9f9d97ab7b84083118b248709c5b7029356"
|
||||
"checksum libnghttp2-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ffbfb81475cc9f625e44f3a8f8b9cf7173815ae1c7cc2fa91853ec009e38198"
|
||||
"checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d"
|
||||
@ -3506,7 +3506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)" = "816b7af21405b011a23554ea2dc3f6576dc86ca557047c34098c1d741f10f823"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
|
||||
"checksum tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "69e16840a1e0a1f1a880b739ef1cc6a4b85496c99b8aa786ccffce6e0c15624c"
|
||||
"checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2"
|
||||
"checksum tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b103c6d08d323b92ff42c8ce62abcd83ca8efa7fd5bf7927efefec75f58c76"
|
||||
"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
|
||||
"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
|
||||
|
309
RELEASES.md
309
RELEASES.md
@ -1,3 +1,312 @@
|
||||
Version 1.32.0 (2019-01-17)
|
||||
==========================
|
||||
|
||||
Language
|
||||
--------
|
||||
#### 2018 edition
|
||||
- [You can now use the `?` operator in macro definitions.][56245] The `?`
|
||||
operator allows you to specify zero or one repetitions similar to the `*` and
|
||||
`+` operators.
|
||||
- [Module paths with no leading keyword like `super`, `self`, or `crate`, will
|
||||
now always resolve to the item (`enum`, `struct`, etc.) available in the
|
||||
module if present, before resolving to a external crate or an item the prelude.][56759]
|
||||
E.g.
|
||||
```rust
|
||||
enum Color { Red, Green, Blue }
|
||||
|
||||
use Color::*;
|
||||
```
|
||||
|
||||
#### All editions
|
||||
- [You can now match against `PhantomData<T>` types.][55837]
|
||||
- [You can now match against literals in macros with the `literal`
|
||||
specifier.][56072] This will match against a literal of any type.
|
||||
E.g. `1`, `'A'`, `"Hello World"`
|
||||
- [Self can now be used as a constructor and pattern for unit and tuple structs.][56365] E.g.
|
||||
```rust
|
||||
struct Point(i32, i32);
|
||||
|
||||
impl Point {
|
||||
pub fn new(x: i32, y: i32) -> Self {
|
||||
Self(x, y)
|
||||
}
|
||||
|
||||
pub fn is_origin(&self) -> bool {
|
||||
match self {
|
||||
Self(0, 0) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
- [Self can also now be used in type definitions.][56366] E.g.
|
||||
```rust
|
||||
enum List<T>
|
||||
where
|
||||
Self: PartialOrd<Self> // can write `Self` instead of `List<T>`
|
||||
{
|
||||
Nil,
|
||||
Cons(T, Box<Self>) // likewise here
|
||||
}
|
||||
```
|
||||
- [You can now mark traits with `#[must_use]`.][55663] This provides a warning if
|
||||
a `impl Trait` or `dyn Trait` is returned and unused in the program.
|
||||
|
||||
Compiler
|
||||
--------
|
||||
- [The default allocator has changed from jemalloc to the default allocator on
|
||||
your system.][55238] The compiler itself on Linux & macOS will still use
|
||||
jemalloc, but programs compiled with it will use the system allocator.
|
||||
- [Added the `aarch64-pc-windows-msvc` target.][55702]
|
||||
|
||||
Libraries
|
||||
---------
|
||||
- [`PathBuf` now implements `FromStr`.][55148]
|
||||
- [`Box<[T]>` now implements `FromIterator<T>`.][55843]
|
||||
- [The `dbg!` macro has been stabilized.][56395] This macro enables you to
|
||||
easily debug expressions in your rust program. E.g.
|
||||
```rust
|
||||
let a = 2;
|
||||
let b = dbg!(a * 2) + 1;
|
||||
// ^-- prints: [src/main.rs:4] a * 2 = 4
|
||||
assert_eq!(b, 5);
|
||||
```
|
||||
|
||||
The following APIs are now `const` functions and can be used in a
|
||||
`const` context.
|
||||
|
||||
- [`Cell::as_ptr`]
|
||||
- [`UnsafeCell::get`]
|
||||
- [`char::is_ascii`]
|
||||
- [`iter::empty`]
|
||||
- [`ManuallyDrop::new`]
|
||||
- [`ManuallyDrop::into_inner`]
|
||||
- [`RangeInclusive::start`]
|
||||
- [`RangeInclusive::end`]
|
||||
- [`NonNull::as_ptr`]
|
||||
- [`slice::as_ptr`]
|
||||
- [`str::as_ptr`]
|
||||
- [`Duration::as_secs`]
|
||||
- [`Duration::subsec_millis`]
|
||||
- [`Duration::subsec_micros`]
|
||||
- [`Duration::subsec_nanos`]
|
||||
- [`CStr::as_ptr`]
|
||||
- [`Ipv4Addr::is_unspecified`]
|
||||
- [`Ipv6Addr::new`]
|
||||
- [`Ipv6Addr::octets`]
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
- [`i8::to_be_bytes`]
|
||||
- [`i8::to_le_bytes`]
|
||||
- [`i8::to_ne_bytes`]
|
||||
- [`i8::from_be_bytes`]
|
||||
- [`i8::from_le_bytes`]
|
||||
- [`i8::from_ne_bytes`]
|
||||
- [`i16::to_be_bytes`]
|
||||
- [`i16::to_le_bytes`]
|
||||
- [`i16::to_ne_bytes`]
|
||||
- [`i16::from_be_bytes`]
|
||||
- [`i16::from_le_bytes`]
|
||||
- [`i16::from_ne_bytes`]
|
||||
- [`i32::to_be_bytes`]
|
||||
- [`i32::to_le_bytes`]
|
||||
- [`i32::to_ne_bytes`]
|
||||
- [`i32::from_be_bytes`]
|
||||
- [`i32::from_le_bytes`]
|
||||
- [`i32::from_ne_bytes`]
|
||||
- [`i64::to_be_bytes`]
|
||||
- [`i64::to_le_bytes`]
|
||||
- [`i64::to_ne_bytes`]
|
||||
- [`i64::from_be_bytes`]
|
||||
- [`i64::from_le_bytes`]
|
||||
- [`i64::from_ne_bytes`]
|
||||
- [`i128::to_be_bytes`]
|
||||
- [`i128::to_le_bytes`]
|
||||
- [`i128::to_ne_bytes`]
|
||||
- [`i128::from_be_bytes`]
|
||||
- [`i128::from_le_bytes`]
|
||||
- [`i128::from_ne_bytes`]
|
||||
- [`isize::to_be_bytes`]
|
||||
- [`isize::to_le_bytes`]
|
||||
- [`isize::to_ne_bytes`]
|
||||
- [`isize::from_be_bytes`]
|
||||
- [`isize::from_le_bytes`]
|
||||
- [`isize::from_ne_bytes`]
|
||||
- [`u8::to_be_bytes`]
|
||||
- [`u8::to_le_bytes`]
|
||||
- [`u8::to_ne_bytes`]
|
||||
- [`u8::from_be_bytes`]
|
||||
- [`u8::from_le_bytes`]
|
||||
- [`u8::from_ne_bytes`]
|
||||
- [`u16::to_be_bytes`]
|
||||
- [`u16::to_le_bytes`]
|
||||
- [`u16::to_ne_bytes`]
|
||||
- [`u16::from_be_bytes`]
|
||||
- [`u16::from_le_bytes`]
|
||||
- [`u16::from_ne_bytes`]
|
||||
- [`u32::to_be_bytes`]
|
||||
- [`u32::to_le_bytes`]
|
||||
- [`u32::to_ne_bytes`]
|
||||
- [`u32::from_be_bytes`]
|
||||
- [`u32::from_le_bytes`]
|
||||
- [`u32::from_ne_bytes`]
|
||||
- [`u64::to_be_bytes`]
|
||||
- [`u64::to_le_bytes`]
|
||||
- [`u64::to_ne_bytes`]
|
||||
- [`u64::from_be_bytes`]
|
||||
- [`u64::from_le_bytes`]
|
||||
- [`u64::from_ne_bytes`]
|
||||
- [`u128::to_be_bytes`]
|
||||
- [`u128::to_le_bytes`]
|
||||
- [`u128::to_ne_bytes`]
|
||||
- [`u128::from_be_bytes`]
|
||||
- [`u128::from_le_bytes`]
|
||||
- [`u128::from_ne_bytes`]
|
||||
- [`usize::to_be_bytes`]
|
||||
- [`usize::to_le_bytes`]
|
||||
- [`usize::to_ne_bytes`]
|
||||
- [`usize::from_be_bytes`]
|
||||
- [`usize::from_le_bytes`]
|
||||
- [`usize::from_ne_bytes`]
|
||||
|
||||
Cargo
|
||||
-----
|
||||
- [You can now run `cargo c` as an alias for `cargo check`.][cargo/6218]
|
||||
- [Usernames are now allowed in alt registry URLs.][cargo/6242]
|
||||
|
||||
Misc
|
||||
----
|
||||
- [`libproc_macro` has been added to the `rust-src` distribution.][55280]
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
- [The argument types for AVX's
|
||||
`_mm256_stream_si256`, `_mm256_stream_pd`, `_mm256_stream_ps`][55610] have
|
||||
been changed from `*const` to `*mut` as the previous implementation
|
||||
was unsound.
|
||||
|
||||
|
||||
[55148]: https://github.com/rust-lang/rust/pull/55148/
|
||||
[55238]: https://github.com/rust-lang/rust/pull/55238/
|
||||
[55280]: https://github.com/rust-lang/rust/pull/55280/
|
||||
[55610]: https://github.com/rust-lang/rust/pull/55610/
|
||||
[55663]: https://github.com/rust-lang/rust/pull/55663/
|
||||
[55702]: https://github.com/rust-lang/rust/pull/55702/
|
||||
[55837]: https://github.com/rust-lang/rust/pull/55837/
|
||||
[55843]: https://github.com/rust-lang/rust/pull/55843/
|
||||
[56072]: https://github.com/rust-lang/rust/pull/56072/
|
||||
[56245]: https://github.com/rust-lang/rust/pull/56245/
|
||||
[56365]: https://github.com/rust-lang/rust/pull/56365/
|
||||
[56366]: https://github.com/rust-lang/rust/pull/56366/
|
||||
[56395]: https://github.com/rust-lang/rust/pull/56395/
|
||||
[56759]: https://github.com/rust-lang/rust/pull/56759/
|
||||
[cargo/6218]: https://github.com/rust-lang/cargo/pull/6218/
|
||||
[cargo/6242]: https://github.com/rust-lang/cargo/pull/6242/
|
||||
[`CStr::as_ptr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.as_ptr
|
||||
[`Cell::as_ptr`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_ptr
|
||||
[`Duration::as_secs`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs
|
||||
[`Duration::subsec_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_micros
|
||||
[`Duration::subsec_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_millis
|
||||
[`Duration::subsec_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_nanos
|
||||
[`Ipv4Addr::is_unspecified`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html#method.is_unspecified
|
||||
[`Ipv6Addr::new`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html#method.new
|
||||
[`Ipv6Addr::octets`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html#method.octets
|
||||
[`ManuallyDrop::into_inner`]: https://doc.rust-lang.org/std/mem/struct.ManuallyDrop.html#method.into_inner
|
||||
[`ManuallyDrop::new`]: https://doc.rust-lang.org/std/mem/struct.ManuallyDrop.html#method.new
|
||||
[`NonNull::as_ptr`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_ptr
|
||||
[`RangeInclusive::end`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html#method.end
|
||||
[`RangeInclusive::start`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html#method.start
|
||||
[`UnsafeCell::get`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html#method.get
|
||||
[`slice::as_ptr`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_ptr
|
||||
[`char::is_ascii`]: https://doc.rust-lang.org/std/primitive.char.html#method.is_ascii
|
||||
[`i128::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.from_be_bytes
|
||||
[`i128::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.from_le_bytes
|
||||
[`i128::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.from_ne_bytes
|
||||
[`i128::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.to_be_bytes
|
||||
[`i128::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.to_le_bytes
|
||||
[`i128::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.to_ne_bytes
|
||||
[`i16::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.from_be_bytes
|
||||
[`i16::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.from_le_bytes
|
||||
[`i16::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.from_ne_bytes
|
||||
[`i16::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.to_be_bytes
|
||||
[`i16::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.to_le_bytes
|
||||
[`i16::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.to_ne_bytes
|
||||
[`i32::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.from_be_bytes
|
||||
[`i32::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.from_le_bytes
|
||||
[`i32::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.from_ne_bytes
|
||||
[`i32::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.to_be_bytes
|
||||
[`i32::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.to_le_bytes
|
||||
[`i32::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.to_ne_bytes
|
||||
[`i64::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.from_be_bytes
|
||||
[`i64::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.from_le_bytes
|
||||
[`i64::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.from_ne_bytes
|
||||
[`i64::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.to_be_bytes
|
||||
[`i64::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.to_le_bytes
|
||||
[`i64::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.to_ne_bytes
|
||||
[`i8::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.from_be_bytes
|
||||
[`i8::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.from_le_bytes
|
||||
[`i8::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.from_ne_bytes
|
||||
[`i8::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.to_be_bytes
|
||||
[`i8::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.to_le_bytes
|
||||
[`i8::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.to_ne_bytes
|
||||
[`isize::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.from_be_bytes
|
||||
[`isize::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.from_le_bytes
|
||||
[`isize::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.from_ne_bytes
|
||||
[`isize::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.to_be_bytes
|
||||
[`isize::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.to_le_bytes
|
||||
[`isize::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.to_ne_bytes
|
||||
[`iter::empty`]: https://doc.rust-lang.org/std/iter/fn.empty.html
|
||||
[`str::as_ptr`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_ptr
|
||||
[`u128::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.from_be_bytes
|
||||
[`u128::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.from_le_bytes
|
||||
[`u128::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.from_ne_bytes
|
||||
[`u128::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.to_be_bytes
|
||||
[`u128::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.to_le_bytes
|
||||
[`u128::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.to_ne_bytes
|
||||
[`u16::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.from_be_bytes
|
||||
[`u16::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.from_le_bytes
|
||||
[`u16::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.from_ne_bytes
|
||||
[`u16::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.to_be_bytes
|
||||
[`u16::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.to_le_bytes
|
||||
[`u16::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.to_ne_bytes
|
||||
[`u32::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.from_be_bytes
|
||||
[`u32::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.from_le_bytes
|
||||
[`u32::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.from_ne_bytes
|
||||
[`u32::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.to_be_bytes
|
||||
[`u32::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.to_le_bytes
|
||||
[`u32::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.to_ne_bytes
|
||||
[`u64::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.from_be_bytes
|
||||
[`u64::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.from_le_bytes
|
||||
[`u64::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.from_ne_bytes
|
||||
[`u64::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.to_be_bytes
|
||||
[`u64::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.to_le_bytes
|
||||
[`u64::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.to_ne_bytes
|
||||
[`u8::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.from_be_bytes
|
||||
[`u8::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.from_le_bytes
|
||||
[`u8::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.from_ne_bytes
|
||||
[`u8::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.to_be_bytes
|
||||
[`u8::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.to_le_bytes
|
||||
[`u8::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.to_ne_bytes
|
||||
[`usize::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.from_be_bytes
|
||||
[`usize::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.from_le_bytes
|
||||
[`usize::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.from_ne_bytes
|
||||
[`usize::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.to_be_bytes
|
||||
[`usize::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.to_le_bytes
|
||||
[`usize::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.to_ne_bytes
|
||||
|
||||
|
||||
Version 1.31.1 (2018-12-20)
|
||||
===========================
|
||||
|
||||
- [Fix Rust failing to build on `powerpc-unknown-netbsd`][56562]
|
||||
- [Fix broken go-to-definition in RLS][rls/1171]
|
||||
- [Fix infinite loop on hover in RLS][rls/1170]
|
||||
|
||||
[56562]: https://github.com/rust-lang/rust/pull/56562
|
||||
[rls/1171]: https://github.com/rust-lang/rls/issues/1171
|
||||
[rls/1170]: https://github.com/rust-lang/rls/pull/1170
|
||||
|
||||
Version 1.31.0 (2018-12-06)
|
||||
==========================
|
||||
|
||||
|
@ -1 +1 @@
|
||||
a01e4761a1507939430d4044a5f0a35fdb2b146c
|
||||
9fda7c2237db910e41d6a712e9a2139b352e558b
|
@ -67,7 +67,7 @@ RUN ./build-gcc.sh
|
||||
COPY dist-x86_64-linux/build-python.sh /tmp/
|
||||
RUN ./build-python.sh
|
||||
|
||||
# Now build LLVM+Clang 7, afterwards configuring further compilations to use the
|
||||
# Now build LLVM+Clang 6, afterwards configuring further compilations to use the
|
||||
# clang/clang++ compilers.
|
||||
COPY dist-x86_64-linux/build-clang.sh /tmp/
|
||||
RUN ./build-clang.sh
|
||||
|
@ -67,7 +67,7 @@ RUN ./build-gcc.sh
|
||||
COPY dist-x86_64-linux/build-python.sh /tmp/
|
||||
RUN ./build-python.sh
|
||||
|
||||
# Now build LLVM+Clang 7, afterwards configuring further compilations to use the
|
||||
# Now build LLVM+Clang 6, afterwards configuring further compilations to use the
|
||||
# clang/clang++ compilers.
|
||||
COPY dist-x86_64-linux/build-clang.sh /tmp/
|
||||
RUN ./build-clang.sh
|
||||
|
@ -13,7 +13,7 @@ set -ex
|
||||
|
||||
source shared.sh
|
||||
|
||||
LLVM=7.0.0
|
||||
LLVM=6.0.0
|
||||
|
||||
mkdir clang
|
||||
cd clang
|
||||
|
@ -20,4 +20,5 @@ COPY scripts/sccache.sh /scripts/
|
||||
RUN sh /scripts/sccache.sh
|
||||
|
||||
ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
|
||||
ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu
|
||||
ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
|
||||
python2.7 ../x.py build --stage 0 src/tools/build-manifest
|
||||
|
@ -51,7 +51,7 @@ hide_output make clean
|
||||
|
||||
cd ..
|
||||
|
||||
LLVM=70
|
||||
LLVM=60
|
||||
|
||||
# may have been downloaded in a previous run
|
||||
if [ ! -d libunwind-release_$LLVM ]; then
|
||||
|
@ -52,7 +52,7 @@ fi
|
||||
#
|
||||
# FIXME: need a scheme for changing this `nightly` value to `beta` and `stable`
|
||||
# either automatically or manually.
|
||||
export RUST_RELEASE_CHANNEL=beta
|
||||
export RUST_RELEASE_CHANNEL=stable
|
||||
if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then
|
||||
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL"
|
||||
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
|
||||
|
@ -20,5 +20,5 @@ Here are the relevant sections in the new and old books:
|
||||
* <small>[In the first edition: Ch 3.27 — Attributes][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/attributes.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/attributes.html
|
||||
[2]: ../reference/attributes.html
|
||||
|
@ -9,6 +9,6 @@ You might be interested in a similar page in [the Rust Reference][3].
|
||||
* <small>[In the first edition: Section 7 — Bibliography][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/bibliography.html
|
||||
[2]: second-edition/index.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/bibliography.html
|
||||
[2]: index.html
|
||||
[3]: ../reference/influences.html
|
||||
|
@ -20,6 +20,6 @@ The best place to learn more about this is [the Rust documentation][3].
|
||||
* <small>[In the first edition: Ch 4.10 — Borrow and AsRef][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/borrow-and-asref.html
|
||||
[2]: second-edition/index.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/borrow-and-asref.html
|
||||
[2]: index.html
|
||||
[3]: ../std/convert/trait.AsRef.html
|
||||
|
@ -20,13 +20,13 @@ fn average(values: &[f64]) -> f64 {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Appendix A — Keywords][2]**
|
||||
* **[in the current edition: Appendix A — Keywords][2]**
|
||||
* [In the Rust Reference: Type Cast Expressions][3]
|
||||
* [In the Rust documentation: `mem::transmute`][4]
|
||||
* <small>[In the first edition: Ch 3.29 — Casting between types][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/casting-between-types.html
|
||||
[2]: second-edition/appendix-01-keywords.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/casting-between-types.html
|
||||
[2]: appendix-01-keywords.html
|
||||
[3]: ../reference/expressions/operator-expr.html#type-cast-expressions
|
||||
[4]: ../std/mem/fn.transmute.html
|
@ -14,9 +14,9 @@ println!("b = {}", b);
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 15.00 — Smart Pointers][2]**
|
||||
* **[In the current edition: Ch 15.00 — Smart Pointers][2]**
|
||||
* <small>[In the first edition: Ch 4.8 — Choosing your Guarantees][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/choosing-your-guarantees.html
|
||||
[2]: second-edition/ch15-00-smart-pointers.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/choosing-your-guarantees.html
|
||||
[2]: ch15-00-smart-pointers.html
|
||||
|
@ -20,9 +20,9 @@ let expensive_closure = |num| {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 13.01 — Closures][2]**
|
||||
* **[in the current edition: Ch 13.01 — Closures][2]**
|
||||
* <small>[In the first edition: Ch 3.23 — Closures][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/closures.html
|
||||
[2]: second-edition/ch13-01-closures.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/closures.html
|
||||
[2]: ch13-01-closures.html
|
||||
|
@ -15,9 +15,9 @@
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 3.04 — Comments][2]**
|
||||
* **[in the current edition: Ch 3.04 — Comments][2]**
|
||||
* <small>[In the first edition: Ch 3.4 — Comments][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/comments.html
|
||||
[2]: second-edition/ch03-04-comments.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/comments.html
|
||||
[2]: ch03-04-comments.html
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 16.00 — Fearless Concurrency][2]**
|
||||
* **[in the current edition: Ch 16.00 — Fearless Concurrency][2]**
|
||||
* <small>[In the first edition: Ch 4.6 — Concurrency][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/concurrency.html
|
||||
[2]: second-edition/ch16-00-concurrency.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/concurrency.html
|
||||
[2]: ch16-00-concurrency.html
|
||||
|
@ -23,6 +23,6 @@ The best place to learn about it is [the Rust Reference][3].
|
||||
* <small>[In the first edition: Ch 4.3 — Conditional Compilation][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/conditional-compilation.html
|
||||
[2]: second-edition/index.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/conditional-compilation.html
|
||||
[2]: index.html
|
||||
[3]: ../reference/attributes.html#conditional-compilation
|
||||
|
@ -18,11 +18,11 @@ mod network {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 7.01 — `mod` and the Filesystem][2]**
|
||||
* [In the second edition: Ch 14.02 — Publishing a Crate to Crates.io][3]
|
||||
* **[in the current edition: Ch 7.01 — `mod` and the Filesystem][2]**
|
||||
* [in the current edition: Ch 14.02 — Publishing a Crate to Crates.io][3]
|
||||
* <small>[In the first edition: Ch 3.25 — Crates and Modules][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/crates-and-modules.html
|
||||
[2]: second-edition/ch07-01-mod-and-the-filesystem.html
|
||||
[3]: second-edition/ch14-02-publishing-to-crates-io.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/crates-and-modules.html
|
||||
[2]: ch07-00-packages-crates-and-modules.html
|
||||
[3]: ch14-02-publishing-to-crates-io.html
|
||||
|
@ -22,9 +22,9 @@ impl<T> Deref for MyBox<T> {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 15.02 — Treating Smart Pointers like Regular References with the `Deref` Trait][2]**
|
||||
* **[in the current edition: Ch 15.02 — Treating Smart Pointers like Regular References with the `Deref` Trait][2]**
|
||||
* <small>[In the first edition: Ch 3.33 — Deref coercions][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/deref-coercions.html
|
||||
[2]: second-edition/ch15-02-deref.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/deref-coercions.html
|
||||
[2]: ch15-02-deref.html
|
||||
|
@ -26,9 +26,9 @@ fn main() {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 15.03 — The `Drop` Trait Runs Code on Cleanup][2]**
|
||||
* **[in the current edition: Ch 15.03 — The `Drop` Trait Runs Code on Cleanup][2]**
|
||||
* <small>[In the first edition: Ch 3.20 — Drop][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/drop.html
|
||||
[2]: second-edition/ch15-03-drop.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/drop.html
|
||||
[2]: ch15-03-drop.html
|
||||
|
@ -10,5 +10,5 @@ It is recommended to start there.
|
||||
* <small>[In the first edition: Ch 4 — Effective Rust][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/effective-rust.html
|
||||
[2]: second-edition/index.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/effective-rust.html
|
||||
[2]: index.html
|
||||
|
@ -15,9 +15,9 @@ enum IpAddrKind {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 6.01 — Defining an Enum][2]**
|
||||
* **[in the current edition: Ch 6.01 — Defining an Enum][2]**
|
||||
* <small>[In the first edition: Ch 3.13 — Enums][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/enums.html
|
||||
[2]: second-edition/ch06-01-defining-an-enum.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/enums.html
|
||||
[2]: ch06-01-defining-an-enum.html
|
||||
|
@ -8,9 +8,9 @@
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 9.00 — Error Handling][2]**
|
||||
* **[in the current edition: Ch 9.00 — Error Handling][2]**
|
||||
* <small>[In the first edition: Ch 4.7 — Error Handling][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/error-handling.html
|
||||
[2]: second-edition/ch09-00-error-handling.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/error-handling.html
|
||||
[2]: ch09-00-error-handling.html
|
||||
|
@ -23,8 +23,8 @@ fn another_function() {
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the first edition: Ch 3.2 — Functions][1]**
|
||||
* <small>[In the second edition: Ch 3.03 — Functions][2]</small>
|
||||
* <small>[in the current edition: Ch 3.03 — Functions][2]</small>
|
||||
|
||||
|
||||
[1]: first-edition/functions.html
|
||||
[2]: second-edition/ch03-03-how-functions-work.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/functions.html
|
||||
[2]: ch03-03-how-functions-work.html
|
||||
|
@ -21,10 +21,10 @@ fn main() {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 10.00 — Generic Types, Traits, and Lifetimes][2]**
|
||||
* **[in the current edition: Ch 10.00 — Generic Types, Traits, and Lifetimes][2]**
|
||||
* <small>[In the first edition: Ch 3.18 — Generics][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/generics.html
|
||||
[2]: second-edition/ch10-00-generics.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/generics.html
|
||||
[2]: ch10-00-generics.html
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
You can [continue to the exact older page][1].
|
||||
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
|
||||
|
||||
* **[In the second edition: Getting Started][2]**
|
||||
* **[in the current edition: Getting Started][2]**
|
||||
* <small>[In the first edition: Getting Started][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/getting-started.html
|
||||
[2]: second-edition/ch01-00-getting-started.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/getting-started.html
|
||||
[2]: ch01-00-getting-started.html
|
||||
|
@ -10,5 +10,5 @@ It is recommended to start there.
|
||||
* <small>[In the first edition: Glossary][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/glossary.html
|
||||
[2]: second-edition/index.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/glossary.html
|
||||
[2]: index.html
|
||||
|
@ -5,8 +5,8 @@
|
||||
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice.
|
||||
|
||||
* **[In the first edition: Tutorial — Guessing Game][1]**
|
||||
* <small>[In the second edition: Ch 2.00 — Guessing Game tutorial][2]</small>
|
||||
* <small>[in the current edition: Ch 2.00 — Guessing Game tutorial][2]</small>
|
||||
|
||||
|
||||
[1]: first-edition/guessing-game.html
|
||||
[2]: second-edition/ch02-00-guessing-game-tutorial.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/guessing-game.html
|
||||
[2]: ch02-00-guessing-game-tutorial.html
|
||||
|
@ -15,9 +15,8 @@ if let Some(3) = some_u8_value {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 6.03 — Concise Control Flow with `if let`][2]**
|
||||
* [In the current edition: Ch 6.03 — Concise Control Flow with `if let`][2]
|
||||
* <small>[In the first edition: Ch 3.21 — if let][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/if-let.html
|
||||
[2]: second-edition/ch06-03-if-let.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/if-let.html
|
||||
[2]: ch06-03-if-let.html
|
||||
|
@ -19,9 +19,9 @@ for val in v1_iter {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 13.02 — Iterators][2]**
|
||||
* **[in the current edition: Ch 13.02 — Iterators][2]**
|
||||
* <small>[In the first edition: Ch 4.5 — Iterators][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/iterators.html
|
||||
[2]: second-edition/ch13-02-iterators.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/iterators.html
|
||||
[2]: ch13-02-iterators.html
|
||||
|
@ -20,11 +20,11 @@
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 10.03 — Lifetimes][2]**
|
||||
* [In the second edition: Ch 19.02 — Advanced Lifetimes][3]
|
||||
* **[in the current edition: Ch 10.03 — Lifetimes][2]**
|
||||
* [in the current edition: Ch 19.02 — Advanced Lifetimes][3]
|
||||
* <small>[In the first edition: Ch 3.10 — Lifetimes][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/lifetimes.html
|
||||
[2]: second-edition/ch10-03-lifetime-syntax.html
|
||||
[3]: second-edition/ch19-02-advanced-lifetimes.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/lifetimes.html
|
||||
[2]: ch10-03-lifetime-syntax.html
|
||||
[3]: ch19-02-advanced-lifetimes.html
|
||||
|
@ -18,13 +18,13 @@ fn main() {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Appendix D — Macros][2]**
|
||||
* **[In the current edition: Ch 19.06 Macros][2]**
|
||||
* [Rust By Example: Macros][3]
|
||||
* [In the Rust Reference: Ch 3.1 — Macros by Example][4]
|
||||
* <small>[In the first edition: Ch 3.34 — Macros][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/macros.html
|
||||
[2]: second-edition/appendix-04-macros.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/macros.html
|
||||
[2]: ch19-06-macros.html
|
||||
[3]: https://rustbyexample.com/macros.html
|
||||
[4]: ../reference/macros-by-example.html
|
||||
|
@ -27,12 +27,12 @@ fn value_in_cents(coin: Coin) -> u32 {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 6.02 — The `match` Control Flow Operator][2]**
|
||||
* [In the second edition: Ch 18.00 — Patterns][3]
|
||||
* **[in the current edition: Ch 6.02 — The `match` Control Flow Operator][2]**
|
||||
* [in the current edition: Ch 18.00 — Patterns][3]
|
||||
* <small>[In the first edition: Ch 3.14 — Match][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/match.html
|
||||
[2]: second-edition/ch06-02-match.html
|
||||
[3]: second-edition/ch18-00-patterns.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/match.html
|
||||
[2]: ch06-02-match.html
|
||||
[3]: ch18-00-patterns.html
|
||||
|
||||
|
@ -21,9 +21,9 @@ impl Rectangle {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 5.03 — Method Syntax][2]**
|
||||
* **[in the current edition: Ch 5.03 — Method Syntax][2]**
|
||||
* <small>[In the first edition: Ch 3.16 — Method Syntax][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/method-syntax.html
|
||||
[2]: second-edition/ch05-03-method-syntax.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/method-syntax.html
|
||||
[2]: ch05-03-method-syntax.html
|
||||
|
@ -15,9 +15,9 @@ println!("The value of x is: {}", x);
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 3.01 — Variables and Mutability][2]**
|
||||
* **[in the current edition: Ch 3.01 — Variables and Mutability][2]**
|
||||
* <small>[In the first edition: Ch 3.11 — Mutability][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/mutability.html
|
||||
[2]: second-edition/ch03-01-variables-and-mutability.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/mutability.html
|
||||
[2]: ch03-01-variables-and-mutability.html
|
||||
|
@ -12,9 +12,9 @@
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 4.00 — Understanding Ownership][2]**
|
||||
* **[in the current edition: Ch 4.00 — Understanding Ownership][2]**
|
||||
* <small>[In the first edition: Ch 3.8 — Ownership][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/ownership.html
|
||||
[2]: second-edition/ch04-00-understanding-ownership.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/ownership.html
|
||||
[2]: ch04-00-understanding-ownership.html
|
||||
|
@ -16,9 +16,9 @@ let y: f32 = 3.0; // f32
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 3.02 — Data Types][2]**
|
||||
* **[in the current edition: Ch 3.02 — Data Types][2]**
|
||||
* <small>[In the first edition: Ch 3.3 — Primitive Types][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/primitive-types.html
|
||||
[2]: second-edition/ch03-02-data-types.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/primitive-types.html
|
||||
[2]: ch03-02-data-types.html
|
||||
|
@ -9,13 +9,13 @@
|
||||
This chapter does not exist yet in [the second edition][2].
|
||||
You can check out other resources that describe macros.
|
||||
|
||||
* **[In the Rust Reference: Ch 3.2 — Procedural Macros][4]**
|
||||
* **[In the current edition: Ch 19.06 Macros][2]**
|
||||
* [In the Rust Reference: Ch 3.2 — Procedural Macros][4]
|
||||
* [The `proc_macro` crate documentation][3]
|
||||
* [In the second edition: (future) Appendix D — Macros][2]
|
||||
* <small>[In the first edition: Ch 4.13 — Procedural Macros (and custom Derive)][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/procedural-macros.html
|
||||
[2]: second-edition/appendix-04-macros.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/procedural-macros.html
|
||||
[2]: ch19-06-macros.html
|
||||
[3]: ../proc_macro/index.html
|
||||
[4]: ../reference/procedural-macros.html
|
||||
[4]: ../reference/procedural-macros.html
|
||||
|
@ -16,9 +16,9 @@ fn calculate_length(s: &String) -> usize { // s is a reference to a String
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 4.02 — References and Borrowing][2]**
|
||||
* **[in the current edition: Ch 4.02 — References and Borrowing][2]**
|
||||
* <small>[In the first edition: Ch 3.9 — References and Borrowing][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/references-and-borrowing.html
|
||||
[2]: second-edition/ch04-02-references-and-borrowing.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/references-and-borrowing.html
|
||||
[2]: ch04-02-references-and-borrowing.html
|
||||
|
@ -16,12 +16,12 @@ You can check out other resources that describe release channels.
|
||||
* **[In the Rustup documentation: Keeping Rust Up-to-date][4]**
|
||||
* [On the website: Install Rust][5]
|
||||
* [In the Rust RFCs: RFC 507 — Release Channels][3]
|
||||
* [In the second edition: How Rust is Made and “Nightly Rust”][2]
|
||||
* [in the current edition: How Rust is Made and “Nightly Rust”][2]
|
||||
* <small>[In the first edition: Ch 4.11 — Release Channels][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/release-channels.html
|
||||
[2]: second-edition/appendix-07-nightly-rust.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/release-channels.html
|
||||
[2]: appendix-07-nightly-rust.html
|
||||
[3]: https://github.com/rust-lang/rfcs/blob/master/text/0507-release-channels.md
|
||||
[4]: https://github.com/rust-lang-nursery/rustup.rs/blob/master/README.md#keeping-rust-up-to-date
|
||||
[5]: https://www.rust-lang.org/en-US/install.html
|
||||
|
@ -21,5 +21,5 @@ Here are the relevant sections in the new and old books:
|
||||
* <small>[In the first edition: Ch 3.12 — Structs][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/structs.html
|
||||
[2]: second-edition/ch05-00-structs.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/structs.html
|
||||
[2]: ch05-00-structs.html
|
||||
|
@ -5,14 +5,14 @@
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
|
||||
* **[In the second edition: Ch 3.00 — Common Programming Concepts][2]**
|
||||
* [In the second edition: Appendix A — Keywords][3]
|
||||
* [In the second edition: Appendix B — Operators][4]
|
||||
* **[in the current edition: Ch 3.00 — Common Programming Concepts][2]**
|
||||
* [in the current edition: Appendix A — Keywords][3]
|
||||
* [in the current edition: Appendix B — Operators][4]
|
||||
* <small>[In the first edition: Ch 3 — Syntax and Semantics][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/syntax-and-semantics.html
|
||||
[2]: second-edition/ch03-00-common-programming-concepts.html
|
||||
[3]: second-edition/appendix-01-keywords.html
|
||||
[4]: second-edition/appendix-02-operators.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/syntax-and-semantics.html
|
||||
[2]: ch03-00-common-programming-concepts.html
|
||||
[3]: appendix-01-keywords.html
|
||||
[4]: appendix-02-operators.html
|
||||
|
||||
|
@ -4,11 +4,10 @@
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Appendix A — Keywords][2]**
|
||||
* **[In the second edition: Appendix B — Operators][3]**
|
||||
* **[In the current edition: Appendix A — Keywords][2]**
|
||||
* **[In the current edition: Appendix B — Operators][3]**
|
||||
* <small>[In the first edition: Ch 6 — Syntax Index][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/syntax-index.html
|
||||
[2]: second-edition/appendix-01-keywords.html
|
||||
[3]: second-edition/appendix-02-operators.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/syntax-index.html
|
||||
[2]: appendix-01-keywords.html
|
||||
[3]: appendix-02-operators.html
|
||||
|
@ -17,9 +17,9 @@ mod tests {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 11.00 — Testing][2]**
|
||||
* **[in the current edition: Ch 11.00 — Testing][2]**
|
||||
* <small>[In the first edition: Ch 4.2 — Testing][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/testing.html
|
||||
[2]: second-edition/ch11-00-testing.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/testing.html
|
||||
[2]: ch11-00-testing.html
|
||||
|
@ -60,9 +60,9 @@ fn main() {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 17.02 — Trait Objects][2]**
|
||||
* **[in the current edition: Ch 17.02 — Trait Objects][2]**
|
||||
* <small>[In the first edition: Ch 3.22 — Trait Objects][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/trait-objects.html
|
||||
[2]: second-edition/ch17-02-trait-objects.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/trait-objects.html
|
||||
[2]: ch17-02-trait-objects.html
|
||||
|
@ -14,11 +14,11 @@ pub trait Summarizable {
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 10.02 — Traits][2]**
|
||||
* [In the second edition: Ch 19.03 — Advanced Traits][3]
|
||||
* **[in the current edition: Ch 10.02 — Traits][2]**
|
||||
* [in the current edition: Ch 19.03 — Advanced Traits][3]
|
||||
* <small>[In the first edition: Ch 3.19 — Traits][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/traits.html
|
||||
[2]: second-edition/ch10-02-traits.html
|
||||
[3]: second-edition/ch19-03-advanced-traits.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/traits.html
|
||||
[2]: ch10-02-traits.html
|
||||
[3]: ch19-03-advanced-traits.html
|
||||
|
@ -8,11 +8,11 @@
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 19.01 — Unsafe Rust][2]**
|
||||
* **[in the current edition: Ch 19.01 — Unsafe Rust][2]**
|
||||
* [The Rustonomicon, The Dark Arts of Advanced and Unsafe Rust Programming][3]
|
||||
* <small>[In the first edition: Ch 3.36 — `unsafe`][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/unsafe.html
|
||||
[2]: second-edition/ch19-01-unsafe-rust.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/unsafe.html
|
||||
[2]: ch19-01-unsafe-rust.html
|
||||
[3]: ../nomicon/index.html
|
||||
|
@ -13,5 +13,5 @@ This particular chapter has moved to [the Unstable Book][2].
|
||||
* <small>[In the first edition: Ch 4.12 — Using Rust without the Standard Library][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/using-rust-without-the-standard-library.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/using-rust-without-the-standard-library.html
|
||||
[2]: ../unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib
|
||||
|
@ -14,10 +14,10 @@ let numbers = vec![1, 2, 3];
|
||||
|
||||
Here are the relevant sections in the new and old books:
|
||||
|
||||
* **[In the second edition: Ch 8.01 — Vectors][2]**
|
||||
* **[in the current edition: Ch 8.01 — Vectors][2]**
|
||||
* <small>[In the first edition: Ch 3.7 — Vectors][1]</small>
|
||||
|
||||
|
||||
[1]: first-edition/vectors.html
|
||||
[2]: second-edition/ch08-01-vectors.html
|
||||
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/vectors.html
|
||||
[2]: ch08-01-vectors.html
|
||||
|
||||
|
@ -15,7 +15,7 @@ library that you can use with `derive`. Each section covers:
|
||||
* Examples of operations that require the trait
|
||||
|
||||
If you want different behavior than that provided by the `derive` attribute,
|
||||
consult the [standard library documentation](../std/index.html)
|
||||
consult the [standard library documentation](../std/index.html)<!-- ignore -->
|
||||
for each trait for details of how to manually implement them.
|
||||
|
||||
The rest of the traits defined in the standard library can’t be implemented on
|
||||
|
@ -188,4 +188,4 @@ doesn’t compile.
|
||||
The source files from which this book is generated can be found on
|
||||
[GitHub][book].
|
||||
|
||||
[book]: https://github.com/rust-lang/book/tree/master/2018-edition/src
|
||||
[book]: https://github.com/rust-lang/book/tree/master/src
|
||||
|
@ -35,6 +35,7 @@ Look at the generated *Cargo.toml* file:
|
||||
name = "guessing_game"
|
||||
version = "0.1.0"
|
||||
authors = ["Your Name <you@example.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
```
|
||||
@ -169,12 +170,12 @@ let mut bar = 5; // mutable
|
||||
> line. Rust ignores everything in comments, which are discussed in more detail
|
||||
> in Chapter 3.
|
||||
|
||||
Now you know that `let mut guess` will introduce a mutable variable named
|
||||
`guess`. On the other side of the equal sign (`=`) is the value that `guess` is
|
||||
bound to, which is the result of calling `String::new`, a function that returns
|
||||
a new instance of a `String`. [`String`][string]<!-- ignore --> is a string
|
||||
type provided by the standard library that is a growable, UTF-8 encoded bit of
|
||||
text.
|
||||
Let's return to the guessing game program. You now know that `let mut guess`
|
||||
will introduce a mutable variable named `guess`. On the other side of the equal
|
||||
sign (`=`) is the value that `guess` is bound to, which is the result of
|
||||
calling `String::new`, a function that returns a new instance of a `String`.
|
||||
[`String`][string]<!-- ignore --> is a string type provided by the standard
|
||||
library that is a growable, UTF-8 encoded bit of text.
|
||||
|
||||
[string]: ../std/string/struct.String.html
|
||||
|
||||
@ -271,14 +272,14 @@ The `Err` variant means the operation failed, and `Err` contains information
|
||||
about how or why the operation failed.
|
||||
|
||||
The purpose of these `Result` types is to encode error-handling information.
|
||||
Values of the `Result` type, like any type, have methods defined on them. An
|
||||
instance of `io::Result` has an [`expect` method][expect]<!-- ignore --> that
|
||||
you can call. If this instance of `io::Result` is an `Err` value, `expect` will
|
||||
cause the program to crash and display the message that you passed as an
|
||||
argument to `expect`. If the `read_line` method returns an `Err`, it would
|
||||
likely be the result of an error coming from the underlying operating system.
|
||||
If this instance of `io::Result` is an `Ok` value, `expect` will take the
|
||||
return value that `Ok` is holding and return just that value to you so you
|
||||
Values of the `Result` type, like values of any type, have methods defined on
|
||||
them. An instance of `io::Result` has an [`expect` method][expect]<!-- ignore
|
||||
--> that you can call. If this instance of `io::Result` is an `Err` value,
|
||||
`expect` will cause the program to crash and display the message that you
|
||||
passed as an argument to `expect`. If the `read_line` method returns an `Err`,
|
||||
it would likely be the result of an error coming from the underlying operating
|
||||
system. If this instance of `io::Result` is an `Ok` value, `expect` will take
|
||||
the return value that `Ok` is holding and return just that value to you so you
|
||||
can use it. In this case, that value is the number of bytes in what the user
|
||||
entered into standard input.
|
||||
|
||||
@ -302,7 +303,7 @@ Rust warns that you haven’t used the `Result` value returned from `read_line`,
|
||||
indicating that the program hasn’t handled a possible error.
|
||||
|
||||
The right way to suppress the warning is to actually write error handling, but
|
||||
since you just want to crash this program when a problem occurs, you can use
|
||||
because you just want to crash this program when a problem occurs, you can use
|
||||
`expect`. You’ll learn about recovering from errors in Chapter 9.
|
||||
|
||||
### Printing Values with `println!` Placeholders
|
||||
@ -392,7 +393,7 @@ version 0.3.14.”
|
||||
[semver]: http://semver.org
|
||||
|
||||
Now, without changing any of the code, let’s build the project, as shown in
|
||||
Listing 2-2:
|
||||
Listing 2-2.
|
||||
|
||||
```text
|
||||
$ cargo build
|
||||
@ -450,7 +451,7 @@ your part of the code.
|
||||
Cargo has a mechanism that ensures you can rebuild the same artifact every time
|
||||
you or anyone else builds your code: Cargo will use only the versions of the
|
||||
dependencies you specified until you indicate otherwise. For example, what
|
||||
happens if next week version `v0.3.15` of the `rand` crate comes out and
|
||||
happens if next week version 0.3.15 of the `rand` crate comes out and
|
||||
contains an important bug fix but also contains a regression that will break
|
||||
your code?
|
||||
|
||||
@ -510,7 +511,7 @@ from a number of packages.
|
||||
### Generating a Random Number
|
||||
|
||||
Now that you’ve added the `rand` crate to *Cargo.toml*, let’s start using
|
||||
`rand`. The next step is to update *src/main.rs*, as shown in Listing 2-3:
|
||||
`rand`. The next step is to update *src/main.rs*, as shown in Listing 2-3.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -608,6 +609,7 @@ use std::cmp::Ordering;
|
||||
use rand::Rng;
|
||||
|
||||
fn main() {
|
||||
|
||||
// ---snip---
|
||||
|
||||
println!("You guessed: {}", guess);
|
||||
@ -629,9 +631,8 @@ The first new bit here is another `use` statement, bringing a type called
|
||||
`Greater`, and `Equal`. These are the three outcomes that are possible when you
|
||||
compare two values.
|
||||
|
||||
Then we add five new lines at the bottom that use the `Ordering` type.
|
||||
|
||||
The `cmp` method compares two values and can be called on anything that can be
|
||||
Then we add five new lines at the bottom that use the `Ordering` type. The
|
||||
`cmp` method compares two values and can be called on anything that can be
|
||||
compared. It takes a reference to whatever you want to compare with: here it’s
|
||||
comparing the `guess` to the `secret_number`. Then it returns a variant of the
|
||||
`Ordering` enum we brought into scope with the `use` statement. We use a
|
||||
@ -729,7 +730,7 @@ a variable named `guess`? It does, but Rust allows us to *shadow* the previous
|
||||
value of `guess` with a new one. This feature is often used in situations in
|
||||
which you want to convert a value from one type to another type. Shadowing lets
|
||||
us reuse the `guess` variable name rather than forcing us to create two unique
|
||||
variables, like `guess_str` and `guess` for example. (Chapter 3 covers
|
||||
variables, such as `guess_str` and `guess` for example. (Chapter 3 covers
|
||||
shadowing in more detail.)
|
||||
|
||||
We bind `guess` to the expression `guess.trim().parse()`. The `guess` in the
|
||||
@ -774,7 +775,7 @@ Let’s run the program now!
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs
|
||||
Running `target/guessing_game`
|
||||
Running `target/debug/guessing_game`
|
||||
Guess the number!
|
||||
The secret number is: 58
|
||||
Please input your guess.
|
||||
@ -834,7 +835,7 @@ shown here:
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 1.50 secs
|
||||
Running `target/guessing_game`
|
||||
Running `target/debug/guessing_game`
|
||||
Guess the number!
|
||||
The secret number is: 59
|
||||
Please input your guess.
|
||||
@ -890,15 +891,29 @@ exiting the program, because the loop is the last part of `main`.
|
||||
To further refine the game’s behavior, rather than crashing the program when
|
||||
the user inputs a non-number, let’s make the game ignore a non-number so the
|
||||
user can continue guessing. We can do that by altering the line where `guess`
|
||||
is converted from a `String` to a `u32`:
|
||||
is converted from a `String` to a `u32`, as shown in Listing 2-5.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
```rust,ignore
|
||||
// --snip--
|
||||
|
||||
io::stdin().read_line(&mut guess)
|
||||
.expect("Failed to read line");
|
||||
|
||||
let guess: u32 = match guess.trim().parse() {
|
||||
Ok(num) => num,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
println!("You guessed: {}", guess);
|
||||
|
||||
// --snip--
|
||||
```
|
||||
|
||||
<span class="caption">Listing 2-5: Ignoring a non-number guess and asking for
|
||||
another guess instead of crashing the program</span>
|
||||
|
||||
Switching from an `expect` call to a `match` expression is how you generally
|
||||
move from crashing on an error to handling the error. Remember that `parse`
|
||||
returns a `Result` type and `Result` is an enum that has the variants `Ok` or
|
||||
@ -917,16 +932,16 @@ does not match the `Ok(num)` pattern in the first `match` arm, but it does
|
||||
match the `Err(_)` pattern in the second arm. The underscore, `_`, is a
|
||||
catchall value; in this example, we’re saying we want to match all `Err`
|
||||
values, no matter what information they have inside them. So the program will
|
||||
execute the second arm’s code, `continue`, which means to go to the next
|
||||
iteration of the `loop` and ask for another guess. So effectively, the program
|
||||
ignores all errors that `parse` might encounter!
|
||||
execute the second arm’s code, `continue`, which tells the program to go to the
|
||||
next iteration of the `loop` and ask for another guess. So effectively, the
|
||||
program ignores all errors that `parse` might encounter!
|
||||
|
||||
Now everything in the program should work as expected. Let’s try it:
|
||||
|
||||
```text
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
|
||||
Running `target/guessing_game`
|
||||
Running `target/debug/guessing_game`
|
||||
Guess the number!
|
||||
The secret number is: 61
|
||||
Please input your guess.
|
||||
@ -948,7 +963,7 @@ You win!
|
||||
Awesome! With one tiny final tweak, we will finish the guessing game. Recall
|
||||
that the program is still printing the secret number. That worked well for
|
||||
testing, but it ruins the game. Let’s delete the `println!` that outputs the
|
||||
secret number. Listing 2-5 shows the final code:
|
||||
secret number. Listing 2-6 shows the final code.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -989,11 +1004,11 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
<span class="caption">Listing 2-5: Complete guessing game code</span>
|
||||
<span class="caption">Listing 2-6: Complete guessing game code</span>
|
||||
|
||||
## Summary
|
||||
|
||||
At this point, you’ve successfully built the guessing game! Congratulations!
|
||||
At this point, you’ve successfully built the guessing game. Congratulations!
|
||||
|
||||
This project was a hands-on way to introduce you to many new Rust concepts:
|
||||
`let`, `match`, methods, associated functions, the use of external crates, and
|
||||
|
@ -44,9 +44,9 @@ Even though compiler errors can be frustrating, they only mean your program
|
||||
isn’t safely doing what you want it to do yet; they do *not* mean that you’re
|
||||
not a good programmer! Experienced Rustaceans still get compiler errors.
|
||||
|
||||
The error indicates that the cause of the error is that you `cannot assign twice
|
||||
to immutable variable x`, because you tried to assign a second value to the
|
||||
immutable `x` variable.
|
||||
The error message indicates that the cause of the error is that you `cannot
|
||||
assign twice to immutable variable x`, because you tried to assign a second
|
||||
value to the immutable `x` variable.
|
||||
|
||||
It’s important that we get compile-time errors when we attempt to change a
|
||||
value that we previously designated as immutable because this very situation
|
||||
@ -126,9 +126,9 @@ not the result of a function call or any other value that could only be
|
||||
computed at runtime.
|
||||
|
||||
Here’s an example of a constant declaration where the constant’s name is
|
||||
`MAX_POINTS` and its value is set to 100,000. (Rust’s constant naming
|
||||
convention is to use all uppercase with underscores between words,
|
||||
and underscores can be inserted in numeric literals to improve readability):
|
||||
`MAX_POINTS` and its value is set to 100,000. (Rust’s naming convention for
|
||||
constants is to use all uppercase with underscores between words, and
|
||||
underscores can be inserted in numeric literals to improve readability):
|
||||
|
||||
```rust
|
||||
const MAX_POINTS: u32 = 100_000;
|
||||
@ -147,13 +147,13 @@ hardcoded value needed to be updated in the future.
|
||||
|
||||
### Shadowing
|
||||
|
||||
As you saw in the “Comparing the Guess to the Secret Number” section in Chapter
|
||||
2, you can declare a new variable with the same name as a previous variable,
|
||||
and the new variable shadows the previous variable. Rustaceans say that the
|
||||
first variable is *shadowed* by the second, which means that the second
|
||||
variable’s value is what appears when the variable is used. We can shadow a
|
||||
variable by using the same variable’s name and repeating the use of the `let`
|
||||
keyword as follows:
|
||||
As you saw in the guessing game tutorial in the “Comparing the Guess to the
|
||||
Secret Number” section in Chapter 2, you can declare a new variable with the
|
||||
same name as a previous variable, and the new variable shadows the previous
|
||||
variable. Rustaceans say that the first variable is *shadowed* by the second,
|
||||
which means that the second variable’s value is what appears when the variable
|
||||
is used. We can shadow a variable by using the same variable’s name and
|
||||
repeating the use of the `let` keyword as follows:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
@ -184,7 +184,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
The main way to consume Boolean values is through conditionals, such as an `if`
|
||||
The main way to use Boolean values is through conditionals, such as an `if`
|
||||
expression. We’ll cover how `if` expressions work in Rust in the “Control Flow”
|
||||
section.
|
||||
|
||||
@ -302,7 +302,7 @@ fn main() {
|
||||
```
|
||||
|
||||
Arrays are useful when you want your data allocated on the stack rather than
|
||||
the heap (we will discuss the stack and the heap more in Chapter 4), or when
|
||||
the heap (we will discuss the stack and the heap more in Chapter 4) or when
|
||||
you want to ensure you always have a fixed number of elements. An array isn’t
|
||||
as flexible as the vector type, though. A vector is a similar collection type
|
||||
provided by the standard library that *is* allowed to grow or shrink in size.
|
||||
|
@ -133,24 +133,22 @@ The value of y is: 6
|
||||
Because we called the function with `5` as the value for `x` and `6` is passed
|
||||
as the value for `y`, the two strings are printed with these values.
|
||||
|
||||
### Function Bodies
|
||||
### Function Bodies Contain Statements and Expressions
|
||||
|
||||
Function bodies are made up of a series of statements optionally ending in an
|
||||
expression. So far, we’ve only covered functions without an ending expression,
|
||||
but you have seen an expression as part of statements. Because Rust is an
|
||||
but you have seen an expression as part of a statement. Because Rust is an
|
||||
expression-based language, this is an important distinction to understand.
|
||||
Other languages don’t have the same distinctions, so let’s look at what
|
||||
statements and expressions are and how their differences affect the bodies of
|
||||
functions.
|
||||
|
||||
### Statements and Expressions
|
||||
|
||||
We’ve actually already used statements and expressions. *Statements* are
|
||||
instructions that perform some action and do not return a value. *Expressions*
|
||||
evaluate to a resulting value. Let’s look at some examples.
|
||||
|
||||
Creating a variable and assigning a value to it with the `let` keyword is a
|
||||
statement. In Listing 3-1, `let y = 6;` is a statement:
|
||||
statement. In Listing 3-1, `let y = 6;` is a statement.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
@ -8,7 +8,7 @@ reading the source code may find useful.
|
||||
Here’s a simple comment:
|
||||
|
||||
```rust
|
||||
// Hello, world.
|
||||
// hello, world
|
||||
```
|
||||
|
||||
In Rust, comments must start with two slashes and continue until the end of the
|
||||
@ -27,7 +27,7 @@ Comments can also be placed at the end of lines containing code:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let lucky_number = 7; // I’m feeling lucky today.
|
||||
let lucky_number = 7; // I’m feeling lucky today
|
||||
}
|
||||
```
|
||||
|
||||
@ -38,7 +38,7 @@ separate line above the code it’s annotating:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
// I’m feeling lucky today.
|
||||
// I’m feeling lucky today
|
||||
let lucky_number = 7;
|
||||
}
|
||||
```
|
||||
|
@ -74,7 +74,8 @@ condition was false
|
||||
```
|
||||
|
||||
It’s also worth noting that the condition in this code *must* be a `bool`. If
|
||||
the condition isn’t a `bool`, we’ll get an error. For example:
|
||||
the condition isn’t a `bool`, we’ll get an error. For example, try running the
|
||||
following code:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -171,7 +172,7 @@ Rust branching construct called `match` for these cases.
|
||||
#### Using `if` in a `let` Statement
|
||||
|
||||
Because `if` is an expression, we can use it on the right side of a `let`
|
||||
statement, as in Listing 3-2:
|
||||
statement, as in Listing 3-2.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -226,9 +227,9 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
When we try to compile this code, we’ll get an error. The `if` and `else` arms have
|
||||
value types that are incompatible, and Rust indicates exactly where to find the
|
||||
problem in the program:
|
||||
When we try to compile this code, we’ll get an error. The `if` and `else` arms
|
||||
have value types that are incompatible, and Rust indicates exactly where to
|
||||
find the problem in the program:
|
||||
|
||||
```text
|
||||
error[E0308]: if and else have incompatible types
|
||||
@ -306,9 +307,8 @@ depending on where the code was in the loop when it received the halt signal.
|
||||
Fortunately, Rust provides another, more reliable way to break out of a loop.
|
||||
You can place the `break` keyword within the loop to tell the program when to
|
||||
stop executing the loop. Recall that we did this in the guessing game in the
|
||||
“Quitting After a Correct Guess” section of Chapter 2 to exit the
|
||||
program when the user won the game by guessing the correct number.
|
||||
|
||||
“Quitting After a Correct Guess” section of Chapter 2 to exit the program when
|
||||
the user won the game by guessing the correct number.
|
||||
|
||||
#### Returning from loops
|
||||
|
||||
@ -372,7 +372,7 @@ true, the code runs; otherwise, it exits the loop.
|
||||
#### Looping Through a Collection with `for`
|
||||
|
||||
You could use the `while` construct to loop over the elements of a collection,
|
||||
such as an array. For example, let’s look at Listing 3-4:
|
||||
such as an array. For example, let’s look at Listing 3-4.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -419,7 +419,7 @@ code to perform the conditional check on every element on every iteration
|
||||
through the loop.
|
||||
|
||||
As a more concise alternative, you can use a `for` loop and execute some code
|
||||
for each item in a collection. A `for` loop looks like this code in Listing 3-5:
|
||||
for each item in a collection. A `for` loop looks like the code in Listing 3-5.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -480,7 +480,7 @@ programs to do the following:
|
||||
* Convert temperatures between Fahrenheit and Celsius.
|
||||
* Generate the nth Fibonacci number.
|
||||
* Print the lyrics to the Christmas carol “The Twelve Days of Christmas,”
|
||||
taking advantage of the repetition in the song.
|
||||
taking advantage of the repetition in the song.
|
||||
|
||||
When you’re ready to move on, we’ll talk about a concept in Rust that *doesn’t*
|
||||
commonly exist in other programming languages: ownership.
|
||||
|
@ -87,9 +87,9 @@ strings.
|
||||
First, let’s take a look at the ownership rules. Keep these rules in mind as we
|
||||
work through the examples that illustrate them:
|
||||
|
||||
> 1. Each value in Rust has a variable that’s called its *owner*.
|
||||
> 2. There can only be one owner at a time.
|
||||
> 3. When the owner goes out of scope, the value will be dropped.
|
||||
* Each value in Rust has a variable that’s called its *owner*.
|
||||
* There can only be one owner at a time.
|
||||
* When the owner goes out of scope, the value will be dropped.
|
||||
|
||||
### Variable Scope
|
||||
|
||||
@ -111,7 +111,7 @@ let s = "hello";
|
||||
The variable `s` refers to a string literal, where the value of the string is
|
||||
hardcoded into the text of our program. The variable is valid from the point at
|
||||
which it’s declared until the end of the current *scope*. Listing 4-1 has
|
||||
comments annotating where the variable `s` is valid:
|
||||
comments annotating where the variable `s` is valid.
|
||||
|
||||
```rust
|
||||
{ // s is not valid here, it’s not yet declared
|
||||
@ -226,7 +226,7 @@ There is a natural point at which we can return the memory our `String` needs
|
||||
to the operating system: when `s` goes out of scope. When a variable goes out
|
||||
of scope, Rust calls a special function for us. This function is called `drop`,
|
||||
and it’s where the author of `String` can put the code to return the memory.
|
||||
Rust calls `drop` automatically at the closing `}`.
|
||||
Rust calls `drop` automatically at the closing curly bracket.
|
||||
|
||||
> Note: In C++, this pattern of deallocating resources at the end of an item’s
|
||||
> lifetime is sometimes called *Resource Acquisition Is Initialization (RAII)*.
|
||||
@ -241,7 +241,7 @@ we’ve allocated on the heap. Let’s explore some of those situations now.
|
||||
#### Ways Variables and Data Interact: Move
|
||||
|
||||
Multiple variables can interact with the same data in different ways in Rust.
|
||||
Let’s look at an example using an integer in Listing 4-2:
|
||||
Let’s look at an example using an integer in Listing 4-2.
|
||||
|
||||
```rust
|
||||
let x = 5;
|
||||
@ -347,7 +347,7 @@ If you’ve heard the terms *shallow copy* and *deep copy* while working with
|
||||
other languages, the concept of copying the pointer, length, and capacity
|
||||
without copying the data probably sounds like making a shallow copy. But
|
||||
because Rust also invalidates the first variable, instead of being called a
|
||||
shallow copy, it’s known as a *move*. Here we would read this by saying that
|
||||
shallow copy, it’s known as a *move*. In this example, we would say that
|
||||
`s1` was *moved* into `s2`. So what actually happens is shown in Figure 4-4.
|
||||
|
||||
<img alt="s1 moved to s2" src="img/trpl04-04.svg" class="center" style="width: 50%;" />
|
||||
@ -388,7 +388,7 @@ different is going on.
|
||||
#### Stack-Only Data: Copy
|
||||
|
||||
There’s another wrinkle we haven’t talked about yet. This code using integers,
|
||||
part of which was shown earlier in Listing 4-2, works and is valid:
|
||||
part of which was shown in Listing 4-2, works and is valid:
|
||||
|
||||
```rust
|
||||
let x = 5;
|
||||
@ -413,7 +413,7 @@ in Chapter 10). If a type has the `Copy` trait, an older variable is still
|
||||
usable after assignment. Rust won’t let us annotate a type with the `Copy`
|
||||
trait if the type, or any of its parts, has implemented the `Drop` trait. If
|
||||
the type needs something special to happen when the value goes out of scope and
|
||||
we add the `Copy` annotation to that type, we’ll get a compile time error. To
|
||||
we add the `Copy` annotation to that type, we’ll get a compile-time error. To
|
||||
learn about how to add the `Copy` annotation to your type, see “Derivable
|
||||
Traits” in Appendix C.
|
||||
|
||||
@ -434,7 +434,7 @@ be sure, but as a general rule, any group of simple scalar values can be
|
||||
The semantics for passing a value to a function are similar to those for
|
||||
assigning a value to a variable. Passing a variable to a function will move or
|
||||
copy, just as assignment does. Listing 4-3 has an example with some annotations
|
||||
showing where variables go into and out of scope:
|
||||
showing where variables go into and out of scope.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -468,14 +468,14 @@ fn makes_copy(some_integer: i32) { // some_integer comes into scope
|
||||
annotated</span>
|
||||
|
||||
If we tried to use `s` after the call to `takes_ownership`, Rust would throw a
|
||||
compile time error. These static checks protect us from mistakes. Try adding
|
||||
compile-time error. These static checks protect us from mistakes. Try adding
|
||||
code to `main` that uses `s` and `x` to see where you can use them and where
|
||||
the ownership rules prevent you from doing so.
|
||||
|
||||
### Return Values and Scope
|
||||
|
||||
Returning values can also transfer ownership. Listing 4-4 is an example with
|
||||
similar annotations to those in Listing 4-3:
|
||||
similar annotations to those in Listing 4-3.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -500,10 +500,10 @@ fn gives_ownership() -> String { // gives_ownership will move its
|
||||
|
||||
some_string // some_string is returned and
|
||||
// moves out to the calling
|
||||
// function.
|
||||
// function
|
||||
}
|
||||
|
||||
// takes_and_gives_back will take a String and return one.
|
||||
// takes_and_gives_back will take a String and return one
|
||||
fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
|
||||
// scope
|
||||
|
||||
@ -525,7 +525,7 @@ It’s quite annoying that anything we pass in also needs to be passed back if w
|
||||
want to use it again, in addition to any data resulting from the body of the
|
||||
function that we might want to return as well.
|
||||
|
||||
It’s possible to return multiple values using a tuple, as shown in Listing 4-5:
|
||||
It’s possible to return multiple values using a tuple, as shown in Listing 4-5.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
|
@ -134,7 +134,7 @@ First, we had to change `s` to be `mut`. Then we had to create a mutable
|
||||
reference with `&mut s` and accept a mutable reference with `some_string: &mut
|
||||
String`.
|
||||
|
||||
But mutable references have one big restriction: you can only have one mutable
|
||||
But mutable references have one big restriction: you can have only one mutable
|
||||
reference to a particular piece of data in a particular scope. This code will
|
||||
fail:
|
||||
|
||||
@ -217,7 +217,7 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta
|
||||
5 | let r2 = &s; // no problem
|
||||
6 | let r3 = &mut s; // BIG PROBLEM
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
7 |
|
||||
7 |
|
||||
8 | println!("{}, {}, and {}", r1, r2, r3);
|
||||
| -- borrow later used here
|
||||
```
|
||||
@ -264,7 +264,7 @@ Here’s the error:
|
||||
|
||||
```text
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> dangle.rs:5:16
|
||||
--> main.rs:5:16
|
||||
|
|
||||
5 | fn dangle() -> &String {
|
||||
| ^ expected lifetime parameter
|
||||
@ -274,10 +274,9 @@ error[E0106]: missing lifetime specifier
|
||||
= help: consider giving it a 'static lifetime
|
||||
```
|
||||
|
||||
This error message refers to a feature we haven’t covered yet: *lifetimes*.
|
||||
We’ll discuss lifetimes in detail in Chapter 10. But, if you disregard the
|
||||
parts about lifetimes, the message does contain the key to why this code is a
|
||||
problem:
|
||||
This error message refers to a feature we haven’t covered yet: lifetimes. We’ll
|
||||
discuss lifetimes in detail in Chapter 10. But, if you disregard the parts
|
||||
about lifetimes, the message does contain the key to why this code is a problem:
|
||||
|
||||
```text
|
||||
this function's return type contains a borrowed value, but there is no value
|
||||
@ -319,8 +318,8 @@ deallocated.
|
||||
|
||||
Let’s recap what we’ve discussed about references:
|
||||
|
||||
* At any given time, you can have *either* (but not both of) one mutable
|
||||
reference or any number of immutable references.
|
||||
* At any given time, you can have *either* one mutable reference *or* any
|
||||
number of immutable references.
|
||||
* References must always be valid.
|
||||
|
||||
Next, we’ll look at a different kind of reference: slices.
|
||||
|
@ -18,7 +18,7 @@ fn first_word(s: &String) -> ?
|
||||
This function, `first_word`, has a `&String` as a parameter. We don’t want
|
||||
ownership, so this is fine. But what should we return? We don’t really have a
|
||||
way to talk about *part* of a string. However, we could return the index of the
|
||||
end of the word. Let’s try that, as shown in Listing 4-7:
|
||||
end of the word. Let’s try that, as shown in Listing 4-7.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -75,6 +75,7 @@ Otherwise, we return the length of the string by using `s.len()`:
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
s.len()
|
||||
```
|
||||
|
||||
@ -83,7 +84,7 @@ string, but there’s a problem. We’re returning a `usize` on its own, but it
|
||||
only a meaningful number in the context of the `&String`. In other words,
|
||||
because it’s a separate value from the `String`, there’s no guarantee that it
|
||||
will still be valid in the future. Consider the program in Listing 4-8 that
|
||||
uses the `first_word` function from Listing 4-7:
|
||||
uses the `first_word` function from Listing 4-7.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -105,7 +106,7 @@ fn main() {
|
||||
|
||||
let word = first_word(&s); // word will get the value 5
|
||||
|
||||
s.clear(); // This empties the String, making it equal to ""
|
||||
s.clear(); // this empties the String, making it equal to ""
|
||||
|
||||
// word still has the value 5 here, but there's no more string that
|
||||
// we could meaningfully use the value 5 with. word is now totally invalid!
|
||||
@ -169,7 +170,7 @@ in the slice and `ending_index` is one more than the last position in the
|
||||
slice. Internally, the slice data structure stores the starting position and
|
||||
the length of the slice, which corresponds to `ending_index` minus
|
||||
`starting_index`. So in the case of `let world = &s[6..11];`, `world` would be
|
||||
a slice that contains a pointer to the 7th byte of `s` and a length value of 5.
|
||||
a slice that contains a pointer to the 7th byte of `s` with a length value of 5.
|
||||
|
||||
Figure 4-6 shows this in a diagram.
|
||||
|
||||
@ -216,8 +217,8 @@ let slice = &s[..];
|
||||
> boundaries. If you attempt to create a string slice in the middle of a
|
||||
> multibyte character, your program will exit with an error. For the purposes
|
||||
> of introducing string slices, we are assuming ASCII only in this section; a
|
||||
> more thorough discussion of UTF-8 handling is in the “Strings” section of
|
||||
> Chapter 8.
|
||||
> more thorough discussion of UTF-8 handling is in the “Storing UTF-8 Encoded
|
||||
> Text with Strings” section of Chapter 8.
|
||||
|
||||
With all this information in mind, let’s rewrite `first_word` to return a
|
||||
slice. The type that signifies “string slice” is written as `&str`:
|
||||
@ -261,7 +262,7 @@ logically incorrect but didn’t show any immediate errors. The problems would
|
||||
show up later if we kept trying to use the first word index with an emptied
|
||||
string. Slices make this bug impossible and let us know we have a problem with
|
||||
our code much sooner. Using the slice version of `first_word` will throw a
|
||||
compile time error:
|
||||
compile-time error:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -271,7 +272,7 @@ fn main() {
|
||||
|
||||
let word = first_word(&s);
|
||||
|
||||
s.clear(); // Error!
|
||||
s.clear(); // error!
|
||||
|
||||
println!("the first word is: {}", word);
|
||||
}
|
||||
@ -285,10 +286,10 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta
|
||||
|
|
||||
8 | let word = first_word(&s);
|
||||
| -- immutable borrow occurs here
|
||||
9 |
|
||||
10 | s.clear(); // Error!
|
||||
9 |
|
||||
10 | s.clear(); // error!
|
||||
| ^^^^^^^^^ mutable borrow occurs here
|
||||
11 |
|
||||
11 |
|
||||
12 | println!("the first word is: {}", word);
|
||||
| ---- borrow later used here
|
||||
```
|
||||
@ -314,20 +315,24 @@ immutable reference.
|
||||
|
||||
#### String Slices as Parameters
|
||||
|
||||
Knowing that you can take slices of literals and `String`s leads us to one more
|
||||
improvement on `first_word`, and that’s its signature:
|
||||
Knowing that you can take slices of literals and `String` values leads us to
|
||||
one more improvement on `first_word`, and that’s its signature:
|
||||
|
||||
```rust,ignore
|
||||
fn first_word(s: &String) -> &str {
|
||||
```
|
||||
|
||||
A more experienced Rustacean would write the following line instead because it
|
||||
allows us to use the same function on both `String`s and `&str`s:
|
||||
A more experienced Rustacean would write the signature shown in Listing 4-9
|
||||
instead because it allows us to use the same function on both `String` values
|
||||
and `&str` values.
|
||||
|
||||
```rust,ignore
|
||||
fn first_word(s: &str) -> &str {
|
||||
```
|
||||
|
||||
<span class="caption">Listing 4-9: Improving the `first_word` function by using
|
||||
a string slice for the type of the `s` parameter</span>
|
||||
|
||||
If we have a string slice, we can pass that directly. If we have a `String`, we
|
||||
can pass a slice of the entire `String`. Defining a function to take a string
|
||||
slice instead of a reference to a `String` makes our API more general and useful
|
||||
|
@ -10,7 +10,7 @@ To define a struct, we enter the keyword `struct` and name the entire struct. A
|
||||
struct’s name should describe the significance of the pieces of data being
|
||||
grouped together. Then, inside curly brackets, we define the names and types of
|
||||
the pieces of data, which we call *fields*. For example, Listing 5-1 shows a
|
||||
struct that stores information about a user account:
|
||||
struct that stores information about a user account.
|
||||
|
||||
```rust
|
||||
struct User {
|
||||
@ -31,7 +31,7 @@ data we want to store in those fields. We don’t have to specify the fields in
|
||||
the same order in which we declared them in the struct. In other words, the
|
||||
struct definition is like a general template for the type, and instances fill
|
||||
in that template with particular data to create values of the type. For
|
||||
example, we can declare a particular user as shown in Listing 5-2:
|
||||
example, we can declare a particular user as shown in Listing 5-2.
|
||||
|
||||
```rust
|
||||
# struct User {
|
||||
@ -56,7 +56,7 @@ To get a specific value from a struct, we can use dot notation. If we wanted
|
||||
just this user’s email address, we could use `user1.email` wherever we wanted
|
||||
to use this value. If the instance is mutable, we can change a value by using
|
||||
the dot notation and assigning into a particular field. Listing 5-3 shows how
|
||||
to change the value in the `email` field of a mutable `User` instance:
|
||||
to change the value in the `email` field of a mutable `User` instance.
|
||||
|
||||
```rust
|
||||
# struct User {
|
||||
@ -80,10 +80,10 @@ user1.email = String::from("anotheremail@example.com");
|
||||
`User` instance</span>
|
||||
|
||||
Note that the entire instance must be mutable; Rust doesn’t allow us to mark
|
||||
only certain fields as mutable.
|
||||
only certain fields as mutable. As with any expression, we can construct a new
|
||||
instance of the struct as the last expression in the function body to
|
||||
implicitly return that new instance.
|
||||
|
||||
As with any expression, we can construct a new instance of the struct as the
|
||||
last expression in the function body to implicitly return that new instance.
|
||||
Listing 5-4 shows a `build_user` function that returns a `User` instance with
|
||||
the given email and username. The `active` field gets the value of `true`, and
|
||||
the `sign_in_count` gets a value of `1`.
|
||||
@ -119,7 +119,7 @@ would get even more annoying. Luckily, there’s a convenient shorthand!
|
||||
Because the parameter names and the struct field names are exactly the same in
|
||||
Listing 5-4, we can use the *field init shorthand* syntax to rewrite
|
||||
`build_user` so that it behaves exactly the same but doesn’t have the
|
||||
repetition of `email` and `username` as shown in Listing 5-5.
|
||||
repetition of `email` and `username`, as shown in Listing 5-5.
|
||||
|
||||
```rust
|
||||
# struct User {
|
||||
@ -156,7 +156,7 @@ instance’s values but changes some. You’ll do this using *struct update synt
|
||||
|
||||
First, Listing 5-6 shows how we create a new `User` instance in `user2` without
|
||||
the update syntax. We set new values for `email` and `username` but otherwise
|
||||
use the same values from `user1` that we created in Listing 5-2:
|
||||
use the same values from `user1` that we created in Listing 5-2.
|
||||
|
||||
```rust
|
||||
# struct User {
|
||||
@ -218,7 +218,7 @@ The code in Listing 5-7 also creates an instance in `user2` that has a
|
||||
different value for `email` and `username` but has the same values for the
|
||||
`active` and `sign_in_count` fields from `user1`.
|
||||
|
||||
### Tuple Structs without Named Fields to Create Different Types
|
||||
### Using Tuple Structs without Named Fields to Create Different Types
|
||||
|
||||
You can also define structs that look similar to tuples, called *tuple
|
||||
structs*. Tuple structs have the added meaning the struct name provides but
|
||||
@ -227,7 +227,7 @@ of the fields. Tuple structs are useful when you want to give the whole tuple a
|
||||
name and make the tuple be a different type than other tuples, and naming each
|
||||
field as in a regular struct would be verbose or redundant.
|
||||
|
||||
To define a tuple struct start with the `struct` keyword and the struct name
|
||||
To define a tuple struct, start with the `struct` keyword and the struct name
|
||||
followed by the types in the tuple. For example, here are definitions and
|
||||
usages of two tuple structs named `Color` and `Point`:
|
||||
|
||||
|
@ -7,7 +7,7 @@ refactor the program until we’re using structs instead.
|
||||
Let’s make a new binary project with Cargo called *rectangles* that will take
|
||||
the width and height of a rectangle specified in pixels and calculate the area
|
||||
of the rectangle. Listing 5-8 shows a short program with one way of doing
|
||||
exactly that in our project’s *src/main.rs*:
|
||||
exactly that in our project’s *src/main.rs*.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -55,7 +55,7 @@ we might do that in “The Tuple Type” section of Chapter 3: by using tuples.
|
||||
|
||||
### Refactoring with Tuples
|
||||
|
||||
Listing 5-9 shows another version of our program that uses tuples:
|
||||
Listing 5-9 shows another version of our program that uses tuples.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -94,7 +94,7 @@ our code.
|
||||
|
||||
We use structs to add meaning by labeling the data. We can transform the tuple
|
||||
we’re using into a data type with a name for the whole as well as names for the
|
||||
parts, as shown in Listing 5-10:
|
||||
parts, as shown in Listing 5-10.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -144,7 +144,7 @@ and `1`. This is a win for clarity.
|
||||
It’d be nice to be able to print an instance of `Rectangle` while we’re
|
||||
debugging our program and see the values for all its fields. Listing 5-11 tries
|
||||
using the `println!` macro as we have used in previous chapters. This won’t
|
||||
work, however:
|
||||
work, however.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -170,7 +170,7 @@ When we run this code, we get an error with this core message:
|
||||
error[E0277]: the trait bound `Rectangle: std::fmt::Display` is not satisfied
|
||||
```
|
||||
|
||||
The `println!` macro can do many kinds of formatting, and by default, curly
|
||||
The `println!` macro can do many kinds of formatting, and by default, the curly
|
||||
brackets tell `println!` to use formatting known as `Display`: output intended
|
||||
for direct end user consumption. The primitive types we’ve seen so far
|
||||
implement `Display` by default, because there’s only one way you’d want to show
|
||||
@ -190,9 +190,9 @@ If we continue reading the errors, we’ll find this helpful note:
|
||||
|
||||
Let’s try it! The `println!` macro call will now look like `println!("rect1 is
|
||||
{:?}", rect1);`. Putting the specifier `:?` inside the curly brackets tells
|
||||
`println!` we want to use an output format called `Debug`. `Debug` is a trait
|
||||
that enables us to print our struct in a way that is useful for developers so
|
||||
we can see its value while we’re debugging our code.
|
||||
`println!` we want to use an output format called `Debug`. The `Debug` trait
|
||||
enables us to print our struct in a way that is useful for developers so we can
|
||||
see its value while we’re debugging our code.
|
||||
|
||||
Run the code with this change. Drat! We still get an error:
|
||||
|
||||
@ -210,7 +210,7 @@ crate, add `#[derive(Debug)]` or manually implement it
|
||||
Rust *does* include functionality to print out debugging information, but we
|
||||
have to explicitly opt in to make that functionality available for our struct.
|
||||
To do that, we add the annotation `#[derive(Debug)]` just before the struct
|
||||
definition, as shown in Listing 5-12:
|
||||
definition, as shown in Listing 5-12.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -253,9 +253,8 @@ rect1 is Rectangle {
|
||||
|
||||
Rust has provided a number of traits for us to use with the `derive` annotation
|
||||
that can add useful behavior to our custom types. Those traits and their
|
||||
behaviors are listed in Appendix C, “Derivable Traits.” We’ll cover how to
|
||||
implement these traits with custom behavior as well as how to create your own
|
||||
traits in Chapter 10.
|
||||
behaviors are listed in Appendix C. We’ll cover how to implement these traits
|
||||
with custom behavior as well as how to create your own traits in Chapter 10.
|
||||
|
||||
Our `area` function is very specific: it only computes the area of rectangles.
|
||||
It would be helpful to tie this behavior more closely to our `Rectangle`
|
||||
|
@ -12,7 +12,7 @@ instance of the struct the method is being called on.
|
||||
|
||||
Let’s change the `area` function that has a `Rectangle` instance as a parameter
|
||||
and instead make an `area` method defined on the `Rectangle` struct, as shown
|
||||
in Listing 5-13:
|
||||
in Listing 5-13.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -125,7 +125,7 @@ struct. This time, we want an instance of `Rectangle` to take another instance
|
||||
of `Rectangle` and return `true` if the second `Rectangle` can fit completely
|
||||
within `self`; otherwise it should return `false`. That is, we want to be able
|
||||
to write the program shown in Listing 5-14, once we’ve defined the `can_hold`
|
||||
method:
|
||||
method.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -164,7 +164,7 @@ calling the `can_hold` method. The return value of `can_hold` will be a
|
||||
Boolean, and the implementation will check whether the width and height of
|
||||
`self` are both greater than the width and height of the other `Rectangle`,
|
||||
respectively. Let’s add the new `can_hold` method to the `impl` block from
|
||||
Listing 5-13, shown in Listing 5-15:
|
||||
Listing 5-13, shown in Listing 5-15.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -234,7 +234,7 @@ namespaces created by modules. We’ll discuss modules in Chapter 7.
|
||||
|
||||
Each struct is allowed to have multiple `impl` blocks. For example, Listing
|
||||
5-15 is equivalent to the code shown in Listing 5-16, which has each method
|
||||
in its own `impl` block:
|
||||
in its own `impl` block.
|
||||
|
||||
```rust
|
||||
# #[derive(Debug)]
|
||||
@ -261,7 +261,7 @@ blocks</span>
|
||||
|
||||
There’s no reason to separate these methods into multiple `impl` blocks here,
|
||||
but this is valid syntax. We’ll see a case in which multiple `impl` blocks are
|
||||
useful in Chapter 10 where we discuss generic types and traits.
|
||||
useful in Chapter 10, where we discuss generic types and traits.
|
||||
|
||||
## Summary
|
||||
|
||||
|
@ -73,7 +73,7 @@ route(IpAddrKind::V6);
|
||||
Using enums has even more advantages. Thinking more about our IP address type,
|
||||
at the moment we don’t have a way to store the actual IP address *data*; we
|
||||
only know what *kind* it is. Given that you just learned about structs in
|
||||
Chapter 5, you might tackle this problem as shown in Listing 6-1:
|
||||
Chapter 5, you might tackle this problem as shown in Listing 6-1.
|
||||
|
||||
```rust
|
||||
enum IpAddrKind {
|
||||
@ -183,7 +183,7 @@ haven’t brought the standard library’s definition into our scope. We’ll ta
|
||||
more about bringing types into scope in Chapter 7.
|
||||
|
||||
Let’s look at another example of an enum in Listing 6-2: this one has a wide
|
||||
variety of types embedded in its variants:
|
||||
variety of types embedded in its variants.
|
||||
|
||||
```rust
|
||||
enum Message {
|
||||
@ -204,7 +204,7 @@ This enum has four variants with different types:
|
||||
* `Write` includes a single `String`.
|
||||
* `ChangeColor` includes three `i32` values.
|
||||
|
||||
Defining an enum with variants like the ones in Listing 6-2 is similar to
|
||||
Defining an enum with variants such as the ones in Listing 6-2 is similar to
|
||||
defining different kinds of struct definitions, except the enum doesn’t use the
|
||||
`struct` keyword and all the variants are grouped together under the `Message`
|
||||
type. The following structs could hold the same data that the preceding enum
|
||||
|
@ -17,7 +17,7 @@ the value falls into the associated code block to be used during execution.
|
||||
Because we just mentioned coins, let’s use them as an example using `match`! We
|
||||
can write a function that can take an unknown United States coin and, in a
|
||||
similar way as the counting machine, determine which coin it is and return its
|
||||
value in cents, as shown here in Listing 6-3:
|
||||
value in cents, as shown here in Listing 6-3.
|
||||
|
||||
```rust
|
||||
enum Coin {
|
||||
@ -100,10 +100,10 @@ From 1999 through 2008, the United States minted quarters with different
|
||||
designs for each of the 50 states on one side. No other coins got state
|
||||
designs, so only quarters have this extra value. We can add this information to
|
||||
our `enum` by changing the `Quarter` variant to include a `UsState` value stored
|
||||
inside it, which we’ve done here in Listing 6-4:
|
||||
inside it, which we’ve done here in Listing 6-4.
|
||||
|
||||
```rust
|
||||
#[derive(Debug)] // So we can inspect the state in a minute
|
||||
#[derive(Debug)] // so we can inspect the state in a minute
|
||||
enum UsState {
|
||||
Alabama,
|
||||
Alaska,
|
||||
@ -179,7 +179,7 @@ the function should return the `None` value and not attempt to perform any
|
||||
operations.
|
||||
|
||||
This function is very easy to write, thanks to `match`, and will look like
|
||||
Listing 6-5:
|
||||
Listing 6-5.
|
||||
|
||||
```rust
|
||||
fn plus_one(x: Option<i32>) -> Option<i32> {
|
||||
@ -292,4 +292,4 @@ can say that we want to do nothing for all the possible values that we don’t
|
||||
list before the `_` placeholder.
|
||||
|
||||
However, the `match` expression can be a bit wordy in a situation in which we
|
||||
only care about *one* of the cases. For this situation, Rust provides `if let`.
|
||||
care about only *one* of the cases. For this situation, Rust provides `if let`.
|
||||
|
@ -3,7 +3,7 @@
|
||||
The `if let` syntax lets you combine `if` and `let` into a less verbose way to
|
||||
handle values that match one pattern while ignoring the rest. Consider the
|
||||
program in Listing 6-6 that matches on an `Option<u8>` value but only wants to
|
||||
execute code if the value is 3:
|
||||
execute code if the value is 3.
|
||||
|
||||
```rust
|
||||
let some_u8_value = Some(0u8);
|
||||
@ -31,15 +31,15 @@ if let Some(3) = some_u8_value {
|
||||
}
|
||||
```
|
||||
|
||||
The syntax `if let` takes a pattern and an expression separated by an `=`. It
|
||||
works the same way as a `match`, where the expression is given to the `match`
|
||||
and the pattern is its first arm.
|
||||
The syntax `if let` takes a pattern and an expression separated by an equal
|
||||
sign. It works the same way as a `match`, where the expression is given to the
|
||||
`match` and the pattern is its first arm.
|
||||
|
||||
Using `if let` means you have less typing, less indentation, and less
|
||||
boilerplate code. However, you lose the exhaustive checking that `match`
|
||||
enforces. Choosing between `match` and `if let` depends on what you’re doing in
|
||||
your particular situation and whether gaining conciseness is an appropriate
|
||||
trade-off for losing exhaustive checking.
|
||||
Using `if let` means less typing, less indentation, and less boilerplate code.
|
||||
However, you lose the exhaustive checking that `match` enforces. Choosing
|
||||
between `match` and `if let` depends on what you’re doing in your particular
|
||||
situation and whether gaining conciseness is an appropriate trade-off for
|
||||
losing exhaustive checking.
|
||||
|
||||
In other words, you can think of `if let` as syntax sugar for a `match` that
|
||||
runs code when the value matches one pattern and then ignores all other values.
|
||||
|
@ -9,7 +9,7 @@ lines of text in a file or the prices of items in a shopping cart.
|
||||
### Creating a New Vector
|
||||
|
||||
To create a new, empty vector, we can call the `Vec::new` function, as shown in
|
||||
Listing 8-1:
|
||||
Listing 8-1.
|
||||
|
||||
```rust
|
||||
let v: Vec<i32> = Vec::new();
|
||||
@ -32,7 +32,7 @@ store once you insert values, so you rarely need to do this type annotation.
|
||||
It’s more common to create a `Vec<T>` that has initial values, and Rust
|
||||
provides the `vec!` macro for convenience. The macro will create a new vector
|
||||
that holds the values you give it. Listing 8-2 creates a new `Vec<i32>` that
|
||||
holds the values `1`, `2`, and `3`:
|
||||
holds the values `1`, `2`, and `3`.
|
||||
|
||||
```rust
|
||||
let v = vec![1, 2, 3];
|
||||
@ -48,7 +48,7 @@ to modify a vector.
|
||||
### Updating a Vector
|
||||
|
||||
To create a vector and then add elements to it, we can use the `push` method,
|
||||
as shown in Listing 8-3:
|
||||
as shown in Listing 8-3.
|
||||
|
||||
```rust
|
||||
let mut v = Vec::new();
|
||||
@ -70,7 +70,7 @@ we don’t need the `Vec<i32>` annotation.
|
||||
### Dropping a Vector Drops Its Elements
|
||||
|
||||
Like any other `struct`, a vector is freed when it goes out of scope, as
|
||||
annotated in Listing 8-4:
|
||||
annotated in Listing 8-4.
|
||||
|
||||
```rust
|
||||
{
|
||||
@ -96,32 +96,22 @@ read their contents is a good next step. There are two ways to reference a
|
||||
value stored in a vector. In the examples, we’ve annotated the types of the
|
||||
values that are returned from these functions for extra clarity.
|
||||
|
||||
Listing 8-5 shows the method of accessing a value in a vector with
|
||||
indexing syntax:
|
||||
Listing 8-5 shows both methods of accessing a value in a vector, either with
|
||||
indexing syntax or the `get` method.
|
||||
|
||||
```rust
|
||||
let v = vec![1, 2, 3, 4, 5];
|
||||
|
||||
let third: &i32 = &v[2];
|
||||
```
|
||||
println!("The third element is {}", third);
|
||||
|
||||
<span class="caption">Listing 8-5: Using indexing syntax to
|
||||
access an item in a vector</span>
|
||||
|
||||
Listing 8-6 shows the method of accessing a value in a vector, with
|
||||
the `get` method:
|
||||
|
||||
```rust
|
||||
let v = vec![1, 2, 3, 4, 5];
|
||||
let v_index = 2;
|
||||
|
||||
match v.get(v_index) {
|
||||
Some(_) => { println!("Reachable element at index: {}", v_index); },
|
||||
None => { println!("Unreachable element at index: {}", v_index); }
|
||||
match v.get(2) {
|
||||
Some(third) => println!("The third element is {}", third),
|
||||
None => println!("There is no third element."),
|
||||
}
|
||||
```
|
||||
|
||||
<span class="caption">Listing 8-6: Using the `get` method to
|
||||
<span class="caption">Listing 8-5: Using indexing syntax or the `get` method to
|
||||
access an item in a vector</span>
|
||||
|
||||
Note two details here. First, we use the index value of `2` to get the third
|
||||
@ -134,7 +124,7 @@ Rust has two ways to reference an element so you can choose how the program
|
||||
behaves when you try to use an index value that the vector doesn’t have an
|
||||
element for. As an example, let’s see what a program will do if it has a vector
|
||||
that holds five elements and then tries to access an element at index 100, as
|
||||
shown in Listing 8-7:
|
||||
shown in Listing 8-6.
|
||||
|
||||
```rust,should_panic,panics
|
||||
let v = vec![1, 2, 3, 4, 5];
|
||||
@ -143,7 +133,7 @@ let does_not_exist = &v[100];
|
||||
let does_not_exist = v.get(100);
|
||||
```
|
||||
|
||||
<span class="caption">Listing 8-7: Attempting to access the element at index
|
||||
<span class="caption">Listing 8-6: Attempting to access the element at index
|
||||
100 in a vector containing five elements</span>
|
||||
|
||||
When we run this code, the first `[]` method will cause the program to panic
|
||||
@ -165,9 +155,9 @@ When the program has a valid reference, the borrow checker enforces the
|
||||
ownership and borrowing rules (covered in Chapter 4) to ensure this reference
|
||||
and any other references to the contents of the vector remain valid. Recall the
|
||||
rule that states you can’t have mutable and immutable references in the same
|
||||
scope. That rule applies in Listing 8-8, where we hold an immutable reference to
|
||||
scope. That rule applies in Listing 8-7, where we hold an immutable reference to
|
||||
the first element in a vector and try to add an element to the end, which won’t
|
||||
work:
|
||||
work.
|
||||
|
||||
```rust,ignore,does_not_compile
|
||||
let mut v = vec![1, 2, 3, 4, 5];
|
||||
@ -179,7 +169,7 @@ v.push(6);
|
||||
println!("The first element is: {}", first);
|
||||
```
|
||||
|
||||
<span class="caption">Listing 8-8: Attempting to add an element to a vector
|
||||
<span class="caption">Listing 8-7: Attempting to add an element to a vector
|
||||
while holding a reference to an item</span>
|
||||
|
||||
Compiling this code will result in this error:
|
||||
@ -198,7 +188,7 @@ error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immuta
|
||||
| ----- borrow later used here
|
||||
```
|
||||
|
||||
The code in Listing 8-8 might look like it should work: why should a reference
|
||||
The code in Listing 8-7 might look like it should work: why should a reference
|
||||
to the first element care about what changes at the end of the vector? This
|
||||
error is due to the way vectors work: adding a new element onto the end of the
|
||||
vector might require allocating new memory and copying the old elements to the
|
||||
@ -214,8 +204,8 @@ programs from ending up in that situation.
|
||||
|
||||
If we want to access each element in a vector in turn, we can iterate through
|
||||
all of the elements rather than use indexes to access one at a time. Listing
|
||||
8-9 shows how to use a `for` loop to get immutable references to each element
|
||||
in a vector of `i32` values and print them:
|
||||
8-8 shows how to use a `for` loop to get immutable references to each element
|
||||
in a vector of `i32` values and print them.
|
||||
|
||||
```rust
|
||||
let v = vec![100, 32, 57];
|
||||
@ -224,12 +214,12 @@ for i in &v {
|
||||
}
|
||||
```
|
||||
|
||||
<span class="caption">Listing 8-9: Printing each element in a vector by
|
||||
<span class="caption">Listing 8-8: Printing each element in a vector by
|
||||
iterating over the elements using a `for` loop</span>
|
||||
|
||||
We can also iterate over mutable references to each element in a mutable vector
|
||||
in order to make changes to all the elements. The `for` loop in Listing 8-10
|
||||
will add `50` to each element:
|
||||
in order to make changes to all the elements. The `for` loop in Listing 8-9
|
||||
will add `50` to each element.
|
||||
|
||||
```rust
|
||||
let mut v = vec![100, 32, 57];
|
||||
@ -238,12 +228,12 @@ for i in &mut v {
|
||||
}
|
||||
```
|
||||
|
||||
<span class="caption">Listing 8-10: Iterating over mutable references to
|
||||
<span class="caption">Listing 8-9: Iterating over mutable references to
|
||||
elements in a vector</span>
|
||||
|
||||
To change the value that the mutable reference refers to, we have to use the
|
||||
dereference operator (`*`) to get to the value in `i` before we can use the
|
||||
`+=` operator . We’ll talk more about `*` in Chapter 15.
|
||||
`+=` operator. We’ll talk more about `*` in Chapter 15.
|
||||
|
||||
### Using an Enum to Store Multiple Types
|
||||
|
||||
@ -258,7 +248,7 @@ some of the columns in the row contain integers, some floating-point numbers,
|
||||
and some strings. We can define an enum whose variants will hold the different
|
||||
value types, and then all the enum variants will be considered the same type:
|
||||
that of the enum. Then we can create a vector that holds that enum and so,
|
||||
ultimately, holds different types. We’ve demonstrated this in Listing 8-11:
|
||||
ultimately, holds different types. We’ve demonstrated this in Listing 8-10.
|
||||
|
||||
```rust
|
||||
enum SpreadsheetCell {
|
||||
@ -274,7 +264,7 @@ let row = vec![
|
||||
];
|
||||
```
|
||||
|
||||
<span class="caption">Listing 8-11: Defining an `enum` to store values of
|
||||
<span class="caption">Listing 8-10: Defining an `enum` to store values of
|
||||
different types in one vector</span>
|
||||
|
||||
Rust needs to know what types will be in the vector at compile time so it knows
|
||||
|
@ -1,7 +1,7 @@
|
||||
## Storing UTF-8 Encoded Text with Strings
|
||||
|
||||
We talked about strings in Chapter 4, but we’ll look at them in more depth now.
|
||||
New Rustaceans commonly get stuck on strings due to a combination of three
|
||||
New Rustaceans commonly get stuck on strings for a combination of three
|
||||
reasons: Rust’s propensity for exposing possible errors, strings being a more
|
||||
complicated data structure than many programmers give them credit for, and
|
||||
UTF-8. These factors combine in a way that can seem difficult when you’re
|
||||
@ -45,7 +45,7 @@ API documentation for more about how to use them and when each is appropriate.
|
||||
|
||||
Many of the same operations available with `Vec<T>` are available with `String`
|
||||
as well, starting with the `new` function to create a string, shown in Listing
|
||||
8-11:
|
||||
8-11.
|
||||
|
||||
```rust
|
||||
let mut s = String::new();
|
||||
@ -57,7 +57,7 @@ This line creates a new empty string called `s`, which we can then load data
|
||||
into. Often, we’ll have some initial data that we want to start the string
|
||||
with. For that, we use the `to_string` method, which is available on any type
|
||||
that implements the `Display` trait, as string literals do. Listing 8-12 shows
|
||||
two examples:
|
||||
two examples.
|
||||
|
||||
```rust
|
||||
let data = "initial contents";
|
||||
@ -75,7 +75,7 @@ This code creates a string containing `initial contents`.
|
||||
|
||||
We can also use the function `String::from` to create a `String` from a string
|
||||
literal. The code in Listing 8-13 is equivalent to the code from Listing 8-12
|
||||
that uses `to_string`:
|
||||
that uses `to_string`.
|
||||
|
||||
```rust
|
||||
let s = String::from("initial contents");
|
||||
@ -90,7 +90,7 @@ redundant, but they all have their place! In this case, `String::from` and
|
||||
`to_string` do the same thing, so which you choose is a matter of style.
|
||||
|
||||
Remember that strings are UTF-8 encoded, so we can include any properly encoded
|
||||
data in them, as shown in Listing 8-14:
|
||||
data in them, as shown in Listing 8-14.
|
||||
|
||||
```rust
|
||||
let hello = String::from("السلام عليكم");
|
||||
@ -120,7 +120,7 @@ use the `+` operator or the `format!` macro to concatenate `String` values.
|
||||
#### Appending to a String with `push_str` and `push`
|
||||
|
||||
We can grow a `String` by using the `push_str` method to append a string slice,
|
||||
as shown in Listing 8-15:
|
||||
as shown in Listing 8-15.
|
||||
|
||||
```rust
|
||||
let mut s = String::from("foo");
|
||||
@ -133,7 +133,7 @@ using the `push_str` method</span>
|
||||
After these two lines, `s` will contain `foobar`. The `push_str` method takes a
|
||||
string slice because we don’t necessarily want to take ownership of the
|
||||
parameter. For example, the code in Listing 8-16 shows that it would be
|
||||
unfortunate if we weren’t able to use `s2` after appending its contents to `s1`:
|
||||
unfortunate if we weren’t able to use `s2` after appending its contents to `s1`.
|
||||
|
||||
```rust
|
||||
let mut s1 = String::from("foo");
|
||||
@ -149,8 +149,8 @@ If the `push_str` method took ownership of `s2`, we wouldn’t be able to print
|
||||
its value on the last line. However, this code works as we’d expect!
|
||||
|
||||
The `push` method takes a single character as a parameter and adds it to the
|
||||
`String`. Listing 8-17 shows code that adds the letter l to a `String` using
|
||||
the `push` method:
|
||||
`String`. Listing 8-17 shows code that adds the letter *l* to a `String` using
|
||||
the `push` method.
|
||||
|
||||
```rust
|
||||
let mut s = String::from("lo");
|
||||
@ -165,12 +165,12 @@ As a result of this code, `s` will contain `lol`.
|
||||
#### Concatenation with the `+` Operator or the `format!` Macro
|
||||
|
||||
Often, you’ll want to combine two existing strings. One way is to use the `+`
|
||||
operator, as shown in Listing 8-18:
|
||||
operator, as shown in Listing 8-18.
|
||||
|
||||
```rust
|
||||
let s1 = String::from("Hello, ");
|
||||
let s2 = String::from("world!");
|
||||
let s3 = s1 + &s2; // Note s1 has been moved here and can no longer be used
|
||||
let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used
|
||||
```
|
||||
|
||||
<span class="caption">Listing 8-18: Using the `+` operator to combine two
|
||||
@ -248,7 +248,7 @@ easier to read and doesn’t take ownership of any of its parameters.
|
||||
In many other programming languages, accessing individual characters in a
|
||||
string by referencing them by index is a valid and common operation. However,
|
||||
if you try to access parts of a `String` using indexing syntax in Rust, you’ll
|
||||
get an error. Consider the invalid code in Listing 8-19:
|
||||
get an error. Consider the invalid code in Listing 8-19.
|
||||
|
||||
```rust,ignore,does_not_compile
|
||||
let s1 = String::from("hello");
|
||||
@ -285,7 +285,7 @@ let len = String::from("Hola").len();
|
||||
|
||||
In this case, `len` will be 4, which means the vector storing the string “Hola”
|
||||
is 4 bytes long. Each of these letters takes 1 byte when encoded in UTF-8. But
|
||||
what about the following line? (Note that this line begins with the capital
|
||||
what about the following line? (Note that this string begins with the capital
|
||||
Cyrillic letter Ze, not the Arabic number 3.)
|
||||
|
||||
```rust
|
||||
@ -393,7 +393,7 @@ Fortunately, you can access elements in a string in other ways.
|
||||
If you need to perform operations on individual Unicode scalar values, the best
|
||||
way to do so is to use the `chars` method. Calling `chars` on “नमस्ते” separates
|
||||
out and returns six values of type `char`, and you can iterate over the result
|
||||
in order to access each element:
|
||||
to access each element:
|
||||
|
||||
```rust
|
||||
for c in "नमस्ते".chars() {
|
||||
|
@ -22,7 +22,7 @@ As always, check the standard library documentation for more information.
|
||||
You can create an empty hash map with `new` and add elements with `insert`. In
|
||||
Listing 8-20, we’re keeping track of the scores of two teams whose names are
|
||||
Blue and Yellow. The Blue team starts with 10 points, and the Yellow team
|
||||
starts with 50:
|
||||
starts with 50.
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
@ -53,7 +53,7 @@ vector of tuples, where each tuple consists of a key and its value. The
|
||||
`HashMap`. For example, if we had the team names and initial scores in two
|
||||
separate vectors, we could use the `zip` method to create a vector of tuples
|
||||
where “Blue” is paired with 10, and so forth. Then we could use the `collect`
|
||||
method to turn that vector of tuples into a hash map, as shown in Listing 8-21:
|
||||
method to turn that vector of tuples into a hash map, as shown in Listing 8-21.
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
@ -77,7 +77,7 @@ contains based on the types of the data in the vectors.
|
||||
|
||||
For types that implement the `Copy` trait, like `i32`, the values are copied
|
||||
into the hash map. For owned values like `String`, the values will be moved and
|
||||
the hash map will be the owner of those values, as demonstrated in Listing 8-22:
|
||||
the hash map will be the owner of those values, as demonstrated in Listing 8-22.
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
@ -105,7 +105,7 @@ the “Validating References with Lifetimes” section in Chapter 10.
|
||||
### Accessing Values in a Hash Map
|
||||
|
||||
We can get a value out of the hash map by providing its key to the `get`
|
||||
method, as shown in Listing 8-23:
|
||||
method, as shown in Listing 8-23.
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
@ -168,7 +168,7 @@ If we insert a key and a value into a hash map and then insert that same key
|
||||
with a different value, the value associated with that key will be replaced.
|
||||
Even though the code in Listing 8-24 calls `insert` twice, the hash map will
|
||||
only contain one key/value pair because we’re inserting the value for the Blue
|
||||
team’s key both times:
|
||||
team’s key both times.
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
@ -192,11 +192,11 @@ overwritten.
|
||||
It’s common to check whether a particular key has a value and, if it doesn’t,
|
||||
insert a value for it. Hash maps have a special API for this called `entry`
|
||||
that takes the key you want to check as a parameter. The return value of the
|
||||
`entry` function is an enum called `Entry` that represents a value that might
|
||||
or might not exist. Let’s say we want to check whether the key for the Yellow
|
||||
team has a value associated with it. If it doesn’t, we want to insert the value
|
||||
50, and the same for the Blue team. Using the `entry` API, the code looks like
|
||||
Listing 8-25:
|
||||
`entry` method is an enum called `Entry` that represents a value that might or
|
||||
might not exist. Let’s say we want to check whether the key for the Yellow team
|
||||
has a value associated with it. If it doesn’t, we want to insert the value 50,
|
||||
and the same for the Blue team. Using the `entry` API, the code looks like
|
||||
Listing 8-25.
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
@ -221,9 +221,9 @@ logic ourselves and, in addition, plays more nicely with the borrow checker.
|
||||
|
||||
Running the code in Listing 8-25 will print `{"Yellow": 50, "Blue": 10}`. The
|
||||
first call to `entry` will insert the key for the Yellow team with the value
|
||||
`50` because the Yellow team doesn’t have a value already. The second call to
|
||||
50 because the Yellow team doesn’t have a value already. The second call to
|
||||
`entry` will not change the hash map because the Blue team already has the
|
||||
value `10`.
|
||||
value 10.
|
||||
|
||||
#### Updating a Value Based on the Old Value
|
||||
|
||||
@ -232,7 +232,7 @@ update it based on the old value. For instance, Listing 8-26 shows code that
|
||||
counts how many times each word appears in some text. We use a hash map with
|
||||
the words as keys and increment the value to keep track of how many times we’ve
|
||||
seen that word. If it’s the first time we’ve seen a word, we’ll first insert
|
||||
the value `0`:
|
||||
the value 0.
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
@ -261,17 +261,17 @@ loop, so all of these changes are safe and allowed by the borrowing rules.
|
||||
|
||||
### Hashing Functions
|
||||
|
||||
By default, `HashMap` uses a “cryptographically strong”[^siphash] hashing function that can
|
||||
provide resistance to Denial of Service (DoS) attacks. This is not the fastest
|
||||
hashing algorithm available, but the trade-off for better security that comes
|
||||
with the drop in performance is worth it. If you profile your code and find
|
||||
that the default hash function is too slow for your purposes, you can switch to
|
||||
another function by specifying a different *hasher*. A hasher is a type that
|
||||
implements the `BuildHasher` trait. We’ll talk about traits and how to
|
||||
implement them in Chapter 10. You don’t necessarily have to implement your own
|
||||
hasher from scratch; [crates.io](https://crates.io) has libraries shared by
|
||||
other Rust users that provide hashers implementing many common hashing
|
||||
algorithms.
|
||||
By default, `HashMap` uses a “cryptographically strong”[^siphash] hashing
|
||||
function that can provide resistance to Denial of Service (DoS) attacks. This
|
||||
is not the fastest hashing algorithm available, but the trade-off for better
|
||||
security that comes with the drop in performance is worth it. If you profile
|
||||
your code and find that the default hash function is too slow for your
|
||||
purposes, you can switch to another function by specifying a different
|
||||
*hasher*. A hasher is a type that implements the `BuildHasher` trait. We’ll
|
||||
talk about traits and how to implement them in Chapter 10. You don’t
|
||||
necessarily have to implement your own hasher from scratch;
|
||||
[crates.io](https://crates.io) has libraries shared by other Rust users that
|
||||
provide hashers implementing many common hashing algorithms.
|
||||
|
||||
[^siphash]: [https://www.131002.net/siphash/siphash.pdf](https://www.131002.net/siphash/siphash.pdf)
|
||||
|
||||
|
@ -45,10 +45,10 @@ thread 'main' panicked at 'crash and burn', src/main.rs:2:4
|
||||
note: Run with `RUST_BACKTRACE=1` for a backtrace.
|
||||
```
|
||||
|
||||
The call to `panic!` causes the error message contained in the last two
|
||||
lines. The first line shows our panic message and the place in our source code
|
||||
where the panic occurred: *src/main.rs:2:4* indicates that it’s the second
|
||||
line, fourth character of our *src/main.rs* file.
|
||||
The call to `panic!` causes the error message contained in the last two lines.
|
||||
The first line shows our panic message and the place in our source code where
|
||||
the panic occurred: *src/main.rs:2:4* indicates that it’s the second line,
|
||||
fourth character of our *src/main.rs* file.
|
||||
|
||||
In this case, the line indicated is part of our code, and if we go to that
|
||||
line, we see the `panic!` macro call. In other cases, the `panic!` call might
|
||||
@ -64,7 +64,7 @@ backtrace is in more detail next.
|
||||
Let’s look at another example to see what it’s like when a `panic!` call comes
|
||||
from a library because of a bug in our code instead of from our code calling
|
||||
the macro directly. Listing 9-1 has some code that attempts to access an
|
||||
element by index in a vector:
|
||||
element by index in a vector.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -77,13 +77,13 @@ fn main() {
|
||||
```
|
||||
|
||||
<span class="caption">Listing 9-1: Attempting to access an element beyond the
|
||||
end of a vector, which will cause a `panic!`</span>
|
||||
end of a vector, which will cause a call to `panic!`</span>
|
||||
|
||||
Here, we’re attempting to access the hundredth element of our vector (which is
|
||||
at index 99 because indexing starts at zero), but it has only three elements.
|
||||
In this situation, Rust will panic. Using `[]` is supposed to return an
|
||||
element, but if you pass an invalid index, there’s no element that Rust could
|
||||
return here that would be correct.
|
||||
Here, we’re attempting to access the 100th element of our vector (which is at
|
||||
index 99 because indexing starts at zero), but it has only 3 elements. In this
|
||||
situation, Rust will panic. Using `[]` is supposed to return an element, but if
|
||||
you pass an invalid index, there’s no element that Rust could return here that
|
||||
would be correct.
|
||||
|
||||
Other languages, like C, will attempt to give you exactly what you asked for in
|
||||
this situation, even though it isn’t what you want: you’ll get whatever is at
|
||||
@ -122,7 +122,7 @@ mentioning your files are code that your code called; the lines below are code
|
||||
that called your code. These lines might include core Rust code, standard
|
||||
library code, or crates that you’re using. Let’s try getting a backtrace by
|
||||
setting the `RUST_BACKTRACE` environment variable to any value except 0.
|
||||
Listing 9-2 shows output similar to what you’ll see:
|
||||
Listing 9-2 shows output similar to what you’ll see.
|
||||
|
||||
```text
|
||||
$ RUST_BACKTRACE=1 cargo run
|
||||
|
@ -29,7 +29,7 @@ library has defined on it in many different situations where the successful
|
||||
value and error value we want to return may differ.
|
||||
|
||||
Let’s call a function that returns a `Result` value because the function could
|
||||
fail. In Listing 9-3 we try to open a file:
|
||||
fail. In Listing 9-3 we try to open a file.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -43,14 +43,13 @@ fn main() {
|
||||
|
||||
<span class="caption">Listing 9-3: Opening a file</span>
|
||||
|
||||
How do we know `File::open` returns a `Result`? We could look at the
|
||||
[standard library API documentation](../std/index.html),
|
||||
or we could ask the compiler! If we give `f` a type
|
||||
annotation that we know is *not* the return type of the function and then try
|
||||
to compile the code, the compiler will tell us that the types don’t match. The
|
||||
error message will then tell us what the type of `f` *is*. Let’s try it! We
|
||||
know that the return type of `File::open` isn’t of type `u32`, so let’s change
|
||||
the `let f` statement to this:
|
||||
How do we know `File::open` returns a `Result`? We could look at the [standard
|
||||
library API documentation](../std/index.html)<!-- ignore -->, or we could ask
|
||||
the compiler! If we give `f` a type annotation that we know is *not* the return
|
||||
type of the function and then try to compile the code, the compiler will tell
|
||||
us that the types don’t match. The error message will then tell us what the
|
||||
type of `f` *is*. Let’s try it! We know that the return type of `File::open`
|
||||
isn’t of type `u32`, so let’s change the `let f` statement to this:
|
||||
|
||||
```rust,ignore
|
||||
let f: u32 = File::open("hello.txt");
|
||||
@ -142,7 +141,7 @@ if `File::open` failed because the file doesn’t exist, we want to create the
|
||||
file and return the handle to the new file. If `File::open` failed for any
|
||||
other reason—for example, because we didn’t have permission to open the file—we
|
||||
still want the code to `panic!` in the same way as it did in Listing 9-4. Look
|
||||
at Listing 9-5, which adds another arm to the `match`:
|
||||
at Listing 9-5, which adds another arm to the `match`.
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -178,21 +177,21 @@ has a method `kind` that we can call to get an `io::ErrorKind` value. The enum
|
||||
`io::ErrorKind` is provided by the standard library and has variants
|
||||
representing the different kinds of errors that might result from an `io`
|
||||
operation. The variant we want to use is `ErrorKind::NotFound`, which indicates
|
||||
the file we’re trying to open doesn’t exist yet. So, we `match` on `f`, but we
|
||||
also then have an inner `match` on `error.kind()`.
|
||||
the file we’re trying to open doesn’t exist yet. So we `match` on `f`, but we
|
||||
also have an inner `match` on `error.kind()`.
|
||||
|
||||
The condition we want to check in the match guard is whether the value returned
|
||||
by `error.kind()` is the `NotFound` variant of the `ErrorKind` enum. If it is,
|
||||
we try to create the file with `File::create`. However, because `File::create`
|
||||
could also fail, we need to add another inner `match` statement as well. When
|
||||
could also fail, we need to add another inner `match` expression as well. When
|
||||
the file can’t be opened, a different error message will be printed. The last
|
||||
arm of the outer `match` stays the same so the program panics on any error
|
||||
besides the missing file error.
|
||||
|
||||
That’s a lot of `match`! `match` is very powerful, but also very much a primitive.
|
||||
In Chapter 13, we’ll learn about closures. The `Result<T, E>` type has many
|
||||
methods that accept a closure, and are implemented as `match` statements. A more
|
||||
seasoned Rustacean might write this:
|
||||
That’s a lot of `match`! `match` is very powerful, but also very much a
|
||||
primitive. In Chapter 13, we’ll learn about closures. The `Result<T, E>` type
|
||||
has many methods that accept a closure, and are implemented as `match`
|
||||
expressions. A more seasoned Rustacean might write this:
|
||||
|
||||
```rust,ignore
|
||||
use std::fs::File;
|
||||
@ -213,16 +212,15 @@ fn main() {
|
||||
|
||||
Come back to this example after you’ve read Chapter 13, and look up what the
|
||||
`map_err` and `unwrap_or_else` methods do in the standard library
|
||||
documentation. There’s many more of these methods that can clean up huge
|
||||
nested `match`es when dealing with errors. We’ll be looking at some other
|
||||
strategies shortly!
|
||||
documentation. There’s many more of these methods that can clean up huge nested
|
||||
`match` expressions when dealing with errors.
|
||||
|
||||
### Shortcuts for Panic on Error: `unwrap` and `expect`
|
||||
|
||||
Using `match` works well enough, but it can be a bit verbose and doesn’t always
|
||||
communicate intent well. The `Result<T, E>` type has many helper methods
|
||||
defined on it to do various tasks. One of those methods, called `unwrap`, is a
|
||||
shortcut method that is implemented just like the `match` statement we wrote in
|
||||
shortcut method that is implemented just like the `match` expression we wrote in
|
||||
Listing 9-4. If the `Result` value is the `Ok` variant, `unwrap` will return
|
||||
the value inside the `Ok`. If the `Result` is the `Err` variant, `unwrap` will
|
||||
call the `panic!` macro for us. Here is an example of `unwrap` in action:
|
||||
|
@ -429,6 +429,7 @@ when you created the crate, your description, and a license added, the
|
||||
name = "guessing_game"
|
||||
version = "0.1.0"
|
||||
authors = ["Your Name <you@example.com>"]
|
||||
edition = "2018"
|
||||
description = "A fun game where you guess what number the computer has chosen."
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
|
@ -161,12 +161,12 @@ impl<'a, T> LimitTracker<'a, T>
|
||||
|
||||
let percentage_of_max = self.value as f64 / self.max as f64;
|
||||
|
||||
if percentage_of_max >= 0.75 && percentage_of_max < 0.9 {
|
||||
self.messenger.send("Warning: You've used up over 75% of your quota!");
|
||||
} else if percentage_of_max >= 0.9 && percentage_of_max < 1.0 {
|
||||
self.messenger.send("Urgent warning: You've used up over 90% of your quota!");
|
||||
} else if percentage_of_max >= 1.0 {
|
||||
if percentage_of_max >= 1.0 {
|
||||
self.messenger.send("Error: You are over your quota!");
|
||||
} else if percentage_of_max >= 0.9 {
|
||||
self.messenger.send("Urgent warning: You've used up over 90% of your quota!");
|
||||
} else if percentage_of_max >= 0.75 {
|
||||
self.messenger.send("Warning: You've used up over 75% of your quota!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ fn main() {
|
||||
separate variables</span>
|
||||
|
||||
This code creates the variables `a` and `b` that match the values of the `x`
|
||||
and `y` fields of the `p` variable. This example shows that the names of the
|
||||
and `y` fields of the `p` struct. This example shows that the names of the
|
||||
variables in the pattern don’t have to match the field names of the struct. But
|
||||
it’s common to want the variable names to match the field names to make it
|
||||
easier to remember which variables came from which fields.
|
||||
|
@ -327,12 +327,10 @@ won’t compile until we add a definition for the `impl_hello_macro` function.
|
||||
<span class="filename">Filename: hello_macro_derive/src/lib.rs</span>
|
||||
|
||||
<!--
|
||||
This usage of `extern crate` is required for the moment with the 1.31 code
|
||||
that's currently rustc 1.31.0-beta.4 (04da282bb 2018-11-01), see:
|
||||
|
||||
- https://github.com/rust-lang/rust/issues/54418
|
||||
- https://github.com/rust-lang/rust/pull/54658
|
||||
- https://github.com/rust-lang/rust/issues/55599
|
||||
This usage of `extern crate` is required for the moment with 1.31.0, see:
|
||||
https://github.com/rust-lang/rust/issues/54418
|
||||
https://github.com/rust-lang/rust/pull/54658
|
||||
https://github.com/rust-lang/rust/issues/55599
|
||||
-->
|
||||
|
||||
```rust,ignore
|
||||
|
@ -248,7 +248,7 @@ impl CtorKind {
|
||||
}
|
||||
|
||||
impl NonMacroAttrKind {
|
||||
fn descr(self) -> &'static str {
|
||||
pub fn descr(self) -> &'static str {
|
||||
match self {
|
||||
NonMacroAttrKind::Builtin => "built-in attribute",
|
||||
NonMacroAttrKind::Tool => "tool attribute",
|
||||
|
@ -334,7 +334,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let result = select.select(&Obligation::new(dummy_cause.clone(), new_env, pred));
|
||||
// Call infcx.resolve_type_vars_if_possible to see if we can
|
||||
// get rid of any inference variables.
|
||||
let obligation = infcx.resolve_type_vars_if_possible(
|
||||
&Obligation::new(dummy_cause.clone(), new_env, pred)
|
||||
);
|
||||
let result = select.select(&obligation);
|
||||
|
||||
match &result {
|
||||
&Ok(Some(ref vtable)) => {
|
||||
@ -369,7 +374,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
}
|
||||
&Ok(None) => {}
|
||||
&Err(SelectionError::Unimplemented) => {
|
||||
if self.is_of_param(pred.skip_binder().trait_ref.substs) {
|
||||
if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
|
||||
already_visited.remove(&pred);
|
||||
self.add_user_pred(
|
||||
&mut user_computed_preds,
|
||||
@ -631,18 +636,28 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
finished_map
|
||||
}
|
||||
|
||||
pub fn is_of_param(&self, substs: &Substs<'_>) -> bool {
|
||||
if substs.is_noop() {
|
||||
return false;
|
||||
}
|
||||
fn is_param_no_infer(&self, substs: &Substs<'_>) -> bool {
|
||||
return self.is_of_param(substs.type_at(0)) &&
|
||||
!substs.types().any(|t| t.has_infer_types());
|
||||
}
|
||||
|
||||
return match substs.type_at(0).sty {
|
||||
pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
|
||||
return match ty.sty {
|
||||
ty::Param(_) => true,
|
||||
ty::Projection(p) => self.is_of_param(p.substs),
|
||||
ty::Projection(p) => self.is_of_param(p.self_ty()),
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
|
||||
match p.ty().skip_binder().sty {
|
||||
ty::Projection(proj) if proj == p.skip_binder().projection_ty => {
|
||||
true
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn evaluate_nested_obligations<
|
||||
'b,
|
||||
'c,
|
||||
@ -661,28 +676,77 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
) -> bool {
|
||||
let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID);
|
||||
|
||||
for (obligation, predicate) in nested
|
||||
.filter(|o| o.recursion_depth == 1)
|
||||
for (obligation, mut predicate) in nested
|
||||
.map(|o| (o.clone(), o.predicate.clone()))
|
||||
{
|
||||
let is_new_pred =
|
||||
fresh_preds.insert(self.clean_pred(select.infcx(), predicate.clone()));
|
||||
|
||||
// Resolve any inference variables that we can, to help selection succeed
|
||||
predicate = select.infcx().resolve_type_vars_if_possible(&predicate);
|
||||
|
||||
// We only add a predicate as a user-displayable bound if
|
||||
// it involves a generic parameter, and doesn't contain
|
||||
// any inference variables.
|
||||
//
|
||||
// Displaying a bound involving a concrete type (instead of a generic
|
||||
// parameter) would be pointless, since it's always true
|
||||
// (e.g. u8: Copy)
|
||||
// Displaying an inference variable is impossible, since they're
|
||||
// an internal compiler detail without a defined visual representation
|
||||
//
|
||||
// We check this by calling is_of_param on the relevant types
|
||||
// from the various possible predicates
|
||||
match &predicate {
|
||||
&ty::Predicate::Trait(ref p) => {
|
||||
let substs = &p.skip_binder().trait_ref.substs;
|
||||
if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
|
||||
&& !only_projections
|
||||
&& is_new_pred {
|
||||
|
||||
if self.is_of_param(substs) && !only_projections && is_new_pred {
|
||||
self.add_user_pred(computed_preds, predicate);
|
||||
}
|
||||
predicates.push_back(p.clone());
|
||||
}
|
||||
&ty::Predicate::Projection(p) => {
|
||||
// If the projection isn't all type vars, then
|
||||
// we don't want to add it as a bound
|
||||
if self.is_of_param(p.skip_binder().projection_ty.substs) && is_new_pred {
|
||||
self.add_user_pred(computed_preds, predicate);
|
||||
} else {
|
||||
debug!("evaluate_nested_obligations: examining projection predicate {:?}",
|
||||
predicate);
|
||||
|
||||
// As described above, we only want to display
|
||||
// bounds which include a generic parameter but don't include
|
||||
// an inference variable.
|
||||
// Additionally, we check if we've seen this predicate before,
|
||||
// to avoid rendering duplicate bounds to the user.
|
||||
if self.is_param_no_infer(p.skip_binder().projection_ty.substs)
|
||||
&& !p.ty().skip_binder().is_ty_infer()
|
||||
&& is_new_pred {
|
||||
debug!("evaluate_nested_obligations: adding projection predicate\
|
||||
to computed_preds: {:?}", predicate);
|
||||
|
||||
// Under unusual circumstances, we can end up with a self-refeential
|
||||
// projection predicate. For example:
|
||||
// <T as MyType>::Value == <T as MyType>::Value
|
||||
// Not only is displaying this to the user pointless,
|
||||
// having it in the ParamEnv will cause an issue if we try to call
|
||||
// poly_project_and_unify_type on the predicate, since this kind of
|
||||
// predicate will normally never end up in a ParamEnv.
|
||||
//
|
||||
// For these reasons, we ignore these weird predicates,
|
||||
// ensuring that we're able to properly synthesize an auto trait impl
|
||||
if self.is_self_referential_projection(p) {
|
||||
debug!("evaluate_nested_obligations: encountered a projection
|
||||
predicate equating a type with itself! Skipping");
|
||||
|
||||
} else {
|
||||
self.add_user_pred(computed_preds, predicate);
|
||||
}
|
||||
}
|
||||
|
||||
// We can only call poly_project_and_unify_type when our predicate's
|
||||
// Ty contains an inference variable - otherwise, there won't be anything to
|
||||
// unify
|
||||
if p.ty().skip_binder().has_infer_types() {
|
||||
debug!("Projecting and unifying projection predicate {:?}",
|
||||
predicate);
|
||||
match poly_project_and_unify_type(select, &obligation.with(p.clone())) {
|
||||
Err(e) => {
|
||||
debug!(
|
||||
|
@ -190,7 +190,26 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
// In the case of a trait predicate, we can skip the "self" type.
|
||||
data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty())
|
||||
}
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Projection(ref data) => {
|
||||
// And similarly for projections. This should be redundant with
|
||||
// the previous check because any projection should have a
|
||||
// matching `Trait` predicate with the same inputs, but we do
|
||||
// the check to be safe.
|
||||
//
|
||||
// Note that we *do* allow projection *outputs* to contain
|
||||
// `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
|
||||
// we just require the user to specify *both* outputs
|
||||
// in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
|
||||
//
|
||||
// This is ALT2 in issue #56288, see that for discussion of the
|
||||
// possible alternatives.
|
||||
data.skip_binder()
|
||||
.projection_ty
|
||||
.trait_ref(self)
|
||||
.input_types()
|
||||
.skip(1)
|
||||
.any(|t| t.has_self_ty())
|
||||
}
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::TypeOutlives(..) |
|
||||
@ -243,6 +262,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
method: &ty::AssociatedItem)
|
||||
-> Option<MethodViolationCode>
|
||||
{
|
||||
debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
|
||||
// Any method that has a `Self : Sized` requisite is otherwise
|
||||
// exempt from the regulations.
|
||||
if self.generics_require_sized_self(method.def_id) {
|
||||
@ -261,6 +281,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
method: &ty::AssociatedItem)
|
||||
-> bool
|
||||
{
|
||||
debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
|
||||
// Any method that has a `Self : Sized` requisite can't be called.
|
||||
if self.generics_require_sized_self(method.def_id) {
|
||||
return false;
|
||||
@ -380,6 +401,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
fn receiver_for_self_ty(
|
||||
self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
|
||||
) -> Ty<'tcx> {
|
||||
debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
|
||||
let substs = Substs::for_item(self, method_def_id, |param, _| {
|
||||
if param.index == 0 {
|
||||
self_ty.into()
|
||||
@ -388,7 +410,10 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
}
|
||||
});
|
||||
|
||||
receiver_ty.subst(self, substs)
|
||||
let result = receiver_ty.subst(self, substs);
|
||||
debug!("receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
|
||||
receiver_ty, self_ty, method_def_id, result);
|
||||
result
|
||||
}
|
||||
|
||||
/// creates the object type for the current trait. For example,
|
||||
@ -404,18 +429,26 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
);
|
||||
|
||||
let mut associated_types = traits::supertraits(self, ty::Binder::dummy(trait_ref))
|
||||
.flat_map(|trait_ref| self.associated_items(trait_ref.def_id()))
|
||||
.filter(|item| item.kind == ty::AssociatedKind::Type)
|
||||
.flat_map(|super_trait_ref| {
|
||||
self.associated_items(super_trait_ref.def_id())
|
||||
.map(move |item| (super_trait_ref, item))
|
||||
})
|
||||
.filter(|(_, item)| item.kind == ty::AssociatedKind::Type)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// existential predicates need to be in a specific order
|
||||
associated_types.sort_by_cached_key(|item| self.def_path_hash(item.def_id));
|
||||
associated_types.sort_by_cached_key(|(_, item)| self.def_path_hash(item.def_id));
|
||||
|
||||
let projection_predicates = associated_types.into_iter().map(|item| {
|
||||
let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
|
||||
// We *can* get bound lifetimes here in cases like
|
||||
// `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
|
||||
//
|
||||
// binder moved to (*)...
|
||||
let super_trait_ref = super_trait_ref.skip_binder();
|
||||
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
|
||||
ty: self.mk_projection(item.def_id, trait_ref.substs),
|
||||
ty: self.mk_projection(item.def_id, super_trait_ref.substs),
|
||||
item_def_id: item.def_id,
|
||||
substs: trait_ref.substs,
|
||||
substs: super_trait_ref.substs,
|
||||
})
|
||||
});
|
||||
|
||||
@ -424,7 +457,8 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
);
|
||||
|
||||
let object_ty = self.mk_dynamic(
|
||||
ty::Binder::dummy(existential_predicates),
|
||||
// (*) ... binder re-introduced here
|
||||
ty::Binder::bind(existential_predicates),
|
||||
lifetime,
|
||||
);
|
||||
|
||||
|
@ -1754,17 +1754,19 @@ bitflags! {
|
||||
pub struct AdtFlags: u32 {
|
||||
const NO_ADT_FLAGS = 0;
|
||||
const IS_ENUM = 1 << 0;
|
||||
const IS_PHANTOM_DATA = 1 << 1;
|
||||
const IS_FUNDAMENTAL = 1 << 2;
|
||||
const IS_UNION = 1 << 3;
|
||||
const IS_BOX = 1 << 4;
|
||||
const IS_UNION = 1 << 1;
|
||||
const IS_STRUCT = 1 << 2;
|
||||
const HAS_CTOR = 1 << 3;
|
||||
const IS_PHANTOM_DATA = 1 << 4;
|
||||
const IS_FUNDAMENTAL = 1 << 5;
|
||||
const IS_BOX = 1 << 6;
|
||||
/// Indicates whether the type is an `Arc`.
|
||||
const IS_ARC = 1 << 5;
|
||||
const IS_ARC = 1 << 7;
|
||||
/// Indicates whether the type is an `Rc`.
|
||||
const IS_RC = 1 << 6;
|
||||
const IS_RC = 1 << 8;
|
||||
/// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
|
||||
/// (i.e., this flag is never set unless this ADT is an enum).
|
||||
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 7;
|
||||
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2079,31 +2081,43 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
repr: ReprOptions) -> Self {
|
||||
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
|
||||
let mut flags = AdtFlags::NO_ADT_FLAGS;
|
||||
let attrs = tcx.get_attrs(did);
|
||||
if attr::contains_name(&attrs, "fundamental") {
|
||||
flags = flags | AdtFlags::IS_FUNDAMENTAL;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().phantom_data() {
|
||||
flags = flags | AdtFlags::IS_PHANTOM_DATA;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().owned_box() {
|
||||
flags = flags | AdtFlags::IS_BOX;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().arc() {
|
||||
flags = flags | AdtFlags::IS_ARC;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().rc() {
|
||||
flags = flags | AdtFlags::IS_RC;
|
||||
}
|
||||
|
||||
if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
|
||||
debug!("found non-exhaustive variant list for {:?}", did);
|
||||
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
|
||||
}
|
||||
match kind {
|
||||
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
|
||||
AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
|
||||
AdtKind::Struct => {}
|
||||
flags |= match kind {
|
||||
AdtKind::Enum => AdtFlags::IS_ENUM,
|
||||
AdtKind::Union => AdtFlags::IS_UNION,
|
||||
AdtKind::Struct => AdtFlags::IS_STRUCT,
|
||||
};
|
||||
|
||||
if let AdtKind::Struct = kind {
|
||||
let variant_def = &variants[VariantIdx::new(0)];
|
||||
let def_key = tcx.def_key(variant_def.did);
|
||||
match def_key.disambiguated_data.data {
|
||||
DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
let attrs = tcx.get_attrs(did);
|
||||
if attr::contains_name(&attrs, "fundamental") {
|
||||
flags |= AdtFlags::IS_FUNDAMENTAL;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().phantom_data() {
|
||||
flags |= AdtFlags::IS_PHANTOM_DATA;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().owned_box() {
|
||||
flags |= AdtFlags::IS_BOX;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().arc() {
|
||||
flags |= AdtFlags::IS_ARC;
|
||||
}
|
||||
if Some(did) == tcx.lang_items().rc() {
|
||||
flags |= AdtFlags::IS_RC;
|
||||
}
|
||||
|
||||
AdtDef {
|
||||
did,
|
||||
variants,
|
||||
@ -2114,25 +2128,25 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
|
||||
#[inline]
|
||||
pub fn is_struct(&self) -> bool {
|
||||
!self.is_union() && !self.is_enum()
|
||||
self.flags.contains(AdtFlags::IS_STRUCT)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_union(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_UNION)
|
||||
self.flags.contains(AdtFlags::IS_UNION)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_enum(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_ENUM)
|
||||
self.flags.contains(AdtFlags::IS_ENUM)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_variant_list_non_exhaustive(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
|
||||
self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
|
||||
}
|
||||
|
||||
/// Returns the kind of the ADT - Struct or Enum.
|
||||
/// Returns the kind of the ADT.
|
||||
#[inline]
|
||||
pub fn adt_kind(&self) -> AdtKind {
|
||||
if self.is_enum() {
|
||||
@ -2161,33 +2175,39 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether this type is #[fundamental] for the purposes
|
||||
/// If this function returns `true`, it implies that `is_struct` must return `true`.
|
||||
#[inline]
|
||||
pub fn has_ctor(&self) -> bool {
|
||||
self.flags.contains(AdtFlags::HAS_CTOR)
|
||||
}
|
||||
|
||||
/// Returns whether this type is `#[fundamental]` for the purposes
|
||||
/// of coherence checking.
|
||||
#[inline]
|
||||
pub fn is_fundamental(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
|
||||
self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is PhantomData<T>.
|
||||
#[inline]
|
||||
pub fn is_phantom_data(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
|
||||
self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is `Arc<T>`.
|
||||
pub fn is_arc(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_ARC)
|
||||
self.flags.contains(AdtFlags::IS_ARC)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is `Rc<T>`.
|
||||
pub fn is_rc(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_RC)
|
||||
self.flags.contains(AdtFlags::IS_RC)
|
||||
}
|
||||
|
||||
/// Returns `true` if this is Box<T>.
|
||||
#[inline]
|
||||
pub fn is_box(&self) -> bool {
|
||||
self.flags.intersects(AdtFlags::IS_BOX)
|
||||
self.flags.contains(AdtFlags::IS_BOX)
|
||||
}
|
||||
|
||||
/// Returns whether this type has a destructor.
|
||||
|
@ -16,7 +16,7 @@ num_cpus = "1.0"
|
||||
rustc-demangle = "0.1.4"
|
||||
memmap = "0.6"
|
||||
log = "0.4.5"
|
||||
libc = "0.2.43"
|
||||
libc = "0.2.44"
|
||||
jobserver = "0.1.11"
|
||||
|
||||
serialize = { path = "../libserialize" }
|
||||
|
@ -335,11 +335,20 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
bx: &mut Bx,
|
||||
llindex: V
|
||||
) -> Self {
|
||||
// Statically compute the offset if we can, otherwise just use the element size,
|
||||
// as this will yield the lowest alignment.
|
||||
let layout = self.layout.field(bx, 0);
|
||||
let offset = if bx.is_const_integral(llindex) {
|
||||
layout.size.checked_mul(bx.const_to_uint(llindex), bx).unwrap_or(layout.size)
|
||||
} else {
|
||||
layout.size
|
||||
};
|
||||
|
||||
PlaceRef {
|
||||
llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]),
|
||||
llextra: None,
|
||||
layout: self.layout.field(bx.cx(), 0),
|
||||
align: self.align
|
||||
layout,
|
||||
align: self.align.restrict_for_offset(offset),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
|
||||
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
|
||||
|
||||
let align = dest.align.restrict_for_offset(dest.layout.field(bx.cx(), 0).size);
|
||||
cg_elem.val.store(&mut body_bx,
|
||||
PlaceRef::new_sized(current, cg_elem.layout, dest.align));
|
||||
PlaceRef::new_sized(current, cg_elem.layout, align));
|
||||
|
||||
let next = body_bx.inbounds_gep(current, &[bx.cx().const_usize(1)]);
|
||||
body_bx.br(header_bx.llbb());
|
||||
|
@ -1415,7 +1415,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
self.check_call_dest(mir, term, &sig, destination, term_location);
|
||||
|
||||
self.prove_predicates(
|
||||
sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)),
|
||||
sig.inputs_and_output.iter().map(|ty| ty::Predicate::WellFormed(ty)),
|
||||
term_location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
);
|
||||
|
@ -86,7 +86,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
||||
type MemoryExtra: Default;
|
||||
|
||||
/// Extra data stored in every allocation.
|
||||
type AllocExtra: AllocationExtra<Self::PointerTag, Self::MemoryExtra>;
|
||||
type AllocExtra: AllocationExtra<Self::PointerTag, Self::MemoryExtra> + 'static;
|
||||
|
||||
/// Memory's allocation map
|
||||
type MemoryMap:
|
||||
|
@ -708,8 +708,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||
relocations
|
||||
.iter()
|
||||
.map(|&(offset, reloc)| {
|
||||
(offset + dest.offset - src.offset + (i * size * relocations.len() as u64),
|
||||
reloc)
|
||||
// compute offset for current repetition
|
||||
let dest_offset = dest.offset + (i * size);
|
||||
(
|
||||
// shift offsets from source allocation to destination allocation
|
||||
offset + dest_offset - src.offset,
|
||||
reloc,
|
||||
)
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
||||
|
||||
// Only allow statics (not consts) to refer to other statics.
|
||||
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
|
||||
if context.is_mutating_use() {
|
||||
if self.mode == Mode::Static && context.is_mutating_use() {
|
||||
// this is not strictly necessary as miri will also bail out
|
||||
// For interior mutability we can't really catch this statically as that
|
||||
// goes through raw pointers and intermediate temporaries, so miri has
|
||||
|
@ -230,13 +230,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
}
|
||||
|
||||
let subclass = SingleImport {
|
||||
target: ident,
|
||||
source: source.ident,
|
||||
result: PerNS {
|
||||
target: ident,
|
||||
source_bindings: PerNS {
|
||||
type_ns: Cell::new(Err(Undetermined)),
|
||||
value_ns: Cell::new(Err(Undetermined)),
|
||||
macro_ns: Cell::new(Err(Undetermined)),
|
||||
},
|
||||
target_bindings: PerNS {
|
||||
type_ns: Cell::new(None),
|
||||
value_ns: Cell::new(None),
|
||||
macro_ns: Cell::new(None),
|
||||
},
|
||||
type_ns_only,
|
||||
};
|
||||
self.add_import_directive(
|
||||
|
@ -75,7 +75,7 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
||||
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::{cmp, fmt, iter, ptr};
|
||||
use std::{cmp, fmt, iter, mem, ptr};
|
||||
use std::collections::BTreeSet;
|
||||
use std::mem::replace;
|
||||
use rustc_data_structures::ptr_key::PtrKey;
|
||||
@ -1022,11 +1022,11 @@ enum ModuleOrUniformRoot<'a> {
|
||||
CurrentScope,
|
||||
}
|
||||
|
||||
impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (*self, *other) {
|
||||
impl ModuleOrUniformRoot<'_> {
|
||||
fn same_def(lhs: Self, rhs: Self) -> bool {
|
||||
match (lhs, rhs) {
|
||||
(ModuleOrUniformRoot::Module(lhs),
|
||||
ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs),
|
||||
ModuleOrUniformRoot::Module(rhs)) => lhs.def() == rhs.def(),
|
||||
(ModuleOrUniformRoot::CrateRootAndExternPrelude,
|
||||
ModuleOrUniformRoot::CrateRootAndExternPrelude) |
|
||||
(ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) |
|
||||
@ -1521,6 +1521,7 @@ pub struct Resolver<'a, 'b: 'a> {
|
||||
|
||||
/// FIXME: Refactor things so that this is passed through arguments and not resolver.
|
||||
last_import_segment: bool,
|
||||
blacklisted_binding: Option<&'a NameBinding<'a>>,
|
||||
|
||||
/// The idents for the primitive types.
|
||||
primitive_type_table: PrimitiveTypeTable,
|
||||
@ -1871,6 +1872,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||
current_self_type: None,
|
||||
current_self_item: None,
|
||||
last_import_segment: false,
|
||||
blacklisted_binding: None,
|
||||
|
||||
primitive_type_table: PrimitiveTypeTable::new(),
|
||||
|
||||
@ -2392,11 +2394,27 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||
ast::UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..],
|
||||
_ => &[TypeNS],
|
||||
};
|
||||
let report_error = |this: &Self, ns| {
|
||||
let what = if ns == TypeNS { "type parameters" } else { "local variables" };
|
||||
this.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
|
||||
};
|
||||
|
||||
for &ns in nss {
|
||||
if let Some(LexicalScopeBinding::Def(..)) =
|
||||
self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) {
|
||||
let what = if ns == TypeNS { "type parameters" } else { "local variables" };
|
||||
self.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
|
||||
match self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) {
|
||||
Some(LexicalScopeBinding::Def(..)) => {
|
||||
report_error(self, ns);
|
||||
}
|
||||
Some(LexicalScopeBinding::Item(binding)) => {
|
||||
let orig_blacklisted_binding =
|
||||
mem::replace(&mut self.blacklisted_binding, Some(binding));
|
||||
if let Some(LexicalScopeBinding::Def(..)) =
|
||||
self.resolve_ident_in_lexical_scope(ident, ns, None,
|
||||
use_tree.prefix.span) {
|
||||
report_error(self, ns);
|
||||
}
|
||||
self.blacklisted_binding = orig_blacklisted_binding;
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
} else if let ast::UseTreeKind::Nested(use_trees) = &use_tree.kind {
|
||||
@ -3858,6 +3876,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||
module = Some(ModuleOrUniformRoot::Module(next_module));
|
||||
record_segment_def(self, def);
|
||||
} else if def == Def::ToolMod && i + 1 != path.len() {
|
||||
if binding.is_import() {
|
||||
self.session.struct_span_err(
|
||||
ident.span, "cannot use a tool module through an import"
|
||||
).span_note(
|
||||
binding.span, "the tool module imported here"
|
||||
).emit();
|
||||
}
|
||||
let def = Def::NonMacroAttr(NonMacroAttrKind::Tool);
|
||||
return PathResult::NonModule(PathResolution::new(def));
|
||||
} else if def == Def::Err {
|
||||
|
@ -499,6 +499,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
.push((path, path_span, kind, parent_scope.clone(), def.ok()));
|
||||
}
|
||||
|
||||
self.prohibit_imported_non_macro_attrs(None, def.ok(), path_span);
|
||||
def
|
||||
} else {
|
||||
let binding = self.early_resolve_ident_in_lexical_scope(
|
||||
@ -515,7 +516,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
.push((path[0].ident, kind, parent_scope.clone(), binding.ok()));
|
||||
}
|
||||
|
||||
binding.map(|binding| binding.def_ignoring_ambiguity())
|
||||
let def = binding.map(|binding| binding.def_ignoring_ambiguity());
|
||||
self.prohibit_imported_non_macro_attrs(binding.ok(), def.ok(), path_span);
|
||||
def
|
||||
}
|
||||
}
|
||||
|
||||
@ -953,36 +956,34 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
// but its `Def` should coincide with a crate passed with `--extern`
|
||||
// (otherwise there would be ambiguity) and we can skip feature error in this case.
|
||||
'ok: {
|
||||
if !is_import || self.session.features_untracked().uniform_paths {
|
||||
if !is_import || !rust_2015 {
|
||||
break 'ok;
|
||||
}
|
||||
if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
|
||||
break 'ok;
|
||||
}
|
||||
if rust_2015 {
|
||||
let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span);
|
||||
let root_module = self.resolve_crate_root(root_ident);
|
||||
if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
|
||||
orig_ident, ns, None, false, path_span)
|
||||
.is_ok() {
|
||||
break 'ok;
|
||||
}
|
||||
let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span);
|
||||
let root_module = self.resolve_crate_root(root_ident);
|
||||
if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
|
||||
orig_ident, ns, None, false, path_span)
|
||||
.is_ok() {
|
||||
break 'ok;
|
||||
}
|
||||
|
||||
let msg = "imports can only refer to extern crate names \
|
||||
passed with `--extern` on stable channel";
|
||||
let mut err = feature_err(&self.session.parse_sess, "uniform_paths",
|
||||
ident.span, GateIssue::Language, msg);
|
||||
|
||||
let msg = "imports can only refer to extern crate names passed with \
|
||||
`--extern` in macros originating from 2015 edition";
|
||||
let mut err = self.session.struct_span_err(ident.span, msg);
|
||||
let what = self.binding_description(binding, ident,
|
||||
flags.contains(Flags::MISC_FROM_PRELUDE));
|
||||
let note_msg = format!("this import refers to {what}", what = what);
|
||||
if binding.span.is_dummy() {
|
||||
let label_span = if binding.span.is_dummy() {
|
||||
err.note(¬e_msg);
|
||||
ident.span
|
||||
} else {
|
||||
err.span_note(binding.span, ¬e_msg);
|
||||
err.span_label(binding.span, "not an extern crate passed with `--extern`");
|
||||
}
|
||||
binding.span
|
||||
};
|
||||
err.span_label(label_span, "not an extern crate passed with `--extern`");
|
||||
err.emit();
|
||||
}
|
||||
|
||||
@ -1091,6 +1092,20 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
}
|
||||
}
|
||||
|
||||
fn prohibit_imported_non_macro_attrs(&self, binding: Option<&'a NameBinding<'a>>,
|
||||
def: Option<Def>, span: Span) {
|
||||
if let Some(Def::NonMacroAttr(kind)) = def {
|
||||
if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) {
|
||||
let msg = format!("cannot use a {} through an import", kind.descr());
|
||||
let mut err = self.session.struct_span_err(span, &msg);
|
||||
if let Some(binding) = binding {
|
||||
err.span_note(binding.span, &format!("the {} imported here", kind.descr()));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
|
||||
err: &mut DiagnosticBuilder<'a>, span: Span) {
|
||||
// First check if this is a locally-defined bang macro.
|
||||
@ -1187,7 +1202,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
let ident = ident.modern();
|
||||
self.macro_names.insert(ident);
|
||||
let def = Def::Macro(def_id, MacroKind::Bang);
|
||||
let vis = ty::Visibility::Invisible; // Doesn't matter for legacy bindings
|
||||
let is_macro_export = attr::contains_name(&item.attrs, "macro_export");
|
||||
let vis = if is_macro_export {
|
||||
ty::Visibility::Public
|
||||
} else {
|
||||
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
|
||||
};
|
||||
let binding = (def, vis, item.span, expansion).to_name_binding(self.arenas);
|
||||
self.set_binding_parent_module(binding, self.current_module);
|
||||
let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding {
|
||||
@ -1195,9 +1215,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||
});
|
||||
*current_legacy_scope = LegacyScope::Binding(legacy_binding);
|
||||
self.all_macros.insert(ident.name, def);
|
||||
if attr::contains_name(&item.attrs, "macro_export") {
|
||||
if is_macro_export {
|
||||
let module = self.graph_root;
|
||||
let vis = ty::Visibility::Public;
|
||||
self.define(module, ident, MacroNS,
|
||||
(def, vis, item.span, expansion, IsMacroExport));
|
||||
} else {
|
||||
|
@ -42,9 +42,10 @@ use std::{mem, ptr};
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ImportDirectiveSubclass<'a> {
|
||||
SingleImport {
|
||||
target: Ident,
|
||||
source: Ident,
|
||||
result: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
|
||||
target: Ident,
|
||||
source_bindings: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
|
||||
target_bindings: PerNS<Cell<Option<&'a NameBinding<'a>>>>,
|
||||
type_ns_only: bool,
|
||||
},
|
||||
GlobImport {
|
||||
@ -227,6 +228,11 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||
}
|
||||
|
||||
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
|
||||
if let Some(blacklisted_binding) = this.blacklisted_binding {
|
||||
if ptr::eq(binding, blacklisted_binding) {
|
||||
return Err((Determined, Weak::No));
|
||||
}
|
||||
}
|
||||
// `extern crate` are always usable for backwards compatibility, see issue #37020,
|
||||
// remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`.
|
||||
let usable = this.is_accessible(binding.vis) || binding.is_extern_crate();
|
||||
@ -234,7 +240,18 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||
};
|
||||
|
||||
if record_used {
|
||||
return resolution.binding.ok_or((Determined, Weak::No)).and_then(|binding| {
|
||||
return resolution.binding.and_then(|binding| {
|
||||
// If the primary binding is blacklisted, search further and return the shadowed
|
||||
// glob binding if it exists. What we really want here is having two separate
|
||||
// scopes in a module - one for non-globs and one for globs, but until that's done
|
||||
// use this hack to avoid inconsistent resolution ICEs during import validation.
|
||||
if let Some(blacklisted_binding) = self.blacklisted_binding {
|
||||
if ptr::eq(binding, blacklisted_binding) {
|
||||
return resolution.shadowed_glob;
|
||||
}
|
||||
}
|
||||
Some(binding)
|
||||
}).ok_or((Determined, Weak::No)).and_then(|binding| {
|
||||
if self.last_import_segment && check_usable(self, binding).is_err() {
|
||||
Err((Determined, Weak::No))
|
||||
} else {
|
||||
@ -465,6 +482,10 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
||||
self.set_binding_parent_module(binding, module);
|
||||
self.update_resolution(module, ident, ns, |this, resolution| {
|
||||
if let Some(old_binding) = resolution.binding {
|
||||
if binding.def() == Def::Err {
|
||||
// Do not override real bindings with `Def::Err`s from error recovery.
|
||||
return Ok(());
|
||||
}
|
||||
match (old_binding.is_glob_import(), binding.is_glob_import()) {
|
||||
(true, true) => {
|
||||
if binding.def() != old_binding.def() {
|
||||
@ -642,10 +663,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
if let Some((span, err, note)) = self.finalize_import(import) {
|
||||
errors = true;
|
||||
|
||||
if let SingleImport { source, ref result, .. } = import.subclass {
|
||||
if let SingleImport { source, ref source_bindings, .. } = import.subclass {
|
||||
if source.name == "self" {
|
||||
// Silence `unresolved import` error if E0429 is already emitted
|
||||
if let Err(Determined) = result.value_ns.get() {
|
||||
if let Err(Determined) = source_bindings.value_ns.get() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -765,9 +786,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
};
|
||||
|
||||
directive.imported_module.set(Some(module));
|
||||
let (source, target, result, type_ns_only) = match directive.subclass {
|
||||
SingleImport { source, target, ref result, type_ns_only } =>
|
||||
(source, target, result, type_ns_only),
|
||||
let (source, target, source_bindings, target_bindings, type_ns_only) =
|
||||
match directive.subclass {
|
||||
SingleImport { source, target, ref source_bindings,
|
||||
ref target_bindings, type_ns_only } =>
|
||||
(source, target, source_bindings, target_bindings, type_ns_only),
|
||||
GlobImport { .. } => {
|
||||
self.resolve_glob_import(directive);
|
||||
return true;
|
||||
@ -777,7 +800,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
|
||||
let mut indeterminate = false;
|
||||
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
|
||||
if let Err(Undetermined) = result[ns].get() {
|
||||
if let Err(Undetermined) = source_bindings[ns].get() {
|
||||
// For better failure detection, pretend that the import will
|
||||
// not define any names while resolving its module path.
|
||||
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
|
||||
@ -786,13 +809,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
);
|
||||
directive.vis.set(orig_vis);
|
||||
|
||||
result[ns].set(binding);
|
||||
source_bindings[ns].set(binding);
|
||||
} else {
|
||||
return
|
||||
};
|
||||
|
||||
let parent = directive.parent_scope.module;
|
||||
match result[ns].get() {
|
||||
match source_bindings[ns].get() {
|
||||
Err(Undetermined) => indeterminate = true,
|
||||
Err(Determined) => {
|
||||
this.update_resolution(parent, target, ns, |_, resolution| {
|
||||
@ -810,6 +833,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
}
|
||||
Ok(binding) => {
|
||||
let imported_binding = this.import(binding, directive);
|
||||
target_bindings[ns].set(Some(imported_binding));
|
||||
let conflict = this.try_define(parent, target, ns, imported_binding);
|
||||
if let Err(old_binding) = conflict {
|
||||
this.report_conflict(parent, target, ns, imported_binding, old_binding);
|
||||
@ -836,7 +860,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
PathResult::Module(module) => {
|
||||
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
|
||||
if let Some(initial_module) = directive.imported_module.get() {
|
||||
if module != initial_module && self.ambiguity_errors.is_empty() {
|
||||
if !ModuleOrUniformRoot::same_def(module, initial_module)
|
||||
&& self.ambiguity_errors.is_empty()
|
||||
{
|
||||
span_bug!(directive.span, "inconsistent resolution for an import");
|
||||
}
|
||||
} else {
|
||||
@ -879,8 +905,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
|
||||
};
|
||||
|
||||
let (ident, result, type_ns_only) = match directive.subclass {
|
||||
SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only),
|
||||
let (ident, source_bindings, target_bindings, type_ns_only) = match directive.subclass {
|
||||
SingleImport { source, ref source_bindings, ref target_bindings, type_ns_only, .. } =>
|
||||
(source, source_bindings, target_bindings, type_ns_only),
|
||||
GlobImport { is_prelude, ref max_vis } => {
|
||||
if directive.module_path.len() <= 1 {
|
||||
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
|
||||
@ -919,17 +946,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
let mut all_ns_err = true;
|
||||
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
|
||||
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
|
||||
let orig_blacklisted_binding =
|
||||
mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get());
|
||||
let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true);
|
||||
let binding = this.resolve_ident_in_module(
|
||||
module, ident, ns, Some(&directive.parent_scope), true, directive.span
|
||||
);
|
||||
this.last_import_segment = orig_last_import_segment;
|
||||
this.blacklisted_binding = orig_blacklisted_binding;
|
||||
directive.vis.set(orig_vis);
|
||||
|
||||
match binding {
|
||||
Ok(binding) => {
|
||||
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
|
||||
let initial_def = result[ns].get().map(|initial_binding| {
|
||||
let initial_def = source_bindings[ns].get().map(|initial_binding| {
|
||||
all_ns_err = false;
|
||||
this.record_use(ident, ns, initial_binding,
|
||||
directive.module_path.is_empty());
|
||||
@ -1034,7 +1064,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
let mut reexport_error = None;
|
||||
let mut any_successful_reexport = false;
|
||||
self.per_ns(|this, ns| {
|
||||
if let Ok(binding) = result[ns].get() {
|
||||
if let Ok(binding) = source_bindings[ns].get() {
|
||||
let vis = directive.vis.get();
|
||||
if !binding.pseudo_vis().is_at_least(vis, &*this) {
|
||||
reexport_error = Some((ns, binding));
|
||||
@ -1078,7 +1108,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
let mut full_path = directive.module_path.clone();
|
||||
full_path.push(Segment::from_ident(ident));
|
||||
self.per_ns(|this, ns| {
|
||||
if let Ok(binding) = result[ns].get() {
|
||||
if let Ok(binding) = source_bindings[ns].get() {
|
||||
this.lint_if_path_starts_with_module(
|
||||
directive.crate_lint(),
|
||||
&full_path,
|
||||
@ -1092,7 +1122,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
|
||||
// Record what this import resolves to for later uses in documentation,
|
||||
// this may resolve to either a value or a type, but for documentation
|
||||
// purposes it's good enough to just favor one over the other.
|
||||
self.per_ns(|this, ns| if let Some(binding) = result[ns].get().ok() {
|
||||
self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() {
|
||||
let mut def = binding.def();
|
||||
if let Def::Macro(def_id, _) = def {
|
||||
// `DefId`s from the "built-in macro crate" should not leak from resolve because
|
||||
|
@ -1013,6 +1013,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
let mut associated_types = BTreeSet::default();
|
||||
|
||||
for tr in traits::elaborate_trait_ref(tcx, principal) {
|
||||
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr);
|
||||
match tr {
|
||||
ty::Predicate::Trait(pred) => {
|
||||
associated_types.extend(tcx.associated_items(pred.def_id())
|
||||
@ -1020,8 +1021,31 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
.map(|item| item.def_id));
|
||||
}
|
||||
ty::Predicate::Projection(pred) => {
|
||||
// Include projections defined on supertraits.
|
||||
projection_bounds.push((pred, DUMMY_SP))
|
||||
// A `Self` within the original bound will be substituted with a
|
||||
// `TRAIT_OBJECT_DUMMY_SELF`, so check for that.
|
||||
let references_self =
|
||||
pred.skip_binder().ty.walk().any(|t| t == dummy_self);
|
||||
|
||||
// If the projection output contains `Self`, force the user to
|
||||
// elaborate it explicitly to avoid a bunch of complexity.
|
||||
//
|
||||
// The "classicaly useful" case is the following:
|
||||
// ```
|
||||
// trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
|
||||
// type MyOutput;
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here, the user could theoretically write `dyn MyTrait<Output=X>`,
|
||||
// but actually supporting that would "expand" to an infinitely-long type
|
||||
// `fix $ τ → dyn MyTrait<MyOutput=X, Output=<τ as MyTrait>::MyOutput`.
|
||||
//
|
||||
// Instead, we force the user to write `dyn MyTrait<MyOutput=X, Output=X>`,
|
||||
// which is uglier but works. See the discussion in #56288 for alternatives.
|
||||
if !references_self {
|
||||
// Include projections defined on supertraits,
|
||||
projection_bounds.push((pred, DUMMY_SP))
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
Def::Local(id) | Def::Upvar(id, ..) => {
|
||||
Some(self.tcx.hir.span(id))
|
||||
}
|
||||
_ => self.tcx.hir.span_if_local(def.def_id())
|
||||
_ => def.opt_def_id().and_then(|did| self.tcx.hir.span_if_local(did)),
|
||||
};
|
||||
if let Some(span) = def_span {
|
||||
let label = match (unit_variant, inner_callee_path) {
|
||||
|
@ -98,7 +98,8 @@ use rustc::mir::interpret::{ConstValue, GlobalId};
|
||||
use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs,
|
||||
UserSelfTy, UserSubsts};
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
|
||||
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
|
||||
use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate,
|
||||
RegionKind};
|
||||
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::query::Providers;
|
||||
@ -914,6 +915,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fcx.resolve_generator_interiors(def_id);
|
||||
|
||||
for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
|
||||
let ty = fcx.normalize_ty(span, ty);
|
||||
fcx.require_type_is_sized(ty, span, code);
|
||||
}
|
||||
fcx.select_all_obligations_or_error();
|
||||
@ -3221,8 +3223,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
return_expr_ty);
|
||||
}
|
||||
|
||||
// A generic function for checking the then and else in an if
|
||||
// or if-else.
|
||||
// A generic function for checking the 'then' and 'else' clauses in an 'if'
|
||||
// or 'if-else' expression.
|
||||
fn check_then_else(&self,
|
||||
cond_expr: &'gcx hir::Expr,
|
||||
then_expr: &'gcx hir::Expr,
|
||||
@ -3547,8 +3549,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
// we don't look at stability attributes on
|
||||
// struct-like enums (yet...), but it's definitely not
|
||||
// a bug to have construct one.
|
||||
if adt_kind != ty::AdtKind::Enum {
|
||||
// a bug to have constructed one.
|
||||
if adt_kind != AdtKind::Enum {
|
||||
tcx.check_stability(v_field.did, Some(expr_id), field.span);
|
||||
}
|
||||
|
||||
@ -3969,7 +3971,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
//
|
||||
// to work in stable even if the Sized bound on `drop` is relaxed.
|
||||
for i in 0..fn_sig.inputs().skip_binder().len() {
|
||||
let input = tcx.erase_late_bound_regions(&fn_sig.input(i));
|
||||
// We just want to check sizedness, so instead of introducing
|
||||
// placeholder lifetimes with probing, we just replace higher lifetimes
|
||||
// with fresh vars.
|
||||
let input = self.replace_bound_vars_with_fresh_vars(
|
||||
expr.span,
|
||||
infer::LateBoundRegionConversionTime::FnCall,
|
||||
&fn_sig.input(i)).0;
|
||||
self.require_type_is_sized_deferred(input, expr.span,
|
||||
traits::SizedArgumentType);
|
||||
}
|
||||
@ -3977,7 +3985,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// Here we want to prevent struct constructors from returning unsized types.
|
||||
// There were two cases this happened: fn pointer coercion in stable
|
||||
// and usual function call in presense of unsized_locals.
|
||||
let output = tcx.erase_late_bound_regions(&fn_sig.output());
|
||||
// Also, as we just want to check sizedness, instead of introducing
|
||||
// placeholder lifetimes with probing, we just replace higher lifetimes
|
||||
// with fresh vars.
|
||||
let output = self.replace_bound_vars_with_fresh_vars(
|
||||
expr.span,
|
||||
infer::LateBoundRegionConversionTime::FnCall,
|
||||
&fn_sig.output()).0;
|
||||
self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType);
|
||||
}
|
||||
|
||||
@ -5148,26 +5162,48 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}).unwrap_or(false);
|
||||
|
||||
let mut new_def = def;
|
||||
let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def {
|
||||
let ty = self.impl_self_ty(span, impl_def_id).ty;
|
||||
let (def_id, ty) = match def {
|
||||
Def::SelfCtor(impl_def_id) => {
|
||||
let ty = self.impl_self_ty(span, impl_def_id).ty;
|
||||
let adt_def = ty.ty_adt_def();
|
||||
|
||||
match ty.ty_adt_def() {
|
||||
Some(adt_def) if adt_def.is_struct() => {
|
||||
let variant = adt_def.non_enum_variant();
|
||||
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
|
||||
(variant.did, self.tcx.type_of(variant.did))
|
||||
}
|
||||
_ => {
|
||||
(impl_def_id, self.tcx.types.err)
|
||||
match adt_def {
|
||||
Some(adt_def) if adt_def.has_ctor() => {
|
||||
let variant = adt_def.non_enum_variant();
|
||||
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
|
||||
(variant.did, self.tcx.type_of(variant.did))
|
||||
}
|
||||
_ => {
|
||||
let mut err = self.tcx.sess.struct_span_err(span,
|
||||
"the `Self` constructor can only be used with tuple or unit structs");
|
||||
if let Some(adt_def) = adt_def {
|
||||
match adt_def.adt_kind() {
|
||||
AdtKind::Enum => {
|
||||
err.note("did you mean to use one of the enum's variants?");
|
||||
},
|
||||
AdtKind::Struct |
|
||||
AdtKind::Union => {
|
||||
err.span_label(
|
||||
span,
|
||||
format!("did you mean `Self {{ /* fields */ }}`?"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
|
||||
(impl_def_id, self.tcx.types.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let def_id = def.def_id();
|
||||
_ => {
|
||||
let def_id = def.def_id();
|
||||
|
||||
// The things we are substituting into the type should not contain
|
||||
// escaping late-bound regions, and nor should the base type scheme.
|
||||
let ty = self.tcx.type_of(def_id);
|
||||
(def_id, ty)
|
||||
// The things we are substituting into the type should not contain
|
||||
// escaping late-bound regions, and nor should the base type scheme.
|
||||
let ty = self.tcx.type_of(def_id);
|
||||
(def_id, ty)
|
||||
}
|
||||
};
|
||||
|
||||
let substs = AstConv::create_substs_for_generic_args(
|
||||
|
@ -283,7 +283,7 @@ nav.sub {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
:not(.source) .example-wrap {
|
||||
.rustdoc:not(.source) .example-wrap {
|
||||
display: inline-flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -301,11 +301,11 @@ nav.sub {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
:not(.source) .example-wrap > pre.rust {
|
||||
.rustdoc:not(.source) .example-wrap > pre.rust {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body:not(.source) .example-wrap > pre {
|
||||
.rustdoc:not(.source) .example-wrap > pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
@ -395,7 +395,7 @@ pub fn make_test(s: &str,
|
||||
|
||||
// Uses libsyntax to parse the doctest and find if there's a main fn and the extern
|
||||
// crate already is included.
|
||||
let (already_has_main, already_has_extern_crate) = crate::syntax::with_globals(|| {
|
||||
let (already_has_main, already_has_extern_crate, found_macro) = crate::syntax::with_globals(|| {
|
||||
use crate::syntax::{ast, parse::{self, ParseSess}, source_map::FilePathMapping};
|
||||
use crate::syntax_pos::FileName;
|
||||
use errors::emitter::EmitterWriter;
|
||||
@ -415,6 +415,7 @@ pub fn make_test(s: &str,
|
||||
|
||||
let mut found_main = false;
|
||||
let mut found_extern_crate = cratename.is_none();
|
||||
let mut found_macro = false;
|
||||
|
||||
let mut parser = match parse::maybe_new_parser_from_source_str(&sess, filename, source) {
|
||||
Ok(p) => p,
|
||||
@ -423,7 +424,7 @@ pub fn make_test(s: &str,
|
||||
err.cancel();
|
||||
}
|
||||
|
||||
return (found_main, found_extern_crate);
|
||||
return (found_main, found_extern_crate, found_macro);
|
||||
}
|
||||
};
|
||||
|
||||
@ -451,6 +452,12 @@ pub fn make_test(s: &str,
|
||||
}
|
||||
}
|
||||
|
||||
if !found_macro {
|
||||
if let ast::ItemKind::Mac(..) = item.node {
|
||||
found_macro = true;
|
||||
}
|
||||
}
|
||||
|
||||
if found_main && found_extern_crate {
|
||||
break;
|
||||
}
|
||||
@ -463,9 +470,28 @@ pub fn make_test(s: &str,
|
||||
}
|
||||
}
|
||||
|
||||
(found_main, found_extern_crate)
|
||||
(found_main, found_extern_crate, found_macro)
|
||||
});
|
||||
|
||||
// If a doctest's `fn main` is being masked by a wrapper macro, the parsing loop above won't
|
||||
// see it. In that case, run the old text-based scan to see if they at least have a main
|
||||
// function written inside a macro invocation. See
|
||||
// https://github.com/rust-lang/rust/issues/56898
|
||||
let already_has_main = if found_macro && !already_has_main {
|
||||
s.lines()
|
||||
.map(|line| {
|
||||
let comment = line.find("//");
|
||||
if let Some(comment_begins) = comment {
|
||||
&line[0..comment_begins]
|
||||
} else {
|
||||
line
|
||||
}
|
||||
})
|
||||
.any(|code| code.contains("fn main"))
|
||||
} else {
|
||||
already_has_main
|
||||
};
|
||||
|
||||
// Don't inject `extern crate std` because it's already injected by the
|
||||
// compiler.
|
||||
if !already_has_extern_crate && !opts.no_crate_inject && cratename != Some("std") {
|
||||
@ -1106,4 +1132,23 @@ assert_eq!(asdf::foo, 4);
|
||||
let output = make_test(input, Some("asdf"), false, &opts);
|
||||
assert_eq!(output, (expected, 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn make_test_main_in_macro() {
|
||||
let opts = TestOptions::default();
|
||||
let input =
|
||||
"#[macro_use] extern crate my_crate;
|
||||
test_wrapper! {
|
||||
fn main() {}
|
||||
}";
|
||||
let expected =
|
||||
"#![allow(unused)]
|
||||
#[macro_use] extern crate my_crate;
|
||||
test_wrapper! {
|
||||
fn main() {}
|
||||
}".to_string();
|
||||
|
||||
let output = make_test(input, Some("my_crate"), false, &opts);
|
||||
assert_eq!(output, (expected, 1));
|
||||
}
|
||||
}
|
||||
|
@ -459,10 +459,7 @@ declare_features! (
|
||||
// Support for arbitrary delimited token streams in non-macro attributes
|
||||
(active, unrestricted_attribute_tokens, "1.30.0", Some(55208), None),
|
||||
|
||||
// Allows `use x::y;` to resolve through `self::x`, not just `::x`
|
||||
(active, uniform_paths, "1.30.0", Some(53130), None),
|
||||
|
||||
// Allows unsized rvalues at arguments and parameters
|
||||
// Allows unsized rvalues at arguments and parameters.
|
||||
(active, unsized_locals, "1.30.0", Some(48055), None),
|
||||
|
||||
// #![test_runner]
|
||||
@ -689,6 +686,8 @@ declare_features! (
|
||||
(accepted, self_struct_ctor, "1.32.0", Some(51994), None),
|
||||
// `Self` in type definitions (RFC 2300)
|
||||
(accepted, self_in_typedefs, "1.32.0", Some(49303), None),
|
||||
// Allows `use x::y;` to search `x` in the current scope.
|
||||
(accepted, uniform_paths, "1.32.0", Some(53130), None),
|
||||
);
|
||||
|
||||
// If you change this, please modify `src/doc/unstable-book` as well. You must
|
||||
|
@ -1,4 +1,4 @@
|
||||
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
|
||||
# The actual contents of this file do not matter, but to trigger a change on the
|
||||
# build bots then the contents should be changed so git updates the mtime.
|
||||
2018-11-28
|
||||
2018-12-13
|
||||
|
@ -12,8 +12,8 @@
|
||||
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
|
||||
# `0.x.0` for Cargo where they were released on `date`.
|
||||
|
||||
date: 2018-12-06
|
||||
rustc: 1.31.0
|
||||
date: 2018-12-20
|
||||
rustc: 1.31.1
|
||||
cargo: 0.32.0
|
||||
|
||||
# When making a stable release the process currently looks like:
|
||||
|
44
src/test/codegen/issue-56927.rs
Normal file
44
src/test/codegen/issue-56927.rs
Normal file
@ -0,0 +1,44 @@
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
|
||||
#![crate_type="rlib"]
|
||||
use std::usize;
|
||||
|
||||
#[repr(align(16))]
|
||||
pub struct S {
|
||||
arr: [u32; 4],
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @test1
|
||||
// CHECK: store i32 0, i32* %{{.+}}, align 16
|
||||
// CHECK: store i32 1, i32* %{{.+}}, align 4
|
||||
// CHECK: store i32 2, i32* %{{.+}}, align 8
|
||||
// CHECK: store i32 3, i32* %{{.+}}, align 4
|
||||
#[no_mangle]
|
||||
pub fn test1(s: &mut S) {
|
||||
s.arr[0] = 0;
|
||||
s.arr[1] = 1;
|
||||
s.arr[2] = 2;
|
||||
s.arr[3] = 3;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @test2
|
||||
// CHECK: store i32 4, i32* %{{.+}}, align 4
|
||||
#[allow(const_err)]
|
||||
#[no_mangle]
|
||||
pub fn test2(s: &mut S) {
|
||||
s.arr[usize::MAX / 4 + 1] = 4;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @test3
|
||||
// CHECK: store i32 5, i32* %{{.+}}, align 4
|
||||
#[no_mangle]
|
||||
pub fn test3(s: &mut S, i: usize) {
|
||||
s.arr[i] = 5;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @test4
|
||||
// CHECK: store i32 6, i32* %{{.+}}, align 4
|
||||
#[no_mangle]
|
||||
pub fn test4(s: &mut S) {
|
||||
s.arr = [6; 4];
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user