New upstream version 1.32.0+dfsg1

This commit is contained in:
Ximin Luo 2019-01-27 21:51:14 -08:00
parent a1dfa0c682
commit 69743fb678
288 changed files with 4337 additions and 3485 deletions

96
Cargo.lock generated
View File

@ -69,7 +69,7 @@ name = "atty"
version = "0.2.11" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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 = [ dependencies = [
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
@ -128,7 +128,7 @@ dependencies = [
"filetime 0.2.1 (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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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_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)", "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)", "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)", "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)", "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)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -392,7 +392,7 @@ name = "commoncrypto-sys"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@ -412,7 +412,7 @@ dependencies = [
"filetime 0.2.1 (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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"core-foundation-sys 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
@ -567,7 +567,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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-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)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "openssl-sys 0.9.38 (registry+https://github.com/rust-lang/crates.io-index)",
@ -631,7 +631,7 @@ name = "directories"
version = "1.0.2" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cfg-if 0.1.5 (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)",
"redox_syscall 0.1.40 (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" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -802,7 +802,7 @@ name = "fs2"
version = "0.4.3" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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 = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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]] [[package]]
@ -1046,7 +1046,7 @@ name = "jobserver"
version = "0.1.11" version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1120,7 +1120,7 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.43" version = "0.2.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -1130,7 +1130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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 = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1285,7 +1285,7 @@ name = "memchr"
version = "2.0.2" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@ -1293,7 +1293,7 @@ name = "memmap"
version = "0.6.2" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
@ -1384,7 +1384,7 @@ name = "num_cpus"
version = "1.8.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@ -1411,7 +1411,7 @@ dependencies = [
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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)", "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" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"fuchsia-zircon 0.3.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)",
"winapi 0.3.6 (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 = [ dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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 = [ dependencies = [
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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 = [ dependencies = [
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cfg-if 0.1.5 (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)",
"redox_syscall 0.1.40 (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)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2939,11 +2939,11 @@ dependencies = [
[[package]] [[package]]
name = "tar" name = "tar"
version = "0.4.19" version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"filetime 0.2.1 (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)",
"redox_syscall 0.1.40 (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)", "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -2953,7 +2953,7 @@ name = "tempfile"
version = "3.0.3" version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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)", "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)", "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" version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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_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)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -3040,7 +3040,7 @@ name = "time"
version = "0.1.40" version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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_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)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -3197,7 +3197,7 @@ name = "wait-timeout"
version = "0.1.5" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]
@ -3261,7 +3261,7 @@ name = "xattr"
version = "0.2.2" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[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 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 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 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 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 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" "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 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 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 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 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 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" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"

View File

@ -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) Version 1.31.0 (2018-12-06)
========================== ==========================

View File

@ -1 +1 @@
a01e4761a1507939430d4044a5f0a35fdb2b146c 9fda7c2237db910e41d6a712e9a2139b352e558b

View File

@ -67,7 +67,7 @@ RUN ./build-gcc.sh
COPY dist-x86_64-linux/build-python.sh /tmp/ COPY dist-x86_64-linux/build-python.sh /tmp/
RUN ./build-python.sh 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. # clang/clang++ compilers.
COPY dist-x86_64-linux/build-clang.sh /tmp/ COPY dist-x86_64-linux/build-clang.sh /tmp/
RUN ./build-clang.sh RUN ./build-clang.sh

View File

@ -67,7 +67,7 @@ RUN ./build-gcc.sh
COPY dist-x86_64-linux/build-python.sh /tmp/ COPY dist-x86_64-linux/build-python.sh /tmp/
RUN ./build-python.sh 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. # clang/clang++ compilers.
COPY dist-x86_64-linux/build-clang.sh /tmp/ COPY dist-x86_64-linux/build-clang.sh /tmp/
RUN ./build-clang.sh RUN ./build-clang.sh

View File

@ -13,7 +13,7 @@ set -ex
source shared.sh source shared.sh
LLVM=7.0.0 LLVM=6.0.0
mkdir clang mkdir clang
cd clang cd clang

View File

@ -20,4 +20,5 @@ COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh RUN sh /scripts/sccache.sh
ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 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

View File

@ -51,7 +51,7 @@ hide_output make clean
cd .. cd ..
LLVM=70 LLVM=60
# may have been downloaded in a previous run # may have been downloaded in a previous run
if [ ! -d libunwind-release_$LLVM ]; then if [ ! -d libunwind-release_$LLVM ]; then

View File

@ -52,7 +52,7 @@ fi
# #
# FIXME: need a scheme for changing this `nightly` value to `beta` and `stable` # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable`
# either automatically or manually. # either automatically or manually.
export RUST_RELEASE_CHANNEL=beta export RUST_RELEASE_CHANNEL=stable
if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"

View File

@ -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> * <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 [2]: ../reference/attributes.html

View File

@ -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> * <small>[In the first edition: Section 7 — Bibliography][1]</small>
[1]: first-edition/bibliography.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/bibliography.html
[2]: second-edition/index.html [2]: index.html
[3]: ../reference/influences.html [3]: ../reference/influences.html

View File

@ -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> * <small>[In the first edition: Ch 4.10 — Borrow and AsRef][1]</small>
[1]: first-edition/borrow-and-asref.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/borrow-and-asref.html
[2]: second-edition/index.html [2]: index.html
[3]: ../std/convert/trait.AsRef.html [3]: ../std/convert/trait.AsRef.html

View File

@ -20,13 +20,13 @@ fn average(values: &[f64]) -> f64 {
Here are the relevant sections in the new and old books: 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 Reference: Type Cast Expressions][3]
* [In the Rust documentation: `mem::transmute`][4] * [In the Rust documentation: `mem::transmute`][4]
* <small>[In the first edition: Ch 3.29 — Casting between types][1]</small> * <small>[In the first edition: Ch 3.29 — Casting between types][1]</small>
[1]: first-edition/casting-between-types.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/casting-between-types.html
[2]: second-edition/appendix-01-keywords.html [2]: appendix-01-keywords.html
[3]: ../reference/expressions/operator-expr.html#type-cast-expressions [3]: ../reference/expressions/operator-expr.html#type-cast-expressions
[4]: ../std/mem/fn.transmute.html [4]: ../std/mem/fn.transmute.html

View File

@ -14,9 +14,9 @@ println!("b = {}", b);
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 4.8 — Choosing your Guarantees][1]</small>
[1]: first-edition/choosing-your-guarantees.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/choosing-your-guarantees.html
[2]: second-edition/ch15-00-smart-pointers.html [2]: ch15-00-smart-pointers.html

View File

@ -20,9 +20,9 @@ let expensive_closure = |num| {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.23 — Closures][1]</small>
[1]: first-edition/closures.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/closures.html
[2]: second-edition/ch13-01-closures.html [2]: ch13-01-closures.html

View File

@ -15,9 +15,9 @@
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.4 — Comments][1]</small>
[1]: first-edition/comments.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/comments.html
[2]: second-edition/ch03-04-comments.html [2]: ch03-04-comments.html

View File

@ -9,9 +9,9 @@
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 4.6 — Concurrency][1]</small>
[1]: first-edition/concurrency.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/concurrency.html
[2]: second-edition/ch16-00-concurrency.html [2]: ch16-00-concurrency.html

View File

@ -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> * <small>[In the first edition: Ch 4.3 — Conditional Compilation][1]</small>
[1]: first-edition/conditional-compilation.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/conditional-compilation.html
[2]: second-edition/index.html [2]: index.html
[3]: ../reference/attributes.html#conditional-compilation [3]: ../reference/attributes.html#conditional-compilation

View File

@ -18,11 +18,11 @@ mod network {
Here are the relevant sections in the new and old books: 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 current 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 14.02 — Publishing a Crate to Crates.io][3]
* <small>[In the first edition: Ch 3.25 — Crates and Modules][1]</small> * <small>[In the first edition: Ch 3.25 — Crates and Modules][1]</small>
[1]: first-edition/crates-and-modules.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/crates-and-modules.html
[2]: second-edition/ch07-01-mod-and-the-filesystem.html [2]: ch07-00-packages-crates-and-modules.html
[3]: second-edition/ch14-02-publishing-to-crates-io.html [3]: ch14-02-publishing-to-crates-io.html

View File

@ -22,9 +22,9 @@ impl<T> Deref for MyBox<T> {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.33 — Deref coercions][1]</small>
[1]: first-edition/deref-coercions.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/deref-coercions.html
[2]: second-edition/ch15-02-deref.html [2]: ch15-02-deref.html

View File

@ -26,9 +26,9 @@ fn main() {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.20 — Drop][1]</small>
[1]: first-edition/drop.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/drop.html
[2]: second-edition/ch15-03-drop.html [2]: ch15-03-drop.html

View File

@ -10,5 +10,5 @@ It is recommended to start there.
* <small>[In the first edition: Ch 4 — Effective Rust][1]</small> * <small>[In the first edition: Ch 4 — Effective Rust][1]</small>
[1]: first-edition/effective-rust.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/effective-rust.html
[2]: second-edition/index.html [2]: index.html

View File

@ -15,9 +15,9 @@ enum IpAddrKind {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.13 — Enums][1]</small>
[1]: first-edition/enums.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/enums.html
[2]: second-edition/ch06-01-defining-an-enum.html [2]: ch06-01-defining-an-enum.html

View File

@ -8,9 +8,9 @@
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 4.7 — Error Handling][1]</small>
[1]: first-edition/error-handling.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/error-handling.html
[2]: second-edition/ch09-00-error-handling.html [2]: ch09-00-error-handling.html

View File

@ -23,8 +23,8 @@ fn another_function() {
Here are the relevant sections in the new and old books: Here are the relevant sections in the new and old books:
* **[In the first edition: Ch 3.2 — Functions][1]** * **[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 [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/functions.html
[2]: second-edition/ch03-03-how-functions-work.html [2]: ch03-03-how-functions-work.html

View File

@ -21,10 +21,10 @@ fn main() {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.18 — Generics][1]</small>
[1]: first-edition/generics.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/generics.html
[2]: second-edition/ch10-00-generics.html [2]: ch10-00-generics.html

View File

@ -5,9 +5,9 @@
You can [continue to the exact older page][1]. 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. 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> * <small>[In the first edition: Getting Started][1]</small>
[1]: first-edition/getting-started.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/getting-started.html
[2]: second-edition/ch01-00-getting-started.html [2]: ch01-00-getting-started.html

View File

@ -10,5 +10,5 @@ It is recommended to start there.
* <small>[In the first edition: Glossary][1]</small> * <small>[In the first edition: Glossary][1]</small>
[1]: first-edition/glossary.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/glossary.html
[2]: second-edition/index.html [2]: index.html

View File

@ -5,8 +5,8 @@
If you're trying to learn Rust, checking out [the second edition][2] might be a better choice. 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]** * **[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 [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/guessing-game.html
[2]: second-edition/ch02-00-guessing-game-tutorial.html [2]: ch02-00-guessing-game-tutorial.html

View File

@ -15,9 +15,8 @@ if let Some(3) = some_u8_value {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.21 — if let][1]</small>
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/if-let.html
[1]: first-edition/if-let.html [2]: ch06-03-if-let.html
[2]: second-edition/ch06-03-if-let.html

View File

@ -19,9 +19,9 @@ for val in v1_iter {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 4.5 — Iterators][1]</small>
[1]: first-edition/iterators.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/iterators.html
[2]: second-edition/ch13-02-iterators.html [2]: ch13-02-iterators.html

View File

@ -20,11 +20,11 @@
Here are the relevant sections in the new and old books: Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 10.03 — Lifetimes][2]** * **[in the current edition: Ch 10.03 — Lifetimes][2]**
* [In the second edition: Ch 19.02 — Advanced Lifetimes][3] * [in the current edition: Ch 19.02 — Advanced Lifetimes][3]
* <small>[In the first edition: Ch 3.10 — Lifetimes][1]</small> * <small>[In the first edition: Ch 3.10 — Lifetimes][1]</small>
[1]: first-edition/lifetimes.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/lifetimes.html
[2]: second-edition/ch10-03-lifetime-syntax.html [2]: ch10-03-lifetime-syntax.html
[3]: second-edition/ch19-02-advanced-lifetimes.html [3]: ch19-02-advanced-lifetimes.html

View File

@ -18,13 +18,13 @@ fn main() {
Here are the relevant sections in the new and old books: 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] * [Rust By Example: Macros][3]
* [In the Rust Reference: Ch 3.1 — Macros by Example][4] * [In the Rust Reference: Ch 3.1 — Macros by Example][4]
* <small>[In the first edition: Ch 3.34 — Macros][1]</small> * <small>[In the first edition: Ch 3.34 — Macros][1]</small>
[1]: first-edition/macros.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/macros.html
[2]: second-edition/appendix-04-macros.html [2]: ch19-06-macros.html
[3]: https://rustbyexample.com/macros.html [3]: https://rustbyexample.com/macros.html
[4]: ../reference/macros-by-example.html [4]: ../reference/macros-by-example.html

View File

@ -27,12 +27,12 @@ fn value_in_cents(coin: Coin) -> u32 {
Here are the relevant sections in the new and old books: 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 current edition: Ch 6.02 — The `match` Control Flow Operator][2]**
* [In the second edition: Ch 18.00 — Patterns][3] * [in the current edition: Ch 18.00 — Patterns][3]
* <small>[In the first edition: Ch 3.14 — Match][1]</small> * <small>[In the first edition: Ch 3.14 — Match][1]</small>
[1]: first-edition/match.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/match.html
[2]: second-edition/ch06-02-match.html [2]: ch06-02-match.html
[3]: second-edition/ch18-00-patterns.html [3]: ch18-00-patterns.html

View File

@ -21,9 +21,9 @@ impl Rectangle {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.16 — Method Syntax][1]</small>
[1]: first-edition/method-syntax.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/method-syntax.html
[2]: second-edition/ch05-03-method-syntax.html [2]: ch05-03-method-syntax.html

View File

@ -15,9 +15,9 @@ println!("The value of x is: {}", x);
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.11 — Mutability][1]</small>
[1]: first-edition/mutability.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/mutability.html
[2]: second-edition/ch03-01-variables-and-mutability.html [2]: ch03-01-variables-and-mutability.html

View File

@ -12,9 +12,9 @@
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.8 — Ownership][1]</small>
[1]: first-edition/ownership.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/ownership.html
[2]: second-edition/ch04-00-understanding-ownership.html [2]: ch04-00-understanding-ownership.html

View File

@ -16,9 +16,9 @@ let y: f32 = 3.0; // f32
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.3 — Primitive Types][1]</small>
[1]: first-edition/primitive-types.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/primitive-types.html
[2]: second-edition/ch03-02-data-types.html [2]: ch03-02-data-types.html

View File

@ -9,13 +9,13 @@
This chapter does not exist yet in [the second edition][2]. This chapter does not exist yet in [the second edition][2].
You can check out other resources that describe macros. 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] * [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> * <small>[In the first edition: Ch 4.13 — Procedural Macros (and custom Derive)][1]</small>
[1]: first-edition/procedural-macros.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/procedural-macros.html
[2]: second-edition/appendix-04-macros.html [2]: ch19-06-macros.html
[3]: ../proc_macro/index.html [3]: ../proc_macro/index.html
[4]: ../reference/procedural-macros.html [4]: ../reference/procedural-macros.html

View File

@ -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: 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> * <small>[In the first edition: Ch 3.9 — References and Borrowing][1]</small>
[1]: first-edition/references-and-borrowing.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/references-and-borrowing.html
[2]: second-edition/ch04-02-references-and-borrowing.html [2]: ch04-02-references-and-borrowing.html

View File

@ -16,12 +16,12 @@ You can check out other resources that describe release channels.
* **[In the Rustup documentation: Keeping Rust Up-to-date][4]** * **[In the Rustup documentation: Keeping Rust Up-to-date][4]**
* [On the website: Install Rust][5] * [On the website: Install Rust][5]
* [In the Rust RFCs: RFC 507 — Release Channels][3] * [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> * <small>[In the first edition: Ch 4.11 — Release Channels][1]</small>
[1]: first-edition/release-channels.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/release-channels.html
[2]: second-edition/appendix-07-nightly-rust.html [2]: appendix-07-nightly-rust.html
[3]: https://github.com/rust-lang/rfcs/blob/master/text/0507-release-channels.md [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 [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 [5]: https://www.rust-lang.org/en-US/install.html

View File

@ -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> * <small>[In the first edition: Ch 3.12 — Structs][1]</small>
[1]: first-edition/structs.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/structs.html
[2]: second-edition/ch05-00-structs.html [2]: ch05-00-structs.html

View File

@ -5,14 +5,14 @@
Here are the relevant sections in the new and old books: Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 3.00 — Common Programming Concepts][2]** * **[in the current edition: Ch 3.00 — Common Programming Concepts][2]**
* [In the second edition: Appendix A — Keywords][3] * [in the current edition: Appendix A — Keywords][3]
* [In the second edition: Appendix B — Operators][4] * [in the current edition: Appendix B — Operators][4]
* <small>[In the first edition: Ch 3 — Syntax and Semantics][1]</small> * <small>[In the first edition: Ch 3 — Syntax and Semantics][1]</small>
[1]: first-edition/syntax-and-semantics.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/syntax-and-semantics.html
[2]: second-edition/ch03-00-common-programming-concepts.html [2]: ch03-00-common-programming-concepts.html
[3]: second-edition/appendix-01-keywords.html [3]: appendix-01-keywords.html
[4]: second-edition/appendix-02-operators.html [4]: appendix-02-operators.html

View File

@ -4,11 +4,10 @@
Here are the relevant sections in the new and old books: 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 second edition: Appendix B — Operators][3]** * **[In the current edition: Appendix B — Operators][3]**
* <small>[In the first edition: Ch 6 — Syntax Index][1]</small> * <small>[In the first edition: Ch 6 — Syntax Index][1]</small>
[1]: https://doc.rust-lang.org/1.30.0/book/first-edition/syntax-index.html
[1]: first-edition/syntax-index.html [2]: appendix-01-keywords.html
[2]: second-edition/appendix-01-keywords.html [3]: appendix-02-operators.html
[3]: second-edition/appendix-02-operators.html

View File

@ -17,9 +17,9 @@ mod tests {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 4.2 — Testing][1]</small>
[1]: first-edition/testing.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/testing.html
[2]: second-edition/ch11-00-testing.html [2]: ch11-00-testing.html

View File

@ -60,9 +60,9 @@ fn main() {
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.22 — Trait Objects][1]</small>
[1]: first-edition/trait-objects.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/trait-objects.html
[2]: second-edition/ch17-02-trait-objects.html [2]: ch17-02-trait-objects.html

View File

@ -14,11 +14,11 @@ pub trait Summarizable {
Here are the relevant sections in the new and old books: Here are the relevant sections in the new and old books:
* **[In the second edition: Ch 10.02 — Traits][2]** * **[in the current edition: Ch 10.02 — Traits][2]**
* [In the second edition: Ch 19.03 — Advanced Traits][3] * [in the current edition: Ch 19.03 — Advanced Traits][3]
* <small>[In the first edition: Ch 3.19 — Traits][1]</small> * <small>[In the first edition: Ch 3.19 — Traits][1]</small>
[1]: first-edition/traits.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/traits.html
[2]: second-edition/ch10-02-traits.html [2]: ch10-02-traits.html
[3]: second-edition/ch19-03-advanced-traits.html [3]: ch19-03-advanced-traits.html

View File

@ -8,11 +8,11 @@
Here are the relevant sections in the new and old books: 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] * [The Rustonomicon, The Dark Arts of Advanced and Unsafe Rust Programming][3]
* <small>[In the first edition: Ch 3.36 — `unsafe`][1]</small> * <small>[In the first edition: Ch 3.36 — `unsafe`][1]</small>
[1]: first-edition/unsafe.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/unsafe.html
[2]: second-edition/ch19-01-unsafe-rust.html [2]: ch19-01-unsafe-rust.html
[3]: ../nomicon/index.html [3]: ../nomicon/index.html

View File

@ -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> * <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 [2]: ../unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib

View File

@ -14,10 +14,10 @@ let numbers = vec![1, 2, 3];
Here are the relevant sections in the new and old books: 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> * <small>[In the first edition: Ch 3.7 — Vectors][1]</small>
[1]: first-edition/vectors.html [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/vectors.html
[2]: second-edition/ch08-01-vectors.html [2]: ch08-01-vectors.html

View File

@ -15,7 +15,7 @@ library that you can use with `derive`. Each section covers:
* Examples of operations that require the trait * Examples of operations that require the trait
If you want different behavior than that provided by the `derive` attribute, 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. for each trait for details of how to manually implement them.
The rest of the traits defined in the standard library cant be implemented on The rest of the traits defined in the standard library cant be implemented on

View File

@ -188,4 +188,4 @@ doesnt compile.
The source files from which this book is generated can be found on The source files from which this book is generated can be found on
[GitHub][book]. [GitHub][book].
[book]: https://github.com/rust-lang/book/tree/master/2018-edition/src [book]: https://github.com/rust-lang/book/tree/master/src

View File

@ -35,6 +35,7 @@ Look at the generated *Cargo.toml* file:
name = "guessing_game" name = "guessing_game"
version = "0.1.0" version = "0.1.0"
authors = ["Your Name <you@example.com>"] authors = ["Your Name <you@example.com>"]
edition = "2018"
[dependencies] [dependencies]
``` ```
@ -169,12 +170,12 @@ let mut bar = 5; // mutable
> line. Rust ignores everything in comments, which are discussed in more detail > line. Rust ignores everything in comments, which are discussed in more detail
> in Chapter 3. > in Chapter 3.
Now you know that `let mut guess` will introduce a mutable variable named Let's return to the guessing game program. You now know that `let mut guess`
`guess`. On the other side of the equal sign (`=`) is the value that `guess` is will introduce a mutable variable named `guess`. On the other side of the equal
bound to, which is the result of calling `String::new`, a function that returns sign (`=`) is the value that `guess` is bound to, which is the result of
a new instance of a `String`. [`String`][string]<!-- ignore --> is a string calling `String::new`, a function that returns a new instance of a `String`.
type provided by the standard library that is a growable, UTF-8 encoded bit of [`String`][string]<!-- ignore --> is a string type provided by the standard
text. library that is a growable, UTF-8 encoded bit of text.
[string]: ../std/string/struct.String.html [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. about how or why the operation failed.
The purpose of these `Result` types is to encode error-handling information. 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 Values of the `Result` type, like values of any type, have methods defined on
instance of `io::Result` has an [`expect` method][expect]<!-- ignore --> that them. An instance of `io::Result` has an [`expect` method][expect]<!-- ignore
you can call. If this instance of `io::Result` is an `Err` value, `expect` will --> that you can call. If this instance of `io::Result` is an `Err` value,
cause the program to crash and display the message that you passed as an `expect` will cause the program to crash and display the message that you
argument to `expect`. If the `read_line` method returns an `Err`, it would passed as an argument to `expect`. If the `read_line` method returns an `Err`,
likely be the result of an error coming from the underlying operating system. it would likely be the result of an error coming from the underlying operating
If this instance of `io::Result` is an `Ok` value, `expect` will take the system. If this instance of `io::Result` is an `Ok` value, `expect` will take
return value that `Ok` is holding and return just that value to you so you 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 can use it. In this case, that value is the number of bytes in what the user
entered into standard input. entered into standard input.
@ -302,7 +303,7 @@ Rust warns that you havent used the `Result` value returned from `read_line`,
indicating that the program hasnt handled a possible error. indicating that the program hasnt handled a possible error.
The right way to suppress the warning is to actually write error handling, but 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`. Youll learn about recovering from errors in Chapter 9. `expect`. Youll learn about recovering from errors in Chapter 9.
### Printing Values with `println!` Placeholders ### Printing Values with `println!` Placeholders
@ -392,7 +393,7 @@ version 0.3.14.”
[semver]: http://semver.org [semver]: http://semver.org
Now, without changing any of the code, lets build the project, as shown in Now, without changing any of the code, lets build the project, as shown in
Listing 2-2: Listing 2-2.
```text ```text
$ cargo build $ 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 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 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 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 contains an important bug fix but also contains a regression that will break
your code? your code?
@ -510,7 +511,7 @@ from a number of packages.
### Generating a Random Number ### Generating a Random Number
Now that youve added the `rand` crate to *Cargo.toml*, lets start using Now that youve added the `rand` crate to *Cargo.toml*, lets 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> <span class="filename">Filename: src/main.rs</span>
@ -608,6 +609,7 @@ use std::cmp::Ordering;
use rand::Rng; use rand::Rng;
fn main() { fn main() {
// ---snip--- // ---snip---
println!("You guessed: {}", guess); 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 `Greater`, and `Equal`. These are the three outcomes that are possible when you
compare two values. compare two values.
Then we add five new lines at the bottom that use the `Ordering` type. 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
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 its compared. It takes a reference to whatever you want to compare with: here its
comparing the `guess` to the `secret_number`. Then it returns a variant of the 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 `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 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 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 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.) shadowing in more detail.)
We bind `guess` to the expression `guess.trim().parse()`. The `guess` in the We bind `guess` to the expression `guess.trim().parse()`. The `guess` in the
@ -774,7 +775,7 @@ Lets run the program now!
$ cargo run $ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs Finished dev [unoptimized + debuginfo] target(s) in 0.43 secs
Running `target/guessing_game` Running `target/debug/guessing_game`
Guess the number! Guess the number!
The secret number is: 58 The secret number is: 58
Please input your guess. Please input your guess.
@ -834,7 +835,7 @@ shown here:
$ cargo run $ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 1.50 secs Finished dev [unoptimized + debuginfo] target(s) in 1.50 secs
Running `target/guessing_game` Running `target/debug/guessing_game`
Guess the number! Guess the number!
The secret number is: 59 The secret number is: 59
Please input your guess. Please input your guess.
@ -890,15 +891,29 @@ exiting the program, because the loop is the last part of `main`.
To further refine the games behavior, rather than crashing the program when To further refine the games behavior, rather than crashing the program when
the user inputs a non-number, lets make the game ignore a non-number so the the user inputs a non-number, lets make the game ignore a non-number so the
user can continue guessing. We can do that by altering the line where `guess` 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 ```rust,ignore
// --snip--
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
let guess: u32 = match guess.trim().parse() { let guess: u32 = match guess.trim().parse() {
Ok(num) => num, Ok(num) => num,
Err(_) => continue, 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 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` 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 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 match the `Err(_)` pattern in the second arm. The underscore, `_`, is a
catchall value; in this example, were saying we want to match all `Err` catchall value; in this example, were saying we want to match all `Err`
values, no matter what information they have inside them. So the program will values, no matter what information they have inside them. So the program will
execute the second arms code, `continue`, which means to go to the next execute the second arms code, `continue`, which tells the program to go to the
iteration of the `loop` and ask for another guess. So effectively, the program next iteration of the `loop` and ask for another guess. So effectively, the
ignores all errors that `parse` might encounter! program ignores all errors that `parse` might encounter!
Now everything in the program should work as expected. Lets try it: Now everything in the program should work as expected. Lets try it:
```text ```text
$ cargo run $ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Running `target/guessing_game` Running `target/debug/guessing_game`
Guess the number! Guess the number!
The secret number is: 61 The secret number is: 61
Please input your guess. Please input your guess.
@ -948,7 +963,7 @@ You win!
Awesome! With one tiny final tweak, we will finish the guessing game. Recall 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 that the program is still printing the secret number. That worked well for
testing, but it ruins the game. Lets delete the `println!` that outputs the testing, but it ruins the game. Lets 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> <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 ## Summary
At this point, youve successfully built the guessing game! Congratulations! At this point, youve successfully built the guessing game. Congratulations!
This project was a hands-on way to introduce you to many new Rust concepts: 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 `let`, `match`, methods, associated functions, the use of external crates, and

View File

@ -44,9 +44,9 @@ Even though compiler errors can be frustrating, they only mean your program
isnt safely doing what you want it to do yet; they do *not* mean that youre isnt safely doing what you want it to do yet; they do *not* mean that youre
not a good programmer! Experienced Rustaceans still get compiler errors. 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 The error message indicates that the cause of the error is that you `cannot
to immutable variable x`, because you tried to assign a second value to the assign twice to immutable variable x`, because you tried to assign a second
immutable `x` variable. value to the immutable `x` variable.
Its important that we get compile-time errors when we attempt to change a Its important that we get compile-time errors when we attempt to change a
value that we previously designated as immutable because this very situation 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. computed at runtime.
Heres an example of a constant declaration where the constants name is Heres an example of a constant declaration where the constants name is
`MAX_POINTS` and its value is set to 100,000. (Rusts constant naming `MAX_POINTS` and its value is set to 100,000. (Rusts naming convention for
convention is to use all uppercase with underscores between words, constants is to use all uppercase with underscores between words, and
and underscores can be inserted in numeric literals to improve readability): underscores can be inserted in numeric literals to improve readability):
```rust ```rust
const MAX_POINTS: u32 = 100_000; const MAX_POINTS: u32 = 100_000;
@ -147,13 +147,13 @@ hardcoded value needed to be updated in the future.
### Shadowing ### Shadowing
As you saw in the “Comparing the Guess to the Secret Number” section in Chapter As you saw in the guessing game tutorial in the “Comparing the Guess to the
2, you can declare a new variable with the same name as a previous variable, Secret Number” section in Chapter 2, you can declare a new variable with the
and the new variable shadows the previous variable. Rustaceans say that the same name as a previous variable, and the new variable shadows the previous
first variable is *shadowed* by the second, which means that the second variable. Rustaceans say that the first variable is *shadowed* by the second,
variables value is what appears when the variable is used. We can shadow a which means that the second variables value is what appears when the variable
variable by using the same variables name and repeating the use of the `let` is used. We can shadow a variable by using the same variables name and
keyword as follows: repeating the use of the `let` keyword as follows:
<span class="filename">Filename: src/main.rs</span> <span class="filename">Filename: src/main.rs</span>

View File

@ -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. Well cover how `if` expressions work in Rust in the “Control Flow” expression. Well cover how `if` expressions work in Rust in the “Control Flow”
section. section.
@ -302,7 +302,7 @@ fn main() {
``` ```
Arrays are useful when you want your data allocated on the stack rather than 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 isnt you want to ensure you always have a fixed number of elements. An array isnt
as flexible as the vector type, though. A vector is a similar collection type 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. provided by the standard library that *is* allowed to grow or shrink in size.

View File

@ -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 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. 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 Function bodies are made up of a series of statements optionally ending in an
expression. So far, weve only covered functions without an ending expression, expression. So far, weve 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. expression-based language, this is an important distinction to understand.
Other languages dont have the same distinctions, so lets look at what Other languages dont have the same distinctions, so lets look at what
statements and expressions are and how their differences affect the bodies of statements and expressions are and how their differences affect the bodies of
functions. functions.
### Statements and Expressions
Weve actually already used statements and expressions. *Statements* are Weve actually already used statements and expressions. *Statements* are
instructions that perform some action and do not return a value. *Expressions* instructions that perform some action and do not return a value. *Expressions*
evaluate to a resulting value. Lets look at some examples. evaluate to a resulting value. Lets look at some examples.
Creating a variable and assigning a value to it with the `let` keyword is a 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> <span class="filename">Filename: src/main.rs</span>

View File

@ -8,7 +8,7 @@ reading the source code may find useful.
Heres a simple comment: Heres a simple comment:
```rust ```rust
// Hello, world. // hello, world
``` ```
In Rust, comments must start with two slashes and continue until the end of the 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 ```rust
fn main() { fn main() {
let lucky_number = 7; // Im feeling lucky today. let lucky_number = 7; // Im feeling lucky today
} }
``` ```
@ -38,7 +38,7 @@ separate line above the code its annotating:
```rust ```rust
fn main() { fn main() {
// Im feeling lucky today. // Im feeling lucky today
let lucky_number = 7; let lucky_number = 7;
} }
``` ```

View File

@ -74,7 +74,8 @@ condition was false
``` ```
Its also worth noting that the condition in this code *must* be a `bool`. If Its also worth noting that the condition in this code *must* be a `bool`. If
the condition isnt a `bool`, well get an error. For example: the condition isnt a `bool`, well get an error. For example, try running the
following code:
<span class="filename">Filename: src/main.rs</span> <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 #### Using `if` in a `let` Statement
Because `if` is an expression, we can use it on the right side of a `let` 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> <span class="filename">Filename: src/main.rs</span>
@ -226,9 +227,9 @@ fn main() {
} }
``` ```
When we try to compile this code, well get an error. The `if` and `else` arms have When we try to compile this code, well get an error. The `if` and `else` arms
value types that are incompatible, and Rust indicates exactly where to find the have value types that are incompatible, and Rust indicates exactly where to
problem in the program: find the problem in the program:
```text ```text
error[E0308]: if and else have incompatible types 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. 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 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 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 “Quitting After a Correct Guess” section of Chapter 2 to exit the program when
program when the user won the game by guessing the correct number. the user won the game by guessing the correct number.
#### Returning from loops #### Returning from loops
@ -372,7 +372,7 @@ true, the code runs; otherwise, it exits the loop.
#### Looping Through a Collection with `for` #### Looping Through a Collection with `for`
You could use the `while` construct to loop over the elements of a collection, You could use the `while` construct to loop over the elements of a collection,
such as an array. For example, lets look at Listing 3-4: such as an array. For example, lets look at Listing 3-4.
<span class="filename">Filename: src/main.rs</span> <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. through the loop.
As a more concise alternative, you can use a `for` loop and execute some code 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> <span class="filename">Filename: src/main.rs</span>

View File

@ -87,9 +87,9 @@ strings.
First, lets take a look at the ownership rules. Keep these rules in mind as we First, lets take a look at the ownership rules. Keep these rules in mind as we
work through the examples that illustrate them: work through the examples that illustrate them:
> 1. Each value in Rust has a variable thats called its *owner*. * Each value in Rust has a variable thats called its *owner*.
> 2. There can only be one owner at a time. * There can only be one owner at a time.
> 3. When the owner goes out of scope, the value will be dropped. * When the owner goes out of scope, the value will be dropped.
### Variable Scope ### Variable Scope
@ -111,7 +111,7 @@ let s = "hello";
The variable `s` refers to a string literal, where the value of the string is 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 hardcoded into the text of our program. The variable is valid from the point at
which its declared until the end of the current *scope*. Listing 4-1 has which its 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 ```rust
{ // s is not valid here, its not yet declared { // s is not valid here, its 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 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`, of scope, Rust calls a special function for us. This function is called `drop`,
and its where the author of `String` can put the code to return the memory. and its 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 items > Note: In C++, this pattern of deallocating resources at the end of an items
> lifetime is sometimes called *Resource Acquisition Is Initialization (RAII)*. > lifetime is sometimes called *Resource Acquisition Is Initialization (RAII)*.
@ -241,7 +241,7 @@ weve allocated on the heap. Lets explore some of those situations now.
#### Ways Variables and Data Interact: Move #### Ways Variables and Data Interact: Move
Multiple variables can interact with the same data in different ways in Rust. Multiple variables can interact with the same data in different ways in Rust.
Lets look at an example using an integer in Listing 4-2: Lets look at an example using an integer in Listing 4-2.
```rust ```rust
let x = 5; let x = 5;
@ -347,7 +347,7 @@ If youve heard the terms *shallow copy* and *deep copy* while working with
other languages, the concept of copying the pointer, length, and capacity other languages, the concept of copying the pointer, length, and capacity
without copying the data probably sounds like making a shallow copy. But without copying the data probably sounds like making a shallow copy. But
because Rust also invalidates the first variable, instead of being called a because Rust also invalidates the first variable, instead of being called a
shallow copy, its known as a *move*. Here we would read this by saying that shallow copy, its 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. `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%;" /> <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 #### Stack-Only Data: Copy
Theres another wrinkle we havent talked about yet. This code using integers, Theres another wrinkle we havent 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 ```rust
let x = 5; 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 wont let us annotate a type with the `Copy` usable after assignment. Rust wont let us annotate a type with the `Copy`
trait if the type, or any of its parts, has implemented the `Drop` trait. If 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 the type needs something special to happen when the value goes out of scope and
we add the `Copy` annotation to that type, well get a compile time error. To we add the `Copy` annotation to that type, well get a compile-time error. To
learn about how to add the `Copy` annotation to your type, see “Derivable learn about how to add the `Copy` annotation to your type, see “Derivable
Traits” in Appendix C. 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 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 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 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> <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> annotated</span>
If we tried to use `s` after the call to `takes_ownership`, Rust would throw a 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 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. the ownership rules prevent you from doing so.
### Return Values and Scope ### Return Values and Scope
Returning values can also transfer ownership. Listing 4-4 is an example with 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> <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 some_string // some_string is returned and
// moves out to the calling // 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 fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
// scope // scope
@ -525,7 +525,7 @@ Its 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 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. function that we might want to return as well.
Its possible to return multiple values using a tuple, as shown in Listing 4-5: Its possible to return multiple values using a tuple, as shown in Listing 4-5.
<span class="filename">Filename: src/main.rs</span> <span class="filename">Filename: src/main.rs</span>

View File

@ -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 reference with `&mut s` and accept a mutable reference with `some_string: &mut
String`. 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 reference to a particular piece of data in a particular scope. This code will
fail: fail:
@ -264,7 +264,7 @@ Heres the error:
```text ```text
error[E0106]: missing lifetime specifier error[E0106]: missing lifetime specifier
--> dangle.rs:5:16 --> main.rs:5:16
| |
5 | fn dangle() -> &String { 5 | fn dangle() -> &String {
| ^ expected lifetime parameter | ^ expected lifetime parameter
@ -274,10 +274,9 @@ error[E0106]: missing lifetime specifier
= help: consider giving it a 'static lifetime = help: consider giving it a 'static lifetime
``` ```
This error message refers to a feature we havent covered yet: *lifetimes*. This error message refers to a feature we havent covered yet: lifetimes. Well
Well discuss lifetimes in detail in Chapter 10. But, if you disregard the discuss lifetimes in detail in Chapter 10. But, if you disregard the parts
parts about lifetimes, the message does contain the key to why this code is a about lifetimes, the message does contain the key to why this code is a problem:
problem:
```text ```text
this function's return type contains a borrowed value, but there is no value this function's return type contains a borrowed value, but there is no value
@ -319,8 +318,8 @@ deallocated.
Lets recap what weve discussed about references: Lets recap what weve discussed about references:
* At any given time, you can have *either* (but not both of) one mutable * At any given time, you can have *either* one mutable reference *or* any
reference or any number of immutable references. number of immutable references.
* References must always be valid. * References must always be valid.
Next, well look at a different kind of reference: slices. Next, well look at a different kind of reference: slices.

View File

@ -18,7 +18,7 @@ fn first_word(s: &String) -> ?
This function, `first_word`, has a `&String` as a parameter. We dont want This function, `first_word`, has a `&String` as a parameter. We dont want
ownership, so this is fine. But what should we return? We dont really have a ownership, so this is fine. But what should we return? We dont really have a
way to talk about *part* of a string. However, we could return the index of the way to talk about *part* of a string. However, we could return the index of the
end of the word. Lets try that, as shown in Listing 4-7: end of the word. Lets try that, as shown in Listing 4-7.
<span class="filename">Filename: src/main.rs</span> <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; return i;
} }
} }
s.len() s.len()
``` ```
@ -83,7 +84,7 @@ string, but theres a problem. Were returning a `usize` on its own, but it
only a meaningful number in the context of the `&String`. In other words, only a meaningful number in the context of the `&String`. In other words,
because its a separate value from the `String`, theres no guarantee that it because its a separate value from the `String`, theres no guarantee that it
will still be valid in the future. Consider the program in Listing 4-8 that 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> <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 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 // 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! // 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 slice. Internally, the slice data structure stores the starting position and
the length of the slice, which corresponds to `ending_index` minus 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 `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. 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 > 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 > 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 > 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 > more thorough discussion of UTF-8 handling is in the “Storing UTF-8 Encoded
> Chapter 8. > Text with Strings” section of Chapter 8.
With all this information in mind, lets rewrite `first_word` to return a With all this information in mind, lets rewrite `first_word` to return a
slice. The type that signifies “string slice” is written as `&str`: slice. The type that signifies “string slice” is written as `&str`:
@ -261,7 +262,7 @@ logically incorrect but didnt show any immediate errors. The problems would
show up later if we kept trying to use the first word index with an emptied 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 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 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> <span class="filename">Filename: src/main.rs</span>
@ -271,7 +272,7 @@ fn main() {
let word = first_word(&s); let word = first_word(&s);
s.clear(); // Error! s.clear(); // error!
println!("the first word is: {}", word); println!("the first word is: {}", word);
} }
@ -286,7 +287,7 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta
8 | let word = first_word(&s); 8 | let word = first_word(&s);
| -- immutable borrow occurs here | -- immutable borrow occurs here
9 | 9 |
10 | s.clear(); // Error! 10 | s.clear(); // error!
| ^^^^^^^^^ mutable borrow occurs here | ^^^^^^^^^ mutable borrow occurs here
11 | 11 |
12 | println!("the first word is: {}", word); 12 | println!("the first word is: {}", word);
@ -314,20 +315,24 @@ immutable reference.
#### String Slices as Parameters #### String Slices as Parameters
Knowing that you can take slices of literals and `String`s leads us to one more Knowing that you can take slices of literals and `String` values leads us to
improvement on `first_word`, and thats its signature: one more improvement on `first_word`, and thats its signature:
```rust,ignore ```rust,ignore
fn first_word(s: &String) -> &str { fn first_word(s: &String) -> &str {
``` ```
A more experienced Rustacean would write the following line instead because it A more experienced Rustacean would write the signature shown in Listing 4-9
allows us to use the same function on both `String`s and `&str`s: instead because it allows us to use the same function on both `String` values
and `&str` values.
```rust,ignore ```rust,ignore
fn first_word(s: &str) -> &str { 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 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 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 slice instead of a reference to a `String` makes our API more general and useful

View File

@ -10,7 +10,7 @@ To define a struct, we enter the keyword `struct` and name the entire struct. A
structs name should describe the significance of the pieces of data being structs name should describe the significance of the pieces of data being
grouped together. Then, inside curly brackets, we define the names and types of 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 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 ```rust
struct User { struct User {
@ -31,7 +31,7 @@ data we want to store in those fields. We dont have to specify the fields in
the same order in which we declared them in the struct. In other words, the 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 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 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 ```rust
# struct User { # struct User {
@ -56,7 +56,7 @@ To get a specific value from a struct, we can use dot notation. If we wanted
just this users email address, we could use `user1.email` wherever we wanted just this users 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 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 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 ```rust
# struct User { # struct User {
@ -80,10 +80,10 @@ user1.email = String::from("anotheremail@example.com");
`User` instance</span> `User` instance</span>
Note that the entire instance must be mutable; Rust doesnt allow us to mark Note that the entire instance must be mutable; Rust doesnt 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 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 given email and username. The `active` field gets the value of `true`, and
the `sign_in_count` gets a value of `1`. the `sign_in_count` gets a value of `1`.
@ -119,7 +119,7 @@ would get even more annoying. Luckily, theres a convenient shorthand!
Because the parameter names and the struct field names are exactly the same in 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 Listing 5-4, we can use the *field init shorthand* syntax to rewrite
`build_user` so that it behaves exactly the same but doesnt have the `build_user` so that it behaves exactly the same but doesnt 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 ```rust
# struct User { # struct User {
@ -156,7 +156,7 @@ instances values but changes some. Youll do this using *struct update synt
First, Listing 5-6 shows how we create a new `User` instance in `user2` without 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 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 ```rust
# struct User { # 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 different value for `email` and `username` but has the same values for the
`active` and `sign_in_count` fields from `user1`. `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 You can also define structs that look similar to tuples, called *tuple
structs*. Tuple structs have the added meaning the struct name provides but 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 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. 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 followed by the types in the tuple. For example, here are definitions and
usages of two tuple structs named `Color` and `Point`: usages of two tuple structs named `Color` and `Point`:

View File

@ -7,7 +7,7 @@ refactor the program until were using structs instead.
Lets make a new binary project with Cargo called *rectangles* that will take Lets 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 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 of the rectangle. Listing 5-8 shows a short program with one way of doing
exactly that in our projects *src/main.rs*: exactly that in our projects *src/main.rs*.
<span class="filename">Filename: src/main.rs</span> <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 ### 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> <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 use structs to add meaning by labeling the data. We can transform the tuple
were using into a data type with a name for the whole as well as names for the were 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> <span class="filename">Filename: src/main.rs</span>
@ -144,7 +144,7 @@ and `1`. This is a win for clarity.
Itd be nice to be able to print an instance of `Rectangle` while were Itd be nice to be able to print an instance of `Rectangle` while were
debugging our program and see the values for all its fields. Listing 5-11 tries 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 wont using the `println!` macro as we have used in previous chapters. This wont
work, however: work, however.
<span class="filename">Filename: src/main.rs</span> <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 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 brackets tell `println!` to use formatting known as `Display`: output intended
for direct end user consumption. The primitive types weve seen so far for direct end user consumption. The primitive types weve seen so far
implement `Display` by default, because theres only one way youd want to show implement `Display` by default, because theres only one way youd want to show
@ -190,9 +190,9 @@ If we continue reading the errors, well find this helpful note:
Lets try it! The `println!` macro call will now look like `println!("rect1 is Lets try it! The `println!` macro call will now look like `println!("rect1 is
{:?}", rect1);`. Putting the specifier `:?` inside the curly brackets tells {:?}", rect1);`. Putting the specifier `:?` inside the curly brackets tells
`println!` we want to use an output format called `Debug`. `Debug` is a trait `println!` we want to use an output format called `Debug`. The `Debug` trait
that enables us to print our struct in a way that is useful for developers so enables us to print our struct in a way that is useful for developers so we can
we can see its value while were debugging our code. see its value while were debugging our code.
Run the code with this change. Drat! We still get an error: 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 Rust *does* include functionality to print out debugging information, but we
have to explicitly opt in to make that functionality available for our struct. 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 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> <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 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 that can add useful behavior to our custom types. Those traits and their
behaviors are listed in Appendix C, “Derivable Traits.” Well cover how to behaviors are listed in Appendix C. Well cover how to implement these traits
implement these traits with custom behavior as well as how to create your own with custom behavior as well as how to create your own traits in Chapter 10.
traits in Chapter 10.
Our `area` function is very specific: it only computes the area of rectangles. 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` It would be helpful to tie this behavior more closely to our `Rectangle`

View File

@ -12,7 +12,7 @@ instance of the struct the method is being called on.
Lets change the `area` function that has a `Rectangle` instance as a parameter Lets 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 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> <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 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 within `self`; otherwise it should return `false`. That is, we want to be able
to write the program shown in Listing 5-14, once weve defined the `can_hold` to write the program shown in Listing 5-14, once weve defined the `can_hold`
method: method.
<span class="filename">Filename: src/main.rs</span> <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 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`, `self` are both greater than the width and height of the other `Rectangle`,
respectively. Lets add the new `can_hold` method to the `impl` block from respectively. Lets 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> <span class="filename">Filename: src/main.rs</span>
@ -234,7 +234,7 @@ namespaces created by modules. Well discuss modules in Chapter 7.
Each struct is allowed to have multiple `impl` blocks. For example, Listing 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 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 ```rust
# #[derive(Debug)] # #[derive(Debug)]
@ -261,7 +261,7 @@ blocks</span>
Theres no reason to separate these methods into multiple `impl` blocks here, Theres no reason to separate these methods into multiple `impl` blocks here,
but this is valid syntax. Well see a case in which multiple `impl` blocks are but this is valid syntax. Well 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 ## Summary

View File

@ -73,7 +73,7 @@ route(IpAddrKind::V6);
Using enums has even more advantages. Thinking more about our IP address type, Using enums has even more advantages. Thinking more about our IP address type,
at the moment we dont have a way to store the actual IP address *data*; we at the moment we dont 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 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 ```rust
enum IpAddrKind { enum IpAddrKind {
@ -183,7 +183,7 @@ havent brought the standard librarys definition into our scope. Well ta
more about bringing types into scope in Chapter 7. more about bringing types into scope in Chapter 7.
Lets look at another example of an enum in Listing 6-2: this one has a wide Lets 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 ```rust
enum Message { enum Message {
@ -204,7 +204,7 @@ This enum has four variants with different types:
* `Write` includes a single `String`. * `Write` includes a single `String`.
* `ChangeColor` includes three `i32` values. * `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 doesnt use the defining different kinds of struct definitions, except the enum doesnt use the
`struct` keyword and all the variants are grouped together under the `Message` `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 type. The following structs could hold the same data that the preceding enum

View File

@ -17,7 +17,7 @@ the value falls into the associated code block to be used during execution.
Because we just mentioned coins, lets use them as an example using `match`! We Because we just mentioned coins, lets use them as an example using `match`! We
can write a function that can take an unknown United States coin and, in a 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 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 ```rust
enum Coin { 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 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 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 our `enum` by changing the `Quarter` variant to include a `UsState` value stored
inside it, which weve done here in Listing 6-4: inside it, which weve done here in Listing 6-4.
```rust ```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 { enum UsState {
Alabama, Alabama,
Alaska, Alaska,
@ -179,7 +179,7 @@ the function should return the `None` value and not attempt to perform any
operations. operations.
This function is very easy to write, thanks to `match`, and will look like This function is very easy to write, thanks to `match`, and will look like
Listing 6-5: Listing 6-5.
```rust ```rust
fn plus_one(x: Option<i32>) -> Option<i32> { 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 dont
list before the `_` placeholder. list before the `_` placeholder.
However, the `match` expression can be a bit wordy in a situation in which we 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`.

View File

@ -3,7 +3,7 @@
The `if let` syntax lets you combine `if` and `let` into a less verbose way to 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 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 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 ```rust
let some_u8_value = Some(0u8); 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 The syntax `if let` takes a pattern and an expression separated by an equal
works the same way as a `match`, where the expression is given to the `match` sign. It works the same way as a `match`, where the expression is given to the
and the pattern is its first arm. `match` and the pattern is its first arm.
Using `if let` means you have less typing, less indentation, and less Using `if let` means less typing, less indentation, and less boilerplate code.
boilerplate code. However, you lose the exhaustive checking that `match` However, you lose the exhaustive checking that `match` enforces. Choosing
enforces. Choosing between `match` and `if let` depends on what youre doing in between `match` and `if let` depends on what youre doing in your particular
your particular situation and whether gaining conciseness is an appropriate situation and whether gaining conciseness is an appropriate trade-off for
trade-off for losing exhaustive checking. losing exhaustive checking.
In other words, you can think of `if let` as syntax sugar for a `match` that 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. runs code when the value matches one pattern and then ignores all other values.

View File

@ -9,7 +9,7 @@ lines of text in a file or the prices of items in a shopping cart.
### Creating a New Vector ### Creating a New Vector
To create a new, empty vector, we can call the `Vec::new` function, as shown in To create a new, empty vector, we can call the `Vec::new` function, as shown in
Listing 8-1: Listing 8-1.
```rust ```rust
let v: Vec<i32> = Vec::new(); let v: Vec<i32> = Vec::new();
@ -32,7 +32,7 @@ store once you insert values, so you rarely need to do this type annotation.
Its more common to create a `Vec<T>` that has initial values, and Rust Its 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 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 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 ```rust
let v = vec![1, 2, 3]; let v = vec![1, 2, 3];
@ -48,7 +48,7 @@ to modify a vector.
### Updating a Vector ### Updating a Vector
To create a vector and then add elements to it, we can use the `push` method, 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 ```rust
let mut v = Vec::new(); let mut v = Vec::new();
@ -70,7 +70,7 @@ we dont need the `Vec<i32>` annotation.
### Dropping a Vector Drops Its Elements ### Dropping a Vector Drops Its Elements
Like any other `struct`, a vector is freed when it goes out of scope, as 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 ```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, weve annotated the types of the value stored in a vector. In the examples, weve annotated the types of the
values that are returned from these functions for extra clarity. values that are returned from these functions for extra clarity.
Listing 8-5 shows the method of accessing a value in a vector with Listing 8-5 shows both methods of accessing a value in a vector, either with
indexing syntax: indexing syntax or the `get` method.
```rust ```rust
let v = vec![1, 2, 3, 4, 5]; let v = vec![1, 2, 3, 4, 5];
let third: &i32 = &v[2]; let third: &i32 = &v[2];
``` println!("The third element is {}", third);
<span class="caption">Listing 8-5: Using indexing syntax to match v.get(2) {
access an item in a vector</span> Some(third) => println!("The third element is {}", third),
None => println!("There is no third element."),
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); }
} }
``` ```
<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> access an item in a vector</span>
Note two details here. First, we use the index value of `2` to get the third 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 doesnt have an behaves when you try to use an index value that the vector doesnt have an
element for. As an example, lets see what a program will do if it has a vector element for. As an example, lets 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 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 ```rust,should_panic,panics
let v = vec![1, 2, 3, 4, 5]; 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); 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> 100 in a vector containing five elements</span>
When we run this code, the first `[]` method will cause the program to panic 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 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 and any other references to the contents of the vector remain valid. Recall the
rule that states you cant have mutable and immutable references in the same rule that states you cant 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 wont the first element in a vector and try to add an element to the end, which wont
work: work.
```rust,ignore,does_not_compile ```rust,ignore,does_not_compile
let mut v = vec![1, 2, 3, 4, 5]; let mut v = vec![1, 2, 3, 4, 5];
@ -179,7 +169,7 @@ v.push(6);
println!("The first element is: {}", first); 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> while holding a reference to an item</span>
Compiling this code will result in this error: 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 | ----- 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 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 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 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 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 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 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: in a vector of `i32` values and print them.
```rust ```rust
let v = vec![100, 32, 57]; 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> iterating over the elements using a `for` loop</span>
We can also iterate over mutable references to each element in a mutable vector 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 in order to make changes to all the elements. The `for` loop in Listing 8-9
will add `50` to each element: will add `50` to each element.
```rust ```rust
let mut v = vec![100, 32, 57]; let mut v = vec![100, 32, 57];
@ -238,7 +228,7 @@ 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> elements in a vector</span>
To change the value that the mutable reference refers to, we have to use the To change the value that the mutable reference refers to, we have to use the
@ -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 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: 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, that of the enum. Then we can create a vector that holds that enum and so,
ultimately, holds different types. Weve demonstrated this in Listing 8-11: ultimately, holds different types. Weve demonstrated this in Listing 8-10.
```rust ```rust
enum SpreadsheetCell { 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> different types in one vector</span>
Rust needs to know what types will be in the vector at compile time so it knows Rust needs to know what types will be in the vector at compile time so it knows

View File

@ -1,7 +1,7 @@
## Storing UTF-8 Encoded Text with Strings ## Storing UTF-8 Encoded Text with Strings
We talked about strings in Chapter 4, but well look at them in more depth now. We talked about strings in Chapter 4, but well 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: Rusts propensity for exposing possible errors, strings being a more reasons: Rusts propensity for exposing possible errors, strings being a more
complicated data structure than many programmers give them credit for, and complicated data structure than many programmers give them credit for, and
UTF-8. These factors combine in a way that can seem difficult when youre UTF-8. These factors combine in a way that can seem difficult when youre
@ -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` 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 as well, starting with the `new` function to create a string, shown in Listing
8-11: 8-11.
```rust ```rust
let mut s = String::new(); 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, well have some initial data that we want to start the string into. Often, well 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 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 that implements the `Display` trait, as string literals do. Listing 8-12 shows
two examples: two examples.
```rust ```rust
let data = "initial contents"; 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 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 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 ```rust
let s = String::from("initial contents"); 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. `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 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 ```rust
let hello = String::from("السلام عليكم"); 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` #### 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, 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 ```rust
let mut s = String::from("foo"); 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 After these two lines, `s` will contain `foobar`. The `push_str` method takes a
string slice because we dont necessarily want to take ownership of the string slice because we dont necessarily want to take ownership of the
parameter. For example, the code in Listing 8-16 shows that it would be parameter. For example, the code in Listing 8-16 shows that it would be
unfortunate if we werent able to use `s2` after appending its contents to `s1`: unfortunate if we werent able to use `s2` after appending its contents to `s1`.
```rust ```rust
let mut s1 = String::from("foo"); let mut s1 = String::from("foo");
@ -149,8 +149,8 @@ If the `push_str` method took ownership of `s2`, we wouldnt be able to print
its value on the last line. However, this code works as wed expect! its value on the last line. However, this code works as wed expect!
The `push` method takes a single character as a parameter and adds it to the 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 `String`. Listing 8-17 shows code that adds the letter *l* to a `String` using
the `push` method: the `push` method.
```rust ```rust
let mut s = String::from("lo"); 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 #### Concatenation with the `+` Operator or the `format!` Macro
Often, youll want to combine two existing strings. One way is to use the `+` Often, youll 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 ```rust
let s1 = String::from("Hello, "); let s1 = String::from("Hello, ");
let s2 = String::from("world!"); 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 <span class="caption">Listing 8-18: Using the `+` operator to combine two
@ -248,7 +248,7 @@ easier to read and doesnt take ownership of any of its parameters.
In many other programming languages, accessing individual characters in a In many other programming languages, accessing individual characters in a
string by referencing them by index is a valid and common operation. However, 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, youll if you try to access parts of a `String` using indexing syntax in Rust, youll
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 ```rust,ignore,does_not_compile
let s1 = String::from("hello"); 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” 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 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.) Cyrillic letter Ze, not the Arabic number 3.)
```rust ```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 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 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 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 ```rust
for c in "नमस्ते".chars() { for c in "नमस्ते".chars() {

View File

@ -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 You can create an empty hash map with `new` and add elements with `insert`. In
Listing 8-20, were keeping track of the scores of two teams whose names are Listing 8-20, were 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 Blue and Yellow. The Blue team starts with 10 points, and the Yellow team
starts with 50: starts with 50.
```rust ```rust
use std::collections::HashMap; 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 `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 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` 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 ```rust
use std::collections::HashMap; 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 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 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 ```rust
use std::collections::HashMap; use std::collections::HashMap;
@ -105,7 +105,7 @@ the “Validating References with Lifetimes” section in Chapter 10.
### Accessing Values in a Hash Map ### Accessing Values in a Hash Map
We can get a value out of the hash map by providing its key to the `get` 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 ```rust
use std::collections::HashMap; 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. 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 Even though the code in Listing 8-24 calls `insert` twice, the hash map will
only contain one key/value pair because were inserting the value for the Blue only contain one key/value pair because were inserting the value for the Blue
teams key both times: teams key both times.
```rust ```rust
use std::collections::HashMap; use std::collections::HashMap;
@ -192,11 +192,11 @@ overwritten.
Its common to check whether a particular key has a value and, if it doesnt, Its common to check whether a particular key has a value and, if it doesnt,
insert a value for it. Hash maps have a special API for this called `entry` 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 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 `entry` method is an enum called `Entry` that represents a value that might or
or might not exist. Lets say we want to check whether the key for the Yellow might not exist. Lets say we want to check whether the key for the Yellow team
team has a value associated with it. If it doesnt, we want to insert the value has a value associated with it. If it doesnt, we want to insert the value 50,
50, and the same for the Blue team. Using the `entry` API, the code looks like and the same for the Blue team. Using the `entry` API, the code looks like
Listing 8-25: Listing 8-25.
```rust ```rust
use std::collections::HashMap; 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 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 first call to `entry` will insert the key for the Yellow team with the value
`50` because the Yellow team doesnt have a value already. The second call to 50 because the Yellow team doesnt have a value already. The second call to
`entry` will not change the hash map because the Blue team already has the `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 #### 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 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 weve the words as keys and increment the value to keep track of how many times weve
seen that word. If its the first time weve seen a word, well first insert seen that word. If its the first time weve seen a word, well first insert
the value `0`: the value 0.
```rust ```rust
use std::collections::HashMap; use std::collections::HashMap;
@ -261,17 +261,17 @@ loop, so all of these changes are safe and allowed by the borrowing rules.
### Hashing Functions ### Hashing Functions
By default, `HashMap` uses a “cryptographically strong”[^siphash] hashing function that can By default, `HashMap` uses a “cryptographically strong”[^siphash] hashing
provide resistance to Denial of Service (DoS) attacks. This is not the fastest function that can provide resistance to Denial of Service (DoS) attacks. This
hashing algorithm available, but the trade-off for better security that comes is not the fastest hashing algorithm available, but the trade-off for better
with the drop in performance is worth it. If you profile your code and find security that comes with the drop in performance is worth it. If you profile
that the default hash function is too slow for your purposes, you can switch to your code and find that the default hash function is too slow for your
another function by specifying a different *hasher*. A hasher is a type that purposes, you can switch to another function by specifying a different
implements the `BuildHasher` trait. Well talk about traits and how to *hasher*. A hasher is a type that implements the `BuildHasher` trait. Well
implement them in Chapter 10. You dont necessarily have to implement your own talk about traits and how to implement them in Chapter 10. You dont
hasher from scratch; [crates.io](https://crates.io) has libraries shared by necessarily have to implement your own hasher from scratch;
other Rust users that provide hashers implementing many common hashing [crates.io](https://crates.io) has libraries shared by other Rust users that
algorithms. provide hashers implementing many common hashing algorithms.
[^siphash]: [https://www.131002.net/siphash/siphash.pdf](https://www.131002.net/siphash/siphash.pdf) [^siphash]: [https://www.131002.net/siphash/siphash.pdf](https://www.131002.net/siphash/siphash.pdf)

View File

@ -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. note: Run with `RUST_BACKTRACE=1` for a backtrace.
``` ```
The call to `panic!` causes the error message contained in the last two The call to `panic!` causes the error message contained in the last two lines.
lines. The first line shows our panic message and the place in our source code The first line shows our panic message and the place in our source code where
where the panic occurred: *src/main.rs:2:4* indicates that its the second the panic occurred: *src/main.rs:2:4* indicates that its the second line,
line, fourth character of our *src/main.rs* file. 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 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 line, we see the `panic!` macro call. In other cases, the `panic!` call might
@ -64,7 +64,7 @@ backtrace is in more detail next.
Lets look at another example to see what its like when a `panic!` call comes Lets look at another example to see what its like when a `panic!` call comes
from a library because of a bug in our code instead of from our code calling 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 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> <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 <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, were attempting to access the hundredth element of our vector (which is Here, were attempting to access the 100th element of our vector (which is at
at index 99 because indexing starts at zero), but it has only three elements. index 99 because indexing starts at zero), but it has only 3 elements. In this
In this situation, Rust will panic. Using `[]` is supposed to return an situation, Rust will panic. Using `[]` is supposed to return an element, but if
element, but if you pass an invalid index, theres no element that Rust could you pass an invalid index, theres no element that Rust could return here that
return here that would be correct. would be correct.
Other languages, like C, will attempt to give you exactly what you asked for in Other languages, like C, will attempt to give you exactly what you asked for in
this situation, even though it isnt what you want: youll get whatever is at this situation, even though it isnt what you want: youll 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 that called your code. These lines might include core Rust code, standard
library code, or crates that youre using. Lets try getting a backtrace by library code, or crates that youre using. Lets try getting a backtrace by
setting the `RUST_BACKTRACE` environment variable to any value except 0. setting the `RUST_BACKTRACE` environment variable to any value except 0.
Listing 9-2 shows output similar to what youll see: Listing 9-2 shows output similar to what youll see.
```text ```text
$ RUST_BACKTRACE=1 cargo run $ RUST_BACKTRACE=1 cargo run

View File

@ -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. value and error value we want to return may differ.
Lets call a function that returns a `Result` value because the function could Lets 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> <span class="filename">Filename: src/main.rs</span>
@ -43,14 +43,13 @@ fn main() {
<span class="caption">Listing 9-3: Opening a file</span> <span class="caption">Listing 9-3: Opening a file</span>
How do we know `File::open` returns a `Result`? We could look at the How do we know `File::open` returns a `Result`? We could look at the [standard
[standard library API documentation](../std/index.html), library API documentation](../std/index.html)<!-- ignore -->, or we could ask
or we could ask the compiler! If we give `f` a type the compiler! If we give `f` a type annotation that we know is *not* the return
annotation that we know is *not* the return type of the function and then try type of the function and then try to compile the code, the compiler will tell
to compile the code, the compiler will tell us that the types dont match. The us that the types dont match. The error message will then tell us what the
error message will then tell us what the type of `f` *is*. Lets try it! We type of `f` *is*. Lets try it! We know that the return type of `File::open`
know that the return type of `File::open` isnt of type `u32`, so lets change isnt of type `u32`, so lets change the `let f` statement to this:
the `let f` statement to this:
```rust,ignore ```rust,ignore
let f: u32 = File::open("hello.txt"); let f: u32 = File::open("hello.txt");
@ -142,7 +141,7 @@ if `File::open` failed because the file doesnt exist, we want to create the
file and return the handle to the new file. If `File::open` failed for any file and return the handle to the new file. If `File::open` failed for any
other reason—for example, because we didnt have permission to open the file—we other reason—for example, because we didnt 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 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> <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 `io::ErrorKind` is provided by the standard library and has variants
representing the different kinds of errors that might result from an `io` representing the different kinds of errors that might result from an `io`
operation. The variant we want to use is `ErrorKind::NotFound`, which indicates operation. The variant we want to use is `ErrorKind::NotFound`, which indicates
the file were trying to open doesnt exist yet. So, we `match` on `f`, but we the file were trying to open doesnt exist yet. So we `match` on `f`, but we
also then have an inner `match` on `error.kind()`. also have an inner `match` on `error.kind()`.
The condition we want to check in the match guard is whether the value returned 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, 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` 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 cant be opened, a different error message will be printed. The last the file cant 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 arm of the outer `match` stays the same so the program panics on any error
besides the missing file error. besides the missing file error.
Thats a lot of `match`! `match` is very powerful, but also very much a primitive. Thats a lot of `match`! `match` is very powerful, but also very much a
In Chapter 13, well learn about closures. The `Result<T, E>` type has many primitive. In Chapter 13, well learn about closures. The `Result<T, E>` type
methods that accept a closure, and are implemented as `match` statements. A more has many methods that accept a closure, and are implemented as `match`
seasoned Rustacean might write this: expressions. A more seasoned Rustacean might write this:
```rust,ignore ```rust,ignore
use std::fs::File; use std::fs::File;
@ -213,16 +212,15 @@ fn main() {
Come back to this example after youve read Chapter 13, and look up what the Come back to this example after youve read Chapter 13, and look up what the
`map_err` and `unwrap_or_else` methods do in the standard library `map_err` and `unwrap_or_else` methods do in the standard library
documentation. Theres many more of these methods that can clean up huge documentation. Theres many more of these methods that can clean up huge nested
nested `match`es when dealing with errors. Well be looking at some other `match` expressions when dealing with errors.
strategies shortly!
### Shortcuts for Panic on Error: `unwrap` and `expect` ### Shortcuts for Panic on Error: `unwrap` and `expect`
Using `match` works well enough, but it can be a bit verbose and doesnt always Using `match` works well enough, but it can be a bit verbose and doesnt always
communicate intent well. The `Result<T, E>` type has many helper methods 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 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 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 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: call the `panic!` macro for us. Here is an example of `unwrap` in action:

View File

@ -429,6 +429,7 @@ when you created the crate, your description, and a license added, the
name = "guessing_game" name = "guessing_game"
version = "0.1.0" version = "0.1.0"
authors = ["Your Name <you@example.com>"] authors = ["Your Name <you@example.com>"]
edition = "2018"
description = "A fun game where you guess what number the computer has chosen." description = "A fun game where you guess what number the computer has chosen."
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View File

@ -161,12 +161,12 @@ impl<'a, T> LimitTracker<'a, T>
let percentage_of_max = self.value as f64 / self.max as f64; let percentage_of_max = self.value as f64 / self.max as f64;
if percentage_of_max >= 0.75 && percentage_of_max < 0.9 { if percentage_of_max >= 1.0 {
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 {
self.messenger.send("Error: You are over your quota!"); 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!");
} }
} }
} }

View File

@ -175,7 +175,7 @@ fn main() {
separate variables</span> separate variables</span>
This code creates the variables `a` and `b` that match the values of the `x` 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 dont have to match the field names of the struct. But variables in the pattern dont have to match the field names of the struct. But
its common to want the variable names to match the field names to make it its common to want the variable names to match the field names to make it
easier to remember which variables came from which fields. easier to remember which variables came from which fields.

View File

@ -327,12 +327,10 @@ wont compile until we add a definition for the `impl_hello_macro` function.
<span class="filename">Filename: hello_macro_derive/src/lib.rs</span> <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 This usage of `extern crate` is required for the moment with 1.31.0, see:
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/54418 https://github.com/rust-lang/rust/issues/55599
- https://github.com/rust-lang/rust/pull/54658
- https://github.com/rust-lang/rust/issues/55599
--> -->
```rust,ignore ```rust,ignore

View File

@ -248,7 +248,7 @@ impl CtorKind {
} }
impl NonMacroAttrKind { impl NonMacroAttrKind {
fn descr(self) -> &'static str { pub fn descr(self) -> &'static str {
match self { match self {
NonMacroAttrKind::Builtin => "built-in attribute", NonMacroAttrKind::Builtin => "built-in attribute",
NonMacroAttrKind::Tool => "tool attribute", NonMacroAttrKind::Tool => "tool attribute",

View File

@ -334,7 +334,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
continue; 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 { match &result {
&Ok(Some(ref vtable)) => { &Ok(Some(ref vtable)) => {
@ -369,7 +374,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
} }
&Ok(None) => {} &Ok(None) => {}
&Err(SelectionError::Unimplemented) => { &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); already_visited.remove(&pred);
self.add_user_pred( self.add_user_pred(
&mut user_computed_preds, &mut user_computed_preds,
@ -631,18 +636,28 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
finished_map finished_map
} }
pub fn is_of_param(&self, substs: &Substs<'_>) -> bool { fn is_param_no_infer(&self, substs: &Substs<'_>) -> bool {
if substs.is_noop() { return self.is_of_param(substs.type_at(0)) &&
return false; !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::Param(_) => true,
ty::Projection(p) => self.is_of_param(p.substs), ty::Projection(p) => self.is_of_param(p.self_ty()),
_ => false, _ => 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< pub fn evaluate_nested_obligations<
'b, 'b,
'c, 'c,
@ -661,28 +676,77 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
) -> bool { ) -> bool {
let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID); let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID);
for (obligation, predicate) in nested for (obligation, mut predicate) in nested
.filter(|o| o.recursion_depth == 1)
.map(|o| (o.clone(), o.predicate.clone())) .map(|o| (o.clone(), o.predicate.clone()))
{ {
let is_new_pred = let is_new_pred =
fresh_preds.insert(self.clean_pred(select.infcx(), predicate.clone())); 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 { match &predicate {
&ty::Predicate::Trait(ref p) => { &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); self.add_user_pred(computed_preds, predicate);
} }
predicates.push_back(p.clone()); predicates.push_back(p.clone());
} }
&ty::Predicate::Projection(p) => { &ty::Predicate::Projection(p) => {
// If the projection isn't all type vars, then debug!("evaluate_nested_obligations: examining projection predicate {:?}",
// we don't want to add it as a bound predicate);
if self.is_of_param(p.skip_binder().projection_ty.substs) && is_new_pred {
self.add_user_pred(computed_preds, 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 { } 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())) { match poly_project_and_unify_type(select, &obligation.with(p.clone())) {
Err(e) => { Err(e) => {
debug!( debug!(

View File

@ -190,7 +190,26 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
// In the case of a trait predicate, we can skip the "self" type. // 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()) 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::WellFormed(..) |
ty::Predicate::ObjectSafe(..) | ty::Predicate::ObjectSafe(..) |
ty::Predicate::TypeOutlives(..) | ty::Predicate::TypeOutlives(..) |
@ -243,6 +262,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
method: &ty::AssociatedItem) method: &ty::AssociatedItem)
-> Option<MethodViolationCode> -> Option<MethodViolationCode>
{ {
debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite is otherwise // Any method that has a `Self : Sized` requisite is otherwise
// exempt from the regulations. // exempt from the regulations.
if self.generics_require_sized_self(method.def_id) { if self.generics_require_sized_self(method.def_id) {
@ -261,6 +281,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
method: &ty::AssociatedItem) method: &ty::AssociatedItem)
-> bool -> bool
{ {
debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite can't be called. // Any method that has a `Self : Sized` requisite can't be called.
if self.generics_require_sized_self(method.def_id) { if self.generics_require_sized_self(method.def_id) {
return false; return false;
@ -380,6 +401,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
fn receiver_for_self_ty( fn receiver_for_self_ty(
self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
) -> Ty<'tcx> { ) -> Ty<'tcx> {
debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
let substs = Substs::for_item(self, method_def_id, |param, _| { let substs = Substs::for_item(self, method_def_id, |param, _| {
if param.index == 0 { if param.index == 0 {
self_ty.into() 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, /// 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)) let mut associated_types = traits::supertraits(self, ty::Binder::dummy(trait_ref))
.flat_map(|trait_ref| self.associated_items(trait_ref.def_id())) .flat_map(|super_trait_ref| {
.filter(|item| item.kind == ty::AssociatedKind::Type) self.associated_items(super_trait_ref.def_id())
.map(move |item| (super_trait_ref, item))
})
.filter(|(_, item)| item.kind == ty::AssociatedKind::Type)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// existential predicates need to be in a specific order // 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::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, 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( let object_ty = self.mk_dynamic(
ty::Binder::dummy(existential_predicates), // (*) ... binder re-introduced here
ty::Binder::bind(existential_predicates),
lifetime, lifetime,
); );

View File

@ -1754,17 +1754,19 @@ bitflags! {
pub struct AdtFlags: u32 { pub struct AdtFlags: u32 {
const NO_ADT_FLAGS = 0; const NO_ADT_FLAGS = 0;
const IS_ENUM = 1 << 0; const IS_ENUM = 1 << 0;
const IS_PHANTOM_DATA = 1 << 1; const IS_UNION = 1 << 1;
const IS_FUNDAMENTAL = 1 << 2; const IS_STRUCT = 1 << 2;
const IS_UNION = 1 << 3; const HAS_CTOR = 1 << 3;
const IS_BOX = 1 << 4; const IS_PHANTOM_DATA = 1 << 4;
const IS_FUNDAMENTAL = 1 << 5;
const IS_BOX = 1 << 6;
/// Indicates whether the type is an `Arc`. /// Indicates whether the type is an `Arc`.
const IS_ARC = 1 << 5; const IS_ARC = 1 << 7;
/// Indicates whether the type is an `Rc`. /// 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]`. /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
/// (i.e., this flag is never set unless this ADT is an enum). /// (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 { repr: ReprOptions) -> Self {
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
let mut flags = AdtFlags::NO_ADT_FLAGS; 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") { if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
debug!("found non-exhaustive variant list for {:?}", did); debug!("found non-exhaustive variant list for {:?}", did);
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
} }
match kind { flags |= match kind {
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM, AdtKind::Enum => AdtFlags::IS_ENUM,
AdtKind::Union => flags = flags | AdtFlags::IS_UNION, AdtKind::Union => AdtFlags::IS_UNION,
AdtKind::Struct => {} 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 { AdtDef {
did, did,
variants, variants,
@ -2114,25 +2128,25 @@ impl<'a, 'gcx, 'tcx> AdtDef {
#[inline] #[inline]
pub fn is_struct(&self) -> bool { pub fn is_struct(&self) -> bool {
!self.is_union() && !self.is_enum() self.flags.contains(AdtFlags::IS_STRUCT)
} }
#[inline] #[inline]
pub fn is_union(&self) -> bool { pub fn is_union(&self) -> bool {
self.flags.intersects(AdtFlags::IS_UNION) self.flags.contains(AdtFlags::IS_UNION)
} }
#[inline] #[inline]
pub fn is_enum(&self) -> bool { pub fn is_enum(&self) -> bool {
self.flags.intersects(AdtFlags::IS_ENUM) self.flags.contains(AdtFlags::IS_ENUM)
} }
#[inline] #[inline]
pub fn is_variant_list_non_exhaustive(&self) -> bool { 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] #[inline]
pub fn adt_kind(&self) -> AdtKind { pub fn adt_kind(&self) -> AdtKind {
if self.is_enum() { 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. /// of coherence checking.
#[inline] #[inline]
pub fn is_fundamental(&self) -> bool { 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>. /// Returns `true` if this is PhantomData<T>.
#[inline] #[inline]
pub fn is_phantom_data(&self) -> bool { 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>`. /// Returns `true` if this is `Arc<T>`.
pub fn is_arc(&self) -> bool { 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>`. /// Returns `true` if this is `Rc<T>`.
pub fn is_rc(&self) -> bool { 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>. /// Returns `true` if this is Box<T>.
#[inline] #[inline]
pub fn is_box(&self) -> bool { 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. /// Returns whether this type has a destructor.

View File

@ -16,7 +16,7 @@ num_cpus = "1.0"
rustc-demangle = "0.1.4" rustc-demangle = "0.1.4"
memmap = "0.6" memmap = "0.6"
log = "0.4.5" log = "0.4.5"
libc = "0.2.43" libc = "0.2.44"
jobserver = "0.1.11" jobserver = "0.1.11"
serialize = { path = "../libserialize" } serialize = { path = "../libserialize" }

View File

@ -335,11 +335,20 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
bx: &mut Bx, bx: &mut Bx,
llindex: V llindex: V
) -> Self { ) -> 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 { PlaceRef {
llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]), llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]),
llextra: None, llextra: None,
layout: self.layout.field(bx.cx(), 0), layout,
align: self.align align: self.align.restrict_for_offset(offset),
} }
} }

View File

@ -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); let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb()); 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, 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)]); let next = body_bx.inbounds_gep(current, &[bx.cx().const_usize(1)]);
body_bx.br(header_bx.llbb()); body_bx.br(header_bx.llbb());

View File

@ -1415,7 +1415,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
self.check_call_dest(mir, term, &sig, destination, term_location); self.check_call_dest(mir, term, &sig, destination, term_location);
self.prove_predicates( 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(), term_location.to_locations(),
ConstraintCategory::Boring, ConstraintCategory::Boring,
); );

View File

@ -86,7 +86,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
type MemoryExtra: Default; type MemoryExtra: Default;
/// Extra data stored in every allocation. /// 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 /// Memory's allocation map
type MemoryMap: type MemoryMap:

View File

@ -708,8 +708,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
relocations relocations
.iter() .iter()
.map(|&(offset, reloc)| { .map(|&(offset, reloc)| {
(offset + dest.offset - src.offset + (i * size * relocations.len() as u64), // compute offset for current repetition
reloc) let dest_offset = dest.offset + (i * size);
(
// shift offsets from source allocation to destination allocation
offset + dest_offset - src.offset,
reloc,
)
}) })
); );
} }

View File

@ -517,7 +517,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
// Only allow statics (not consts) to refer to other statics. // Only allow statics (not consts) to refer to other statics.
if self.mode == Mode::Static || self.mode == Mode::StaticMut { 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 // this is not strictly necessary as miri will also bail out
// For interior mutability we can't really catch this statically as that // For interior mutability we can't really catch this statically as that
// goes through raw pointers and intermediate temporaries, so miri has // goes through raw pointers and intermediate temporaries, so miri has

View File

@ -230,13 +230,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
} }
let subclass = SingleImport { let subclass = SingleImport {
target: ident,
source: source.ident, source: source.ident,
result: PerNS { target: ident,
source_bindings: PerNS {
type_ns: Cell::new(Err(Undetermined)), type_ns: Cell::new(Err(Undetermined)),
value_ns: Cell::new(Err(Undetermined)), value_ns: Cell::new(Err(Undetermined)),
macro_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, type_ns_only,
}; };
self.add_import_directive( self.add_import_directive(

View File

@ -75,7 +75,7 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::{cmp, fmt, iter, ptr}; use std::{cmp, fmt, iter, mem, ptr};
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::mem::replace; use std::mem::replace;
use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::ptr_key::PtrKey;
@ -1022,11 +1022,11 @@ enum ModuleOrUniformRoot<'a> {
CurrentScope, CurrentScope,
} }
impl<'a> PartialEq for ModuleOrUniformRoot<'a> { impl ModuleOrUniformRoot<'_> {
fn eq(&self, other: &Self) -> bool { fn same_def(lhs: Self, rhs: Self) -> bool {
match (*self, *other) { match (lhs, rhs) {
(ModuleOrUniformRoot::Module(lhs), (ModuleOrUniformRoot::Module(lhs),
ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs), ModuleOrUniformRoot::Module(rhs)) => lhs.def() == rhs.def(),
(ModuleOrUniformRoot::CrateRootAndExternPrelude, (ModuleOrUniformRoot::CrateRootAndExternPrelude,
ModuleOrUniformRoot::CrateRootAndExternPrelude) | ModuleOrUniformRoot::CrateRootAndExternPrelude) |
(ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) | (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. /// FIXME: Refactor things so that this is passed through arguments and not resolver.
last_import_segment: bool, last_import_segment: bool,
blacklisted_binding: Option<&'a NameBinding<'a>>,
/// The idents for the primitive types. /// The idents for the primitive types.
primitive_type_table: PrimitiveTypeTable, primitive_type_table: PrimitiveTypeTable,
@ -1871,6 +1872,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
current_self_type: None, current_self_type: None,
current_self_item: None, current_self_item: None,
last_import_segment: false, last_import_segment: false,
blacklisted_binding: None,
primitive_type_table: PrimitiveTypeTable::new(), 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][..], ast::UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..],
_ => &[TypeNS], _ => &[TypeNS],
}; };
for &ns in nss { let report_error = |this: &Self, ns| {
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" }; let what = if ns == TypeNS { "type parameters" } else { "local variables" };
self.session.span_err(ident.span, &format!("imports cannot refer to {}", what)); this.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
};
for &ns in nss {
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 { } 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)); module = Some(ModuleOrUniformRoot::Module(next_module));
record_segment_def(self, def); record_segment_def(self, def);
} else if def == Def::ToolMod && i + 1 != path.len() { } 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); let def = Def::NonMacroAttr(NonMacroAttrKind::Tool);
return PathResult::NonModule(PathResolution::new(def)); return PathResult::NonModule(PathResolution::new(def));
} else if def == Def::Err { } else if def == Def::Err {

View File

@ -499,6 +499,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
.push((path, path_span, kind, parent_scope.clone(), def.ok())); .push((path, path_span, kind, parent_scope.clone(), def.ok()));
} }
self.prohibit_imported_non_macro_attrs(None, def.ok(), path_span);
def def
} else { } else {
let binding = self.early_resolve_ident_in_lexical_scope( 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())); .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,13 +956,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
// but its `Def` should coincide with a crate passed with `--extern` // 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. // (otherwise there would be ambiguity) and we can skip feature error in this case.
'ok: { 'ok: {
if !is_import || self.session.features_untracked().uniform_paths { if !is_import || !rust_2015 {
break 'ok; break 'ok;
} }
if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() { if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
break 'ok; break 'ok;
} }
if rust_2015 {
let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span); let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span);
let root_module = self.resolve_crate_root(root_ident); let root_module = self.resolve_crate_root(root_ident);
if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module), if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
@ -967,22 +969,21 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
.is_ok() { .is_ok() {
break '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, let what = self.binding_description(binding, ident,
flags.contains(Flags::MISC_FROM_PRELUDE)); flags.contains(Flags::MISC_FROM_PRELUDE));
let note_msg = format!("this import refers to {what}", what = what); 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(&note_msg); err.note(&note_msg);
ident.span
} else { } else {
err.span_note(binding.span, &note_msg); err.span_note(binding.span, &note_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(); 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, fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
err: &mut DiagnosticBuilder<'a>, span: Span) { err: &mut DiagnosticBuilder<'a>, span: Span) {
// First check if this is a locally-defined bang macro. // First check if this is a locally-defined bang macro.
@ -1187,7 +1202,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let ident = ident.modern(); let ident = ident.modern();
self.macro_names.insert(ident); self.macro_names.insert(ident);
let def = Def::Macro(def_id, MacroKind::Bang); 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); let binding = (def, vis, item.span, expansion).to_name_binding(self.arenas);
self.set_binding_parent_module(binding, self.current_module); self.set_binding_parent_module(binding, self.current_module);
let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding { 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); *current_legacy_scope = LegacyScope::Binding(legacy_binding);
self.all_macros.insert(ident.name, def); 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 module = self.graph_root;
let vis = ty::Visibility::Public;
self.define(module, ident, MacroNS, self.define(module, ident, MacroNS,
(def, vis, item.span, expansion, IsMacroExport)); (def, vis, item.span, expansion, IsMacroExport));
} else { } else {

View File

@ -42,9 +42,10 @@ use std::{mem, ptr};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ImportDirectiveSubclass<'a> { pub enum ImportDirectiveSubclass<'a> {
SingleImport { SingleImport {
target: Ident,
source: 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, type_ns_only: bool,
}, },
GlobImport { GlobImport {
@ -227,6 +228,11 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
} }
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { 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, // `extern crate` are always usable for backwards compatibility, see issue #37020,
// remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`. // remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`.
let usable = this.is_accessible(binding.vis) || binding.is_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 { 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() { if self.last_import_segment && check_usable(self, binding).is_err() {
Err((Determined, Weak::No)) Err((Determined, Weak::No))
} else { } else {
@ -465,6 +482,10 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
self.set_binding_parent_module(binding, module); self.set_binding_parent_module(binding, module);
self.update_resolution(module, ident, ns, |this, resolution| { self.update_resolution(module, ident, ns, |this, resolution| {
if let Some(old_binding) = resolution.binding { 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()) { match (old_binding.is_glob_import(), binding.is_glob_import()) {
(true, true) => { (true, true) => {
if binding.def() != old_binding.def() { 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) { if let Some((span, err, note)) = self.finalize_import(import) {
errors = true; errors = true;
if let SingleImport { source, ref result, .. } = import.subclass { if let SingleImport { source, ref source_bindings, .. } = import.subclass {
if source.name == "self" { if source.name == "self" {
// Silence `unresolved import` error if E0429 is already emitted // 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; continue;
} }
} }
@ -765,9 +786,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}; };
directive.imported_module.set(Some(module)); directive.imported_module.set(Some(module));
let (source, target, result, type_ns_only) = match directive.subclass { let (source, target, source_bindings, target_bindings, type_ns_only) =
SingleImport { source, target, ref result, type_ns_only } => match directive.subclass {
(source, target, result, type_ns_only), SingleImport { source, target, ref source_bindings,
ref target_bindings, type_ns_only } =>
(source, target, source_bindings, target_bindings, type_ns_only),
GlobImport { .. } => { GlobImport { .. } => {
self.resolve_glob_import(directive); self.resolve_glob_import(directive);
return true; return true;
@ -777,7 +800,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
let mut indeterminate = false; let mut indeterminate = false;
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { 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 // For better failure detection, pretend that the import will
// not define any names while resolving its module path. // not define any names while resolving its module path.
let orig_vis = directive.vis.replace(ty::Visibility::Invisible); 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); directive.vis.set(orig_vis);
result[ns].set(binding); source_bindings[ns].set(binding);
} else { } else {
return return
}; };
let parent = directive.parent_scope.module; let parent = directive.parent_scope.module;
match result[ns].get() { match source_bindings[ns].get() {
Err(Undetermined) => indeterminate = true, Err(Undetermined) => indeterminate = true,
Err(Determined) => { Err(Determined) => {
this.update_resolution(parent, target, ns, |_, resolution| { this.update_resolution(parent, target, ns, |_, resolution| {
@ -810,6 +833,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
} }
Ok(binding) => { Ok(binding) => {
let imported_binding = this.import(binding, directive); let imported_binding = this.import(binding, directive);
target_bindings[ns].set(Some(imported_binding));
let conflict = this.try_define(parent, target, ns, imported_binding); let conflict = this.try_define(parent, target, ns, imported_binding);
if let Err(old_binding) = conflict { if let Err(old_binding) = conflict {
this.report_conflict(parent, target, ns, imported_binding, old_binding); 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) => { PathResult::Module(module) => {
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`. // Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
if let Some(initial_module) = directive.imported_module.get() { 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"); span_bug!(directive.span, "inconsistent resolution for an import");
} }
} else { } else {
@ -879,8 +905,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
}; };
let (ident, result, type_ns_only) = match directive.subclass { let (ident, source_bindings, target_bindings, type_ns_only) = match directive.subclass {
SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only), 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 } => { GlobImport { is_prelude, ref max_vis } => {
if directive.module_path.len() <= 1 { if directive.module_path.len() <= 1 {
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 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; let mut all_ns_err = true;
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
let orig_vis = directive.vis.replace(ty::Visibility::Invisible); 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 orig_last_import_segment = mem::replace(&mut this.last_import_segment, true);
let binding = this.resolve_ident_in_module( let binding = this.resolve_ident_in_module(
module, ident, ns, Some(&directive.parent_scope), true, directive.span module, ident, ns, Some(&directive.parent_scope), true, directive.span
); );
this.last_import_segment = orig_last_import_segment; this.last_import_segment = orig_last_import_segment;
this.blacklisted_binding = orig_blacklisted_binding;
directive.vis.set(orig_vis); directive.vis.set(orig_vis);
match binding { match binding {
Ok(binding) => { Ok(binding) => {
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`. // 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; all_ns_err = false;
this.record_use(ident, ns, initial_binding, this.record_use(ident, ns, initial_binding,
directive.module_path.is_empty()); 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 reexport_error = None;
let mut any_successful_reexport = false; let mut any_successful_reexport = false;
self.per_ns(|this, ns| { 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(); let vis = directive.vis.get();
if !binding.pseudo_vis().is_at_least(vis, &*this) { if !binding.pseudo_vis().is_at_least(vis, &*this) {
reexport_error = Some((ns, binding)); 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(); let mut full_path = directive.module_path.clone();
full_path.push(Segment::from_ident(ident)); full_path.push(Segment::from_ident(ident));
self.per_ns(|this, ns| { 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( this.lint_if_path_starts_with_module(
directive.crate_lint(), directive.crate_lint(),
&full_path, &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, // Record what this import resolves to for later uses in documentation,
// this may resolve to either a value or a type, but for 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. // 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(); let mut def = binding.def();
if let Def::Macro(def_id, _) = def { if let Def::Macro(def_id, _) = def {
// `DefId`s from the "built-in macro crate" should not leak from resolve because // `DefId`s from the "built-in macro crate" should not leak from resolve because

View File

@ -1013,6 +1013,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
let mut associated_types = BTreeSet::default(); let mut associated_types = BTreeSet::default();
for tr in traits::elaborate_trait_ref(tcx, principal) { for tr in traits::elaborate_trait_ref(tcx, principal) {
debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr);
match tr { match tr {
ty::Predicate::Trait(pred) => { ty::Predicate::Trait(pred) => {
associated_types.extend(tcx.associated_items(pred.def_id()) associated_types.extend(tcx.associated_items(pred.def_id())
@ -1020,9 +1021,32 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
.map(|item| item.def_id)); .map(|item| item.def_id));
} }
ty::Predicate::Projection(pred) => { ty::Predicate::Projection(pred) => {
// Include projections defined on supertraits. // 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)) projection_bounds.push((pred, DUMMY_SP))
} }
}
_ => () _ => ()
} }
} }

View File

@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Def::Local(id) | Def::Upvar(id, ..) => { Def::Local(id) | Def::Upvar(id, ..) => {
Some(self.tcx.hir.span(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 { if let Some(span) = def_span {
let label = match (unit_variant, inner_callee_path) { let label = match (unit_variant, inner_callee_path) {

View File

@ -98,7 +98,8 @@ use rustc::mir::interpret::{ConstValue, GlobalId};
use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs,
UserSelfTy, UserSubsts}; UserSelfTy, UserSubsts};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; 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::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable; use rustc::ty::fold::TypeFoldable;
use rustc::ty::query::Providers; 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); fcx.resolve_generator_interiors(def_id);
for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) { 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.require_type_is_sized(ty, span, code);
} }
fcx.select_all_obligations_or_error(); fcx.select_all_obligations_or_error();
@ -3221,8 +3223,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
return_expr_ty); return_expr_ty);
} }
// A generic function for checking the then and else in an if // A generic function for checking the 'then' and 'else' clauses in an 'if'
// or if-else. // or 'if-else' expression.
fn check_then_else(&self, fn check_then_else(&self,
cond_expr: &'gcx hir::Expr, cond_expr: &'gcx hir::Expr,
then_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 // we don't look at stability attributes on
// struct-like enums (yet...), but it's definitely not // struct-like enums (yet...), but it's definitely not
// a bug to have construct one. // a bug to have constructed one.
if adt_kind != ty::AdtKind::Enum { if adt_kind != AdtKind::Enum {
tcx.check_stability(v_field.did, Some(expr_id), field.span); 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. // to work in stable even if the Sized bound on `drop` is relaxed.
for i in 0..fn_sig.inputs().skip_binder().len() { 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, self.require_type_is_sized_deferred(input, expr.span,
traits::SizedArgumentType); 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. // Here we want to prevent struct constructors from returning unsized types.
// There were two cases this happened: fn pointer coercion in stable // There were two cases this happened: fn pointer coercion in stable
// and usual function call in presense of unsized_locals. // 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); 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); }).unwrap_or(false);
let mut new_def = def; let mut new_def = def;
let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def { let (def_id, ty) = match def {
Def::SelfCtor(impl_def_id) => {
let ty = self.impl_self_ty(span, impl_def_id).ty; let ty = self.impl_self_ty(span, impl_def_id).ty;
let adt_def = ty.ty_adt_def();
match ty.ty_adt_def() { match adt_def {
Some(adt_def) if adt_def.is_struct() => { Some(adt_def) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant(); let variant = adt_def.non_enum_variant();
new_def = Def::StructCtor(variant.did, variant.ctor_kind); new_def = Def::StructCtor(variant.did, variant.ctor_kind);
(variant.did, self.tcx.type_of(variant.did)) (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) (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 // The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme. // escaping late-bound regions, and nor should the base type scheme.
let ty = self.tcx.type_of(def_id); let ty = self.tcx.type_of(def_id);
(def_id, ty) (def_id, ty)
}
}; };
let substs = AstConv::create_substs_for_generic_args( let substs = AstConv::create_substs_for_generic_args(

View File

@ -283,7 +283,7 @@ nav.sub {
padding-left: 0; padding-left: 0;
} }
:not(.source) .example-wrap { .rustdoc:not(.source) .example-wrap {
display: inline-flex; display: inline-flex;
margin-bottom: 10px; margin-bottom: 10px;
} }
@ -301,11 +301,11 @@ nav.sub {
text-align: right; text-align: right;
} }
:not(.source) .example-wrap > pre.rust { .rustdoc:not(.source) .example-wrap > pre.rust {
width: 100%; width: 100%;
} }
body:not(.source) .example-wrap > pre { .rustdoc:not(.source) .example-wrap > pre {
margin: 0; margin: 0;
} }

View File

@ -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 // Uses libsyntax to parse the doctest and find if there's a main fn and the extern
// crate already is included. // 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::{ast, parse::{self, ParseSess}, source_map::FilePathMapping};
use crate::syntax_pos::FileName; use crate::syntax_pos::FileName;
use errors::emitter::EmitterWriter; use errors::emitter::EmitterWriter;
@ -415,6 +415,7 @@ pub fn make_test(s: &str,
let mut found_main = false; let mut found_main = false;
let mut found_extern_crate = cratename.is_none(); 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) { let mut parser = match parse::maybe_new_parser_from_source_str(&sess, filename, source) {
Ok(p) => p, Ok(p) => p,
@ -423,7 +424,7 @@ pub fn make_test(s: &str,
err.cancel(); 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 { if found_main && found_extern_crate {
break; 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 // Don't inject `extern crate std` because it's already injected by the
// compiler. // compiler.
if !already_has_extern_crate && !opts.no_crate_inject && cratename != Some("std") { 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); let output = make_test(input, Some("asdf"), false, &opts);
assert_eq!(output, (expected, 3)); 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));
}
} }

View File

@ -459,10 +459,7 @@ declare_features! (
// Support for arbitrary delimited token streams in non-macro attributes // Support for arbitrary delimited token streams in non-macro attributes
(active, unrestricted_attribute_tokens, "1.30.0", Some(55208), None), (active, unrestricted_attribute_tokens, "1.30.0", Some(55208), None),
// Allows `use x::y;` to resolve through `self::x`, not just `::x` // Allows unsized rvalues at arguments and parameters.
(active, uniform_paths, "1.30.0", Some(53130), None),
// Allows unsized rvalues at arguments and parameters
(active, unsized_locals, "1.30.0", Some(48055), None), (active, unsized_locals, "1.30.0", Some(48055), None),
// #![test_runner] // #![test_runner]
@ -689,6 +686,8 @@ declare_features! (
(accepted, self_struct_ctor, "1.32.0", Some(51994), None), (accepted, self_struct_ctor, "1.32.0", Some(51994), None),
// `Self` in type definitions (RFC 2300) // `Self` in type definitions (RFC 2300)
(accepted, self_in_typedefs, "1.32.0", Some(49303), None), (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 // If you change this, please modify `src/doc/unstable-book` as well. You must

View File

@ -1,4 +1,4 @@
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # 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 # 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. # build bots then the contents should be changed so git updates the mtime.
2018-11-28 2018-12-13

View File

@ -12,8 +12,8 @@
# source tarball for a stable release you'll likely see `1.x.0` for rustc and # 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`. # `0.x.0` for Cargo where they were released on `date`.
date: 2018-12-06 date: 2018-12-20
rustc: 1.31.0 rustc: 1.31.1
cargo: 0.32.0 cargo: 0.32.0
# When making a stable release the process currently looks like: # When making a stable release the process currently looks like:

View 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